|
|
1.1 ! root 1: number.c: ! 2: ! 3: /* Copyright 1990, AT&T Bell Labs */ ! 4: ! 5: /* Canonicalize the number string pointed to by dp, of length ! 6: len. Put the result in kp. ! 7: ! 8: A field of length zero, or all blank, is regarded as 0. ! 9: Over/underflow is rendered as huge or zero and properly signed. ! 10: It happens 1e+-1022. ! 11: ! 12: Canonicalized strings may be compared as strings of unsigned ! 13: chars. For good measure, a canonical string has no zero bytes. ! 14: ! 15: Syntax: optionally signed floating point, with optional ! 16: leading spaces. A syntax deviation ends the number. ! 17: ! 18: Form of output: packed in 4-bit nibbles. First ! 19: 3 nibbles count the number N of significant digits ! 20: before the decimal point. The quantity actually stored ! 21: is 2048+sign(x)*(N+1024). Further nibbles contain ! 22: 1 decimal digit d each, stored as d+2 if x is positive ! 23: and as 10-d if x is negative. Leading and trailing ! 24: zeros are stripped, and a trailing "digit" d = -1 ! 25: is appended. (The trailing digit handled like all others, ! 26: so encodes as 1 or 0xb according to the sign of x.) ! 27: An odd number of nibbles is padded with zero. ! 28: ! 29: Buglet: overflow is reported if output is exactly filled. ! 30: ! 31: */ ! 32: #include "fsort.h" ! 33: ! 34: #define encode(x) (neg? 10-(x): (x)+2) ! 35: #define putdig(x) (nib? (*dig=encode(x)<<4, nib=0): \ ! 36: (*dig++|=encode(x), nib=1)) ! 37: ! 38: static int gflag; ! 39: ! 40: int ! 41: gcode(uchar *dp, uchar*kp, int len, struct field *f) ! 42: <60>{ ! 43: int ret; ! 44: <60>gflag++; ! 45: <60>ret = ncode(dp, kp, len, f); ! 46: <60>gflag--; ! 47: return <60>ret; ! 48: } ! 49: ! 50: int ! 51: ncode(uchar *dp, uchar*kp, int len, struct field *f) ! 52: <374264>{ ! 53: uchar *dig = <374264>kp + 1; /* byte for next digit */ ! 54: int nib = <374264>0; /* high nibble 1, low nibble 0 */ ! 55: uchar *cp = <374264>dp; ! 56: uchar *ep = <374264>cp + len; /* end pointer */ ! 57: int zeros = <374264>0; /* count zeros seen but not installed */ ! 58: int sigdig = <374264>1024; ! 59: int neg = <374264>f->rflag; /* 0 for +, 1 for - */ ! 60: int decimal = <374264>0; ! 61: int n, inv; ! 62: ! 63: <374264>kp[1] = 0; ! 64: for( <374264>; <418322>cp<ep ; <44058>cp++) /* eat blanks */ ! 65: if(<418322>*cp!=' ' && <374272>*cp!='\t') ! 66: <374264>break; ! 67: if(<374264>cp < ep) /* eat sign */ ! 68: switch(<374264>*cp) { ! 69: case '-': ! 70: <218>neg ^= 1; ! 71: case '+': ! 72: <225>cp++; ! 73: } ! 74: for( <374264>; <707527>cp<ep; <333263>cp++) /* eat leading zeros */ ! 75: if(<707511>*cp != '0') ! 76: <374248>break; ! 77: if(<374264>*cp=='.' && <331112>cp<ep) { /* decimal point among lead zeros */ ! 78: <331112>decimal++; ! 79: for(<331112>cp++; <367735>cp<ep; <36623>cp++) { ! 80: if(<367735>*cp != '0') ! 81: <331112>break; ! 82: <36623>sigdig--; ! 83: } ! 84: } ! 85: if(<374264>*cp>'9' || <374255>*cp<'0' || <373799>cp>=ep) { /* no sig digit*/ ! 86: <465>sigdig = 0; ! 87: <465>neg = 0; ! 88: <465>goto retzero; ! 89: } ! 90: for( <373799>; <2405784>cp<ep; <2031985>cp++) { ! 91: switch(<2071744>*cp) { ! 92: default: ! 93: <39726>goto out; ! 94: case '.': ! 95: if(<16>decimal) ! 96: <2>goto out; ! 97: <14>decimal++; ! 98: <14>continue; ! 99: case '0': ! 100: <132382>zeros++; ! 101: if(<132382>!decimal) ! 102: <3976>sigdig++; ! 103: <132382>continue; ! 104: case '1': case '2': case '3': case '4': case '5': ! 105: case '6': case '7': case '8': case '9': ! 106: for( <1899589>; <2027985>zeros>0; <128396>zeros--) ! 107: <128396>putdig<65793>(0); ! 108: <1899589>n = *cp - '0'; ! 109: <1899589>putdig<929380>(n); ! 110: if(<1899589>!decimal) ! 111: <77803>sigdig++; ! 112: <1899589>continue; ! 113: case 'e': ! 114: case 'E': ! 115: if(<31>!gflag) ! 116: <6>goto out; ! 117: <25>inv = 1; ! 118: if(<25>cp < ep) switch(<25>*++cp) { ! 119: case '-': ! 120: <13>inv = -1; ! 121: case '+': ! 122: <15>cp++; ! 123: } ! 124: if(<25>*cp>'9' || <25>*cp<'0' || <21>cp>=ep) ! 125: <4>goto out; ! 126: for(<21>n=0; <62>cp<ep; <41>cp++) { ! 127: int c = <44>*cp; ! 128: if(<44>c<'0' || <44>c>'9') ! 129: <3>break; ! 130: if(<41>(n = 10*n+c-'0') >= 0) ! 131: <41>continue; ! 132: <0>sigdig = 2047*inv; ! 133: <0>goto out; ! 134: } ! 135: <21>sigdig += n*inv; ! 136: <21>goto out; ! 137: } ! 138: } ! 139: out: ! 140: if(<373799>sigdig<0 || <373799>sigdig>=2047) { ! 141: <0>sigdig = sigdig<0? <0>0: <0>2047; ! 142: <0>warn("numeric field overflow", (char*)dp, len); ! 143: <0>dig = kp + 1; ! 144: <0>*dig = 0; ! 145: <0>nib = 0; ! 146: } ! 147: retzero: ! 148: if(<374264>neg) ! 149: <219>sigdig = 2048 - sigdig; ! 150: else ! 151: <374045>sigdig = 2048 + sigdig; ! 152: <374264>kp[0] = sigdig >> 4; ! 153: <374264>kp[1] |= sigdig << 4; ! 154: <374264>putdig<37639>(-1); ! 155: return <374264>dig - kp + 1 - nib; ! 156: } ! 157: rsort.c: ! 158: ! 159: /* Copyright 1990, AT&T Bell Labs */ ! 160: #include "fsort.h" ! 161: ! 162: /* Radix sort by bytes. Records are chained in a list. ! 163: There are up to 257 bins at each recursion level. ! 164: The "null bin" is for short strings that have run out; ! 165: the rest are for byte values 0-255 */ ! 166: ! 167: int aflag = 0; ! 168: int uflag = 0; ! 169: int rflag = 0; ! 170: int sflag = 0; ! 171: ! 172: /* Sort the list s by distributing according to ! 173: digit d into an array of bins, sorting the bins ! 174: recursively, and re-collecting them back into the list. ! 175: If uflag is nonzero return only 1 representative of ! 176: each equivalence class. The squeeze step noted ! 177: below determines what bins are in use, and squeezes ! 178: those into a stack frame, which is contiguous to s. ! 179: The null bin is handled separately to cut the span ! 180: of the squeeze loop. ! 181: Precondition: length(s) > 1 */ ! 182: ! 183: #define tiebreak(t) \ ! 184: if(uflag) { \ ! 185: t->tail = !aflag? t->head: \ ! 186: listaccum(t->head, t->tail); \ ! 187: t->tail->next = 0; \ ! 188: } else if(keyed && !sflag && t->head->next) { \ ! 189: rflag = fields[0].rflag; \ ! 190: keyed = 0; \ ! 191: sort(t, 0); \ ! 192: keyed = 1; \ ! 193: rflag = 0; \ ! 194: } else ! 195: ! 196: void ! 197: sort(struct list *s, int d) ! 198: <126745>{ ! 199: extern int uflag; ! 200: struct list *t; ! 201: struct rec *r, *q; ! 202: struct list *frame = <126745>s + 1; /* stack frame */ ! 203: static struct list bins[257]; ! 204: # define nullbin (bins+256) ! 205: int nbin; /* number of filled bins */ ! 206: struct list *low; /* lowest unsorted nonnull bin */ ! 207: loop: ! 208: <447576>r = s->head; ! 209: <447576>low = bins + 256; ! 210: <447576>nbin = 0; ! 211: while(<3688466>r) { ! 212: if(<3240890>keyed) ! 213: if(<1334292>r->klen > (len_t)d) ! 214: <1116270>t = bins + key(r)[d]; ! 215: else ! 216: <218022>t = nullbin; ! 217: else ! 218: if(<1906598>r->dlen > (len_t)d) ! 219: <1714238>t = bins + data(r)[d]; ! 220: else ! 221: <192360>t = nullbin; ! 222: if(<3240890>t->head == 0) { ! 223: if(<555902>low > t) ! 224: <363502>low = t; ! 225: <555902>t->head = r; ! 226: <555902>nbin++; ! 227: } else ! 228: <2684988>t->tail->next = r; /* stable sort */ ! 229: <3240890>t->tail = r; ! 230: <3240890>r = r->next; ! 231: } ! 232: <447576>t = frame; /* t is stack top */ ! 233: if(<447576>t+nbin > stackmax) ! 234: <0>fatal("stack overflow", "", 0); ! 235: # define push(b) /* onto stack */ \ ! 236: *t = *b, \ ! 237: t->tail->next = 0, \ ! 238: t++, \ ! 239: b->head = 0, \ ! 240: nbin-- ! 241: if(<447576>nullbin->head) ! 242: <106517>push(nullbin); ! 243: for( <447576>; <1381435>nbin>0; <933859>low++) ! 244: if(<933859>low->head) ! 245: <449385>push(low); ! 246: if(<447576>t == frame+1) { /* tail recursion */ ! 247: /* debug(frame, t, d);*/ ! 248: <427056>r = frame->head; ! 249: if(<427056>r->len[keyed] <= d) { ! 250: <106225>tiebreak(<26635>frame); ! 251: <106225>*s = *frame; ! 252: return<106225>; /* string ran out */ ! 253: } ! 254: <320831>d++; ! 255: <320831>goto loop; ! 256: } ! 257: /* debug(frame, t, d);*/ ! 258: <20520>t--; ! 259: if(<20520>t->head->next) /* skip 1-item list */ ! 260: <13713>sort(t, d+1); ! 261: if(<20520>!rflag) { /* forward order */ ! 262: <15796>r = t->tail; ! 263: while(<112441>t > frame) { ! 264: <96645>q = t->head; ! 265: if(<96645>(--t>frame || <15796>t->head->len[keyed]>d) ! 266: && <96353>t->head->next) ! 267: <82209>sort(t, d+1); ! 268: else if(<14436>t==frame) ! 269: <3163>tiebreak(t);<295> ! 270: <96645>t->tail->next = q; /* concatenate */ ! 271: } ! 272: <15796>s->head = frame->head; ! 273: <15796>s->tail = r; ! 274: } else { /* reverse order */ ! 275: <4724>r = t->head; ! 276: while(<16405>t > frame) { ! 277: <11681>q = t->tail; ! 278: if(<11681>(--t>frame || <4724>t->head->len[keyed]>d) ! 279: && <11681>t->head->next) ! 280: <4070>sort(t, d+1); ! 281: else if(<7611>t==frame) ! 282: <3881>tiebreak(t);<1360> ! 283: <11681>q->next = t->head; /* concatenate */ ! 284: } ! 285: <4724>s->head = r; ! 286: <4724>s->tail = frame->tail; ! 287: } ! 288: /* printf("return\n"); debug(s,s+1,d);*/ ! 289: <20520>} ! 290: ! 291: /* ! 292: debug(struct list *stack, struct list *top, int d) ! 293: { ! 294: printf("----------------------level %d\n", d); ! 295: while(stack<top) { ! 296: printout(stack->head, stdout, "stdout"); ! 297: printf("----------------------\n"); ! 298: stack++; ! 299: } ! 300: } ! 301: */ ! 302: merge.c: ! 303: ! 304: /* Copyright 1990, AT&T Bell Labs */ ! 305: #include <stdlib.h> ! 306: #include <string.h> ! 307: #include "fsort.h" ! 308: ! 309: char *disorder = "key out of order"; ! 310: char *duplicate = "duplicate key"; ! 311: char *space = "out of space for merging"; ! 312: ! 313: enum { IEOF, IOK }; ! 314: enum { IPRE = 01000, IFOL = 02000 }; /* see find() */ ! 315: enum { NMERGE = 16 }; ! 316: ! 317: int nmerge = NMERGE; /* max number of files to merge at once */ ! 318: int nextfile; ! 319: ! 320: struct merge { /* current record in an open file */ ! 321: char *name; /* name of file (for diagnostics) */ ! 322: FILE *file; ! 323: struct rec *rec; /* pointer to the data (and key) */ ! 324: short serial; /* file no., breaks ties for stable sort */ ! 325: short del; /* delete at close */ ! 326: }; ! 327: ! 328: struct merge *mfile; /* one struct per open file */ ! 329: struct merge **f; /* pointers to mfile, ordered by content */ ! 330: ! 331: static void mergephase(int, char*); ! 332: static int find(int, int*); ! 333: static int fillrec(struct merge*); ! 334: static int compare(struct merge*, struct merge*); ! 335: static void syncerr(struct merge*, char*); ! 336: extern int link(char*, char*); ! 337: extern int unlink(char*); ! 338: static void recinit(int nf, int nm, int n); ! 339: static void mv(int, int); ! 340: ! 341: static void ! 342: recalloc(struct merge *m) ! 343: <1241>{ ! 344: if(<1241>m->rec) ! 345: return<784>; /* hygiene; doesn't happen */ ! 346: <457>m->rec = (struct rec*)malloc(MINREC); ! 347: if(<457>m->rec == 0) ! 348: <0>fatal(space, "", 0); ! 349: <457>m->rec->dlen = 0; ! 350: <457>m->rec->next = (struct rec*)((uchar*)m->rec + MINREC); ! 351: <457>} ! 352: ! 353: /* misfortune : all fields are parsed and converted ! 354: before comparison. Lazy parsing might be in order, ! 355: but it's too hard to contemplate */ ! 356: ! 357: /* Merge strategy, to merge N inputs in groups of at most M. ! 358: Numbers, like (1), are keyed to comments in code. ! 359: If N <= M, merge everything. (4) ! 360: If N > M*(M-1)+1 ! 361: greedily merge M at a time (1) to reduce to the next case. ! 362: Merge x bunches of M (3) and one bunch of y (2), ! 363: then merge the x+1 new files (4) with the remaining z files ! 364: in an exactly M-way merge. Calculate x,y,z thus: ! 365: Mx + y + z = N file count ! 366: x + 1 + z = M final merge ! 367: 2 <= y <= M ! 368: x >= 0 ! 369: z >= 0 ! 370: by algebra ! 371: (M-1)x + y = N-M+1 ! 372: y == (N-M+1) mod (M-1), 2 <= y <= M ! 373: x == (n-M+1-y)/(M-1) ! 374: Total cost is Mx + y + N. (Strategy due to P. McIlroy.) */ ! 375: ! 376: /* merge n files. the first unmerged temp file is nm (i.e. ! 377: nm is the number of already merged files). the first ! 378: unmerged input file is nf. ! 379: rename temp files to keep a dense set beginning at 0 ! 380: (It seems silly to rename 100 files after merging ! 381: every 1; how much time does that actually cost?) */ ! 382: void ! 383: merge1(int nf, int nm, int n) ! 384: <161>{ ! 385: char *name; ! 386: int i, j; ! 387: int flag = <161>nf<nfiles; ! 388: <161>recinit(nf, nm, n); ! 389: <161>name = filename(nextfile++); ! 390: <161>mergephase(n, name); ! 391: <161>free(name); ! 392: if(<161>flag) ! 393: return<137>; ! 394: <24>mv(--nextfile, nm); ! 395: for(<24>i=nm+n, j=nm+1; <180>i<nextfile; <156>i++, j++) ! 396: <156>mv(i, j); ! 397: <24>nextfile -= n - 1; ! 398: <24>} ! 399: ! 400: /* if flag = 0 merge input files; else temps only. ! 401: this program is specialized to two levels of merge; ! 402: should fix that some day. */ ! 403: ! 404: void ! 405: merge(int flag) ! 406: <68>{ ! 407: char buf[BUFSIZ]; ! 408: FILE *input, *output; ! 409: int n, y; ! 410: char *name; ! 411: int nf = <68>0; /* next input file to merge */ ! 412: int nm = <68>0; /* total already merged once */ ! 413: int nt = <68>nfiles; /* files as yet unmerged */ ! 414: if(<68>flag) { ! 415: <21>nf = nfiles; ! 416: <21>nt = nextfile; ! 417: } ! 418: if(<68>mfile == 0) ! 419: <49>mfile = (struct merge*)calloc(nmerge+1, ! 420: sizeof(*mfile)); ! 421: if(<68>f == 0) ! 422: <49>f = (struct merge**)calloc(nmerge+1, ! 423: sizeof(*f)); ! 424: if(<68>mfile==0 || <68>f==0) ! 425: <0>fatal(space,"",0); ! 426: ! 427: if(<68>nt > nmerge*(nmerge-1)+1) { /* (1) */ ! 428: for(<19>nm=0; <135>nt>0; <116>) { ! 429: <116>n = nt>nmerge? <97>nmerge: <19>nt; ! 430: <116>merge1(nf, nm, n); ! 431: if(<116>flag) <0>nf += n; ! 432: <116>nt -= n; ! 433: <116>nm++; ! 434: } ! 435: <19>merge(1); ! 436: return<19>; ! 437: } ! 438: if(<49>nt > nmerge) { /* (2) */ ! 439: <30>y = (nt-nmerge+1)%(nmerge-1); ! 440: if(<30>y <= 1) <14>y += nmerge-1; ! 441: <30>merge1(nf, nm, y); ! 442: <30>nf = nf+y>=nfiles? <18>nfiles: <12>nf+y; ! 443: <30>nt -= y; ! 444: <30>nm++; ! 445: } ! 446: while(<64>nt+nm > nmerge) { /* (3) */ ! 447: <15>merge1(nf, nm, nmerge); ! 448: <15>nf = nf+nmerge>=nfiles? <6>nfiles: <9>nf+nmerge; ! 449: <15>nt -= nmerge; ! 450: <15>nm++; ! 451: } ! 452: ! 453: <49>n = nm+nt; /* (4) */ ! 454: <49>recinit(nf, 0, n); ! 455: if(<49>!overwrite(nf)) ! 456: <46>name = oname; ! 457: else ! 458: <3>name = filename(nextfile++); ! 459: <49>mergephase(n, name); ! 460: if(<48>name == oname) ! 461: return<45>; ! 462: <3>input = fileopen(name, "r"); ! 463: <3>output = fileopen(oname, "w"); ! 464: while(<88>n = fread(buf, 1, sizeof(buf), input)) ! 465: if(<85>fwrite(buf, 1, n, output) != n) ! 466: <0>fatal("error writing", oname, 0); ! 467: <3>fileclose(input, name); ! 468: <3>unlink(name); ! 469: <3>free(name); ! 470: <3>fileclose(output, oname); ! 471: <3>} ! 472: ! 473: /* Initialize merge records for n files, beginning with ! 474: input file number nf and temp file number nm. ! 475: ! 476: There are nfiles-nf input files; any files beyond that ! 477: number must be temporaries, which come from already ! 478: merged inputs. (The only time that both kinds of ! 479: files are present is the very last merge, when for ! 480: stability, the temps are regarded as earlier.) */ ! 481: ! 482: static void ! 483: recinit(int nf, int nm, int n) ! 484: <210>{ ! 485: int i; ! 486: struct merge *m; ! 487: int last = <210>nfiles-nf + nextfile-nm == n; ! 488: for(<210>i=0; <1277>i<=n; <1067>i++) /* one extra, for mergephase() */ ! 489: <1067>recalloc(&mfile[i]); ! 490: for(<210>i=0; <1067>i<n; <857>i++) { ! 491: <857>m = &mfile[i]; ! 492: <857>m->del = nf>=nfiles || <635>last && <126>i<nextfile; ! 493: <857>m->name = m->del? <243>filename(nm++): <614>files[nf++]; ! 494: <857>m->file = fileopen(m->name, "r"); ! 495: <857>m->serial = i; ! 496: <857>f[i] = m; ! 497: } ! 498: <210>f[n] = &mfile[n]; ! 499: <210>} ! 500: ! 501: static void ! 502: mv(int i, int j) ! 503: <180>{ ! 504: char *old, *new; ! 505: if(<180>i == j) return<0>; /* believed not to happen */ ! 506: <180>old = filename(i); ! 507: <180>new = filename(j); ! 508: <180>unlink(new); ! 509: if(<180>link(old,new) == -1 || <180>unlink(old) == -1) ! 510: <0>fatal("cannot move", old, 0); ! 511: <180>free(old); ! 512: <180>free(new); ! 513: <180>} ! 514: ! 515: static void ! 516: emit(FILE *output) ! 517: <22296>{ ! 518: struct merge *m = <22296>f[0]; ! 519: int n = <22296>m->rec->dlen; ! 520: uchar *p = <22296>data(m->rec); /* hanky panky for speed */ ! 521: uchar *e = <22296>p + n++; /* use fwrite instead of */ ! 522: int c = <22296>*e; /* printf */ ! 523: <22296>*e = '\n'; ! 524: if(<22296>fwrite((char*)p, 1, n, output) != n) ! 525: <0>fatal("error writing", m->name, 0); ! 526: <22296>*e = c; ! 527: <22296>} ! 528: ! 529: /* Merge files in mfile[0]..mfile[n-1]. ! 530: f[0]..f[l-1] points to files in increasing order ! 531: of their current records. All the current records ! 532: are strictly ordered, either by tie-breaking, or ! 533: by skipping records that compare equal under -u. ! 534: There are two phases: (a) initialization (reading ! 535: from a file when there is no record at hand) and ! 536: (b) continuation (reading the next record with the ! 537: intent of displacing the current record). ! 538: These conditions arise, at places numbered in comments ! 539: (1) the record compares equal to another, and would follow ! 540: that other if ties were broken ! 541: (2) the record compares equal to another, and would precede ! 542: that other if ties were broken ! 543: (3) the record falls between two others ! 544: ! 545: At all times the keys pointed to by f[0]..f[l] ! 546: are distinct (perhaps due to tie-breaking), as ! 547: are the files they come from. When a new key ! 548: is read, its proper home (in tie-broken order) ! 549: is between f[j-1] and f[j]. ! 550: The picture below shows the hardest case (2b), ! 551: where key a from file F is about to be emitted. ! 552: All keys in the sequence axby are distinct, as ! 553: are the files they come from. A new key is read ! 554: from file F into the extra space pointed to by ! 555: f[i]. (Keeping one extra key allows disorder to ! 556: be detected almost for free.) The ! 557: new key is equal to key b pointed to by f[j] ! 558: and file F precedes file G in stability order. ! 559: Thus b(F) deserves to be kept and b(G) discarded. ! 560: 0 j l=n ! 561: -------------------------------------------- ! 562: | a(F) | x | b(G) | y | b(F) | ! 563: -------------------------------------------- ! 564: ! 565: We emit the record at 0, and displace the key ! 566: at j, from whose file there is now no record ! 567: present; l decreases by one. ! 568: 0 j l n ! 569: -------------------------------------------- ! 570: | x | b(F) | y | ?(G) | | ! 571: -------------------------------------------- ! 572: ! 573: This takes us back to initialization. From ! 574: this configuration it is possible to reach ! 575: case (2a), like (2b) except that the key at 0 ! 576: is not to be emitted; (2a) cannot happen during ! 577: the original initialization. ! 578: */ ! 579: ! 580: #define moveup(a,n) memmove(a+1, a, (n)*sizeof(*a)) ! 581: #define movedown(a,n) memmove(a-1, a, (n)*sizeof(*a)) ! 582: ! 583: static void ! 584: mergephase(int n, char *name) ! 585: <210>{ ! 586: int j, flags; ! 587: struct merge *mp; ! 588: struct rec *r; ! 589: int l = <210>0; ! 590: int k = <210>-1; /* for spotting sync errors */ ! 591: FILE *output = fileopen(<210>name, "w"); ! 592: init: while(<19606>l < n) { /*(a)*/ ! 593: <19124>mp = f[l]; ! 594: if(<19124>fillrec(mp) == IEOF) { ! 595: <52>movedown(f+l+1, n-l); ! 596: <52>f[n--] = mp; ! 597: <52>continue; ! 598: } ! 599: <19072>j = find(l, &flags); ! 600: if(<19072>j <= k) ! 601: <0>syncerr(mp, disorder); ! 602: if(<19072>flags & IFOL) { /*(1a)*/ ! 603: if(<17234>!aflag || <17169>doaccum(f[j-1]->rec, mp->rec)) ! 604: <17234>continue; ! 605: } else if(<1838>flags & IPRE) /*(2a)*/ ! 606: if(<761>!aflag || <758>doaccum(mp->rec, f[j]->rec)) { ! 607: <761>f[l] = f[j]; ! 608: <761>f[j] = mp; ! 609: <761>k = j; ! 610: <761>continue; ! 611: } ! 612: <1077>moveup(f+j, l-j); /*(3a)*/ ! 613: <1077>f[j] = mp; ! 614: <1077>l++; ! 615: } ! 616: while(<24714>n > 0) { /*(b)*/ ! 617: <24505>mp = f[l]; ! 618: <24505>r = mp->rec; ! 619: <24505>*mp = *f[0]; ! 620: <24505>mp->rec = r; ! 621: if(<24505>fillrec(mp) == IEOF) { ! 622: <803>emit(output); ! 623: <803>mp = f[0]; ! 624: <803>movedown(f+1, l); ! 625: <803>f[--n] = mp; ! 626: <803>l = n; ! 627: <803>continue; ! 628: } ! 629: <23702>j = find(l, &flags); ! 630: if(<23702>j == 0) ! 631: <1>syncerr(mp, disorder); ! 632: if(<23701>flags & IFOL) { /*(1b)*/ ! 633: if(<2208>!aflag || <1906>doaccum(f[j-1]->rec, mp->rec)) ! 634: <2208>continue; ! 635: } else if(<21493>flags & IPRE) /*(2b)*/ ! 636: if(<272>!aflag || <107>doaccum(mp->rec, f[j]->rec)) { ! 637: <272>emit(output); ! 638: <272>f[l] = f[j]; ! 639: <272>f[j] = mp; ! 640: <272>mp = f[0]; ! 641: <272>movedown(f+1, l); ! 642: <272>f[l--] = mp; ! 643: <272>k = j - 1; ! 644: <272>goto init; ! 645: } ! 646: <21221>emit(output); /*(3b)*/ ! 647: <21221>mp = f[0]; ! 648: <21221>movedown(f+1, j-1); ! 649: <21221>f[j-1] = f[l]; ! 650: <21221>f[l] = mp; ! 651: } ! 652: ! 653: <209>fileclose(output, name); ! 654: <209>} ! 655: ! 656: static int ! 657: fillrec(struct merge *mp) ! 658: <284696>{ ! 659: struct rec *r = <284696>getline(mp->rec, mp->file); ! 660: if(<284696>r == 0) ! 661: return <283702>IOK; ! 662: if(<994>r == ENDFILE) { ! 663: <937>fileclose(mp->file, mp->name); ! 664: if(<937>mp->del) ! 665: <243>unlink(mp->name); ! 666: return <937>IEOF; ! 667: } ! 668: <57>mp->rec = r; ! 669: return <57>IOK; ! 670: } ! 671: ! 672: /* ! 673: Return the proper index for the extra record f[l] ! 674: to be inserted before (regardless of -u). ! 675: Under -u, if the extra record is a duplicate, return ! 676: the index flagged by IFOL or IPRE according as ! 677: the insertion position follows or precedes a ! 678: record of the same value. ! 679: */ ! 680: ! 681: static int ! 682: find(int l, int *flags) ! 683: <42774>{ ! 684: int i, t; ! 685: int bot = <42774>0; ! 686: int top = <42774>l; ! 687: while(<145791>bot < top) { ! 688: <123492>i = (bot+top)/2; ! 689: <123492>t = compare(f[l], f[i]); ! 690: if(<123492>t < 0) ! 691: <55383>top = i; ! 692: else if(<68109>t > 0) ! 693: <39369>bot = i + 1; ! 694: else if(<28740>uflag) { ! 695: if(<20475>f[l]->serial < f[i]->serial) { ! 696: <1033>*flags = IPRE; ! 697: return <1033>i; ! 698: } else { ! 699: <19442>*flags = IFOL; ! 700: return <19442>i + 1; ! 701: } ! 702: } ! 703: else if(<8265>f[l]->serial < f[i]->serial) ! 704: <2917>top = i; ! 705: else ! 706: <5348>bot = i + 1; ! 707: } ! 708: <22299>*flags = 0; ! 709: return <22299>top; ! 710: } ! 711: ! 712: static int ! 713: compare(struct merge *mi, struct merge *mj) ! 714: <364393>{ ! 715: uchar *ip, *jp; ! 716: uchar *ei, *ej; ! 717: uchar *trans, *keep; ! 718: int li, lj, k; ! 719: if(<364393>simplekeyed) { ! 720: <19>trans = fields->trans; ! 721: <19>keep = fields->keep; ! 722: <19>ip = data(mi->rec); ! 723: <19>jp = data(mj->rec); ! 724: <19>ei = ip + mi->rec->dlen; ! 725: <19>ej = jp + mj->rec->dlen; ! 726: for( <19>; <13>; <13>ip++, jp++) { ! 727: while(<35>ip<ei && <29>!keep[*ip]) <3>ip++; ! 728: while(<35>jp<ej && <29>!keep[*jp]) <3>jp++; ! 729: if(<32>ip>=ei || <26>jp>=ej) <7>break; ! 730: <25>k = trans[*ip] - trans[*jp]; ! 731: if(<25>k != 0) <12>break; ! 732: } ! 733: if(<19>ip<ei && <13>jp<ej) ! 734: return <12>k*signedrflag; ! 735: else if(<7>ip < ei) ! 736: return <1>signedrflag; ! 737: else if(<6>jp < ej) ! 738: return <1>-signedrflag; ! 739: else if(<5>sflag) ! 740: return <4>0; ! 741: } else if(<364374>keyed) { ! 742: <194802>ip = key(mi->rec); ! 743: <194802>jp = key(mj->rec); ! 744: <194802>li = mi->rec->klen; ! 745: <194802>lj = mj->rec->klen; ! 746: for(<194802>k=li<lj?<1091>li:<193711>lj; <901648>--k>=0; <706846>ip++, jp++) ! 747: if(<807963>*ip != *jp) ! 748: <101117>break; ! 749: if(<194802>k < 0) { ! 750: if(<93685>li != lj) ! 751: <0>fatal("theorem disproved","",0); ! 752: if(<93685>sflag) ! 753: return <24419>0; ! 754: } else ! 755: return <101117>*ip - *jp; ! 756: ! 757: } ! 758: <238839>li = mi->rec->dlen; ! 759: <238839>lj = mj->rec->dlen; ! 760: <238839>ip = data(mi->rec); ! 761: <238839>jp = data(mj->rec); ! 762: for(<238839>k=li<lj?<7726>li:<231113>lj; <1907768>--k>=0; <1668929>ip++, jp++) ! 763: if(<1764308>*ip != *jp) ! 764: <95379>break; ! 765: return <238839>(k<0? <143460>li-lj: <95379>*ip-*jp)*signedrflag; ! 766: } ! 767: ! 768: void ! 769: check(char *name) ! 770: <87>{ ! 771: int i, t; ! 772: ! 773: <87>mfile = (struct merge*)calloc(2,sizeof(*mfile)); ! 774: <87>recalloc(&mfile[0]); ! 775: <87>recalloc(&mfile[1]); ! 776: <87>mfile[0].name = mfile[1].name = name; ! 777: <87>mfile[0].file = mfile[1].file = fileopen(name, "r"); ! 778: if(<87>mfile[0].file == 0) ! 779: <0>fatal("can't open ", name, 0); ! 780: ! 781: if(<87>fillrec(&mfile[0]) == IEOF) ! 782: return<3>; ! 783: for(<84>i=1; <240980>fillrec(&mfile[i])!=IEOF; <240896>i^=1) { ! 784: <240901>t = compare(&mfile[i^1], &mfile[i]); ! 785: if(<240901>t>0) ! 786: <4>syncerr(&mfile[i], disorder); ! 787: else if(<240897>t==0 && <138849>uflag) ! 788: <1>syncerr(&mfile[i], duplicate); ! 789: } ! 790: <79>} ! 791: ! 792: static void ! 793: syncerr(struct merge *m, char *message) ! 794: <6>{ ! 795: int n = <6>m->rec->dlen; ! 796: <6>warn("trouble in file", m->name, 0); ! 797: <6>fatal(message, n?<6>(char*)data(m->rec):"", n); ! 798: <0>} ! 799: optiona.c: ! 800: ! 801: #include <float.h> ! 802: #include <math.h> ! 803: #include <ctype.h> ! 804: #include <string.h> ! 805: #include <stdlib.h> ! 806: #include "fsort.h" ! 807: ! 808: /* portability hack for old libc's */ ! 809: #define realloc(p,q) (p?realloc(p,q):malloc(q)) ! 810: ! 811: struct field accum[NF]; ! 812: int naccum; ! 813: ! 814: typedef struct { ! 815: uchar *e; /* last+1st char */ ! 816: signed char s; /* -1 for neg, 1 for pos */ ! 817: char c; /* 1 if + sign, else 0 */ ! 818: char z; /* 1 for leading 0, else 0 */ ! 819: char p; /* nonzero if a decimal point */ ! 820: int f; /* number of digits after dec. pt. */ ! 821: } desc; ! 822: ! 823: #define max(a, b) ((a)>(b)?(a):(b)) ! 824: #define mod10(a) (((a)+20)%10) ! 825: #define div10(a) (((a)+20)/10-2) ! 826: ! 827: /* find least significant digit and other facts about a number ! 828: in field beginning at a and ending just before e */ ! 829: ! 830: desc ! 831: lsd(uchar *a, uchar *e) ! 832: <99690>{ ! 833: desc d = <99690>{ 0, 1, 0, 0, 0, 0 }; ! 834: while(<271072>a<e && <269069>(*a==' '||<97687>*a=='\t')) <171382>a++; ! 835: if(<99690>a >= e) ! 836: <2003>; ! 837: else if(<97687>*a == '-') { ! 838: <7505>d.s = -1; ! 839: <7505>a++; ! 840: } else if(<90182>*a == '+') { ! 841: <3>d.c = 1; ! 842: <3>a++; ! 843: } ! 844: if(<99690>a+1<e && <51891>*a=='0' && <13>isdigit(a[1])) d.z = 1; ! 845: while(<299631>a<e && <199978>isdigit(*a)) ! 846: <199941>a++; ! 847: if(<99690>a<e && <37>*a=='.') { ! 848: <13>d.p = 1; ! 849: while(<38>++a<e && <25>isdigit(*a)) ! 850: <25>d.f++; ! 851: } ! 852: <99690>d.e = a; ! 853: return <99690>d; ! 854: } ! 855: ! 856: /* add the fields at a and b as desc-ribed, ! 857: putting result, with decimal point omitted, ! 858: right justified before re. ! 859: calculates in 10's complement and recomplements ! 860: magnitude if negative. ! 861: set *sgn -1 for neg, 1 for signed +, 0 for unsigned. */ ! 862: ! 863: uchar * ! 864: add(uchar *re, uchar *a, desc ad, uchar *b, desc bd, int *sgn) ! 865: <49845>{ ! 866: int d = <49845>0; ! 867: uchar *t; ! 868: uchar *r = <49845>re; ! 869: while(<49848>ad.f > bd.f) { ! 870: <3>d += (*--ad.e - '0')*ad.s; ! 871: <3>*--re = mod10(d); ! 872: <3>d = div10(d); ! 873: <3>ad.f--; ! 874: } ! 875: while(<49861>bd.f > ad.f) { ! 876: <16>d += (*--bd.e - '0')*bd.s; ! 877: <16>*--re = mod10(d); ! 878: <16>d = div10(d); ! 879: <16>bd.f--; ! 880: } ! 881: while(<220476>ad.e>a || <50616>bd.e>b) { ! 882: if(<170631>ad.f-- == 0) { ! 883: if(<49843>ad.p) ! 884: <6>ad.e--; ! 885: if(<49843>bd.p) ! 886: <7>bd.e--; ! 887: } ! 888: if(<170631>ad.e > a) ! 889: if(<169860>isdigit(*--ad.e)) ! 890: <139640>d += (*ad.e - '0')*ad.s; ! 891: else ! 892: <30220>ad.e = a; ! 893: if(<170631>bd.e > b) ! 894: if(<109780>isdigit(*--bd.e)) ! 895: <60307>d += (*bd.e - '0')*bd.s; ! 896: else ! 897: <49473>bd.e = b; ! 898: <170631>*--re = mod10(d); ! 899: <170631>d = div10(d); ! 900: } ! 901: <49845>*sgn = ad.c | bd.c; ! 902: if(<49845>d > 0) ! 903: <1>*--re = 1; /* happens only on overflow */ ! 904: else if(<49844>d < 0) { ! 905: int x = <4997>10; ! 906: <4997>*sgn = -1; ! 907: for(<4997>t = r; <33242>--t>=re; <28245>) { ! 908: <28245>*t = (x - *t)%10; ! 909: if(<28245>*t != 0) ! 910: <21111>x = 9; ! 911: } ! 912: if(<4997>d < -1) ! 913: <0>*--re = 1; /* hygiene, can't happen */ ! 914: } ! 915: while(<81359>re<r && <79328>*re==0) ! 916: <31514>re++; ! 917: return <49845>re; ! 918: } ! 919: ! 920: int ! 921: fieldaccum(uchar *a, uchar *ae, uchar *b, uchar *be) ! 922: <49845>{ ! 923: static uchar *r, *re; /* not pure ansi (re-r=nil-nil=?) */ ! 924: desc da = <49845>lsd(a, ae); ! 925: desc db = <49845>lsd(b, be); ! 926: int sgn, Sgn, f; ! 927: uchar *v; ! 928: while(<51247>re-r < max(da.e-a+db.f, db.e-b+da.f) <26>+ 1) { ! 929: int l = <1402>re - r + 100; ! 930: <1402>r = (uchar*)<1387>realloc(r, l); ! 931: if(<1402>r == 0) ! 932: <0>fatal("out of space","",0); ! 933: <1402>re = r + l; ! 934: } ! 935: <49845>f = max(da.f, db.f);<3> ! 936: <49845>v = add(re, a, da, b, db, &sgn); ! 937: <49845>Sgn = sgn != 0; ! 938: if(<49845>Sgn+max(re-v,f+1)+<46132>(da.p|<3713>db.p) > ae-a) ! 939: return <1>0; ! 940: while(<49860>re>v && <47829>--f>=0) ! 941: <16>*--ae = *--re + '0'; ! 942: while(<49850>--f >= 0) ! 943: <6>*--ae = '0'; ! 944: if(<49844>da.p | db.p) ! 945: <10>*--ae = '.'; ! 946: if(<49844>re <= v) ! 947: <2031>*--ae = '0'; ! 948: while(<188963>re > v) ! 949: <139119>*--ae = *--re + '0'; ! 950: if(<49844>da.z | db.z) ! 951: while(<16>ae > a+Sgn) ! 952: <9>*--ae = '0'; ! 953: if(<49844>sgn > 0) ! 954: <3>*--ae = '+'; ! 955: else if(<49841>sgn < 0) ! 956: <4997>*--ae = '-'; ! 957: if(<49844>ae<a || <49844>v<r) ! 958: <0>fatal("bug in accumulation","",0); ! 959: while(<93111>ae > a) ! 960: <43267>*--ae = ' '; ! 961: return <49844>1; ! 962: } ! 963: ! 964: void ! 965: chkaccum(struct field *field) ! 966: <34>{ ! 967: if(<34>field->coder == 0) ! 968: <34>field->coder = acode; ! 969: if(<34>field->coder != acode) ! 970: <0>goto bad; ! 971: if(<34>field->trans == 0) ! 972: <33>field->trans = ident; ! 973: if(<34>field->trans != ident) ! 974: <1>goto bad; ! 975: if(<33>field->keep == 0) ! 976: <31>field->keep = all; ! 977: if(<33>field->keep != all) ! 978: <2>goto bad; ! 979: if(<31>field->rflag) ! 980: <1>goto bad; ! 981: return<30>; ! 982: bad: ! 983: <4>fatal("improper modifier with -a","",0); ! 984: return<0>; ! 985: } ! 986: ! 987: /* acode is unlike other coding functions. instead of ! 988: making a key in the place pointed to by op, ! 989: it makes a list of field locations. it might ! 990: be more honest if op were declared void* */ ! 991: ! 992: struct loc { uchar *from, *to; }; ! 993: ! 994: int ! 995: acode(uchar *ip, uchar *op, int len, struct field *f) ! 996: <99690>{ ! 997: struct loc *lp = <99690>(struct loc*)op; ! 998: <99690>lp->from = ip; ! 999: <99690>lp->to = ip + len; ! 1000: if(<99690>!tab && <99690>!f->bflag && ! 1001: <99686>f->begin.fieldno>0 && <99560>f->begin.charno==0) ! 1002: <99556>lp->from++; ! 1003: return <99690>sizeof(*lp); ! 1004: } ! 1005: ! 1006: int ! 1007: doaccum(struct rec *arec, struct rec *brec) ! 1008: <44842>{ ! 1009: int i; ! 1010: struct loc aloc[NF], bloc[NF]; ! 1011: <44842>fieldcode(data(arec), (uchar*)aloc, arec->dlen, ! 1012: (uchar*)-1, accum, naccum); ! 1013: <44842>fieldcode(data(brec), (uchar*)bloc, brec->dlen, ! 1014: (uchar*)-1, accum, naccum); ! 1015: for(<44842>i=0; <94686>i<naccum; <49844>i++) ! 1016: if(<49845>!fieldaccum(aloc[i].from, aloc[i].to, ! 1017: bloc[i].from, bloc[i].to)) { ! 1018: if(<1>i==0) ! 1019: <1>warn("sum too long; record kept: ", ! 1020: (char*)data(brec), brec->dlen); ! 1021: else ! 1022: <0>fatal("sum too long on adding: ", ! 1023: (char*)data(brec), brec->dlen); ! 1024: return <1>0; ! 1025: } ! 1026: return <44841>1; ! 1027: } ! 1028: ! 1029: struct rec * ! 1030: listaccum(struct rec *head, struct rec *tail) ! 1031: <134>{ ! 1032: struct rec *q = <134>head; ! 1033: struct rec *p = <134>head; ! 1034: for(<134>;<24902>;<24902>) { ! 1035: if(<25036>q == tail) ! 1036: <134>break; ! 1037: <24902>q = q->next; ! 1038: if(<24902>doaccum(p, q)) ! 1039: <24901>p->next = q->next; ! 1040: else ! 1041: <1>p = q; ! 1042: } ! 1043: return <134>p; ! 1044: } ! 1045: fsort.c: ! 1046: ! 1047: /* Copyright 1990, AT&T Bell Labs */ ! 1048: #include <stdlib.h> ! 1049: #include <string.h> ! 1050: #include <ctype.h> ! 1051: #include "fsort.h" ! 1052: ! 1053: int mflag = 0; ! 1054: int cflag = 0; ! 1055: int keyed = 0; ! 1056: ! 1057: extern void readin(void); ! 1058: extern void dumptotemp(void); ! 1059: extern void sealstack(struct rec *p); ! 1060: extern void filelist(int, char**); ! 1061: extern int getopt(int, char*const*, const char*); ! 1062: extern char *optarg; ! 1063: extern int optind; ! 1064: ! 1065: FILE *input; ! 1066: char *oname = "-"; ! 1067: char *tname[] = { "/usr/tmp"/*substitutable*/, "/usr/tmp", "/tmp", 0 }; ! 1068: ! 1069: char **files; ! 1070: int nfiles; ! 1071: char *nofiles[] = { "-", 0 }; ! 1072: ! 1073: main(int argc, char **argv) ! 1074: <311>{ ! 1075: int c, n; ! 1076: static char s[3] = { '-' }; ! 1077: for(<311>;<590>;<590>) { ! 1078: if(<901>optind<argc && <873>argv[optind][0]=='+' && ! 1079: <26>isdigit(argv[optind][1])) { ! 1080: <26>optind += fieldarg(argv[optind], ! 1081: argv[optind+1]); ! 1082: <26>continue; ! 1083: } ! 1084: <875>n = optind; /* for sake of case '?' */ ! 1085: <875>c = getopt(argc,argv,"a:bcdfgik:mno:rst:uw:y:MT:"); ! 1086: switch(<875>c) { ! 1087: case '?': ! 1088: <16>fatal("bad option", argv[n], 0); ! 1089: default: ! 1090: <0>fatal("implementation error 1","",0); ! 1091: case 'b': ! 1092: case 'd': ! 1093: case 'f': ! 1094: case 'g': ! 1095: case 'i': ! 1096: case 'n': ! 1097: case 'M': ! 1098: case 'r': ! 1099: <97>s[1] = c; ! 1100: <97>fieldarg(s, 0); ! 1101: <97>continue; ! 1102: case 'c': ! 1103: <88>cflag++; ! 1104: <88>continue; ! 1105: case 'm': ! 1106: <49>mflag++; ! 1107: <49>continue; ! 1108: case 's': ! 1109: <9>sflag++; ! 1110: <9>continue; ! 1111: case 'u': ! 1112: <17>uflag++; ! 1113: <17>sflag++; ! 1114: <17>continue; ! 1115: case 'a': ! 1116: <35>aflag++; ! 1117: <35>uflag++; ! 1118: <35>sflag++; ! 1119: <35>optionk(optarg, accum, &naccum); ! 1120: <35>continue; ! 1121: case 'k': ! 1122: <181>optionk(optarg, fields, &nfields); ! 1123: <175>continue; ! 1124: case 'o': ! 1125: <5>oname = optarg; ! 1126: <5>continue; ! 1127: case 'T': ! 1128: <1>tname[0] = optarg; ! 1129: <1>continue; ! 1130: case 'w': ! 1131: <33>nmerge = atoi(optarg); ! 1132: if(<33>nmerge < 2) ! 1133: <0>fatal("-w too small","",0); ! 1134: <33>continue; ! 1135: case 'y': ! 1136: <5>optiony(optarg); ! 1137: <5>continue; ! 1138: case 't': ! 1139: if(<51>strlen(optarg) != 1) ! 1140: <1>fatal("bad argument for -t", "", 0); ! 1141: <50>tab = optarg[0]; ! 1142: <50>continue; ! 1143: case 'z': ! 1144: <0>warn("nonstandard option -z ignored","",0); ! 1145: case -1: ! 1146: <288>break; ! 1147: } ! 1148: <288>break; ! 1149: } ! 1150: <288>filelist(argc, argv); ! 1151: if(<288>cflag) ! 1152: <88>aflag = 0; ! 1153: <288>fieldwrapup(); ! 1154: <282>tabinit(); ! 1155: <282>setsigs(cleanup); ! 1156: ! 1157: if(<282>cflag) { ! 1158: if(<88>nfiles > 1) ! 1159: <1>fatal("-c takes just one file", "", 0); ! 1160: <87>check(files[0]); ! 1161: return <82>0; ! 1162: } ! 1163: if(<194>mflag) { ! 1164: <47>merge(0); ! 1165: return <46>0; ! 1166: } ! 1167: for(<147>n=0; <820>n<nfiles; <673>n++) { ! 1168: <676>input = fileopen(files[n], "r"); ! 1169: <674>readin(); ! 1170: <674>fileclose(input, files[n]); ! 1171: } ! 1172: if(<144>stack->head==0 && <12>nextfile==0) { /* empty input */ ! 1173: if(<12>strcmp(oname,"-") != 0) ! 1174: <4>fileclose(fileopen(oname, "w"), oname); ! 1175: return <12>0; ! 1176: } ! 1177: if(<132>stack->head && <132>stack->head->next) ! 1178: <120>sort(stack, 0); ! 1179: if(<132>nextfile > 0) { ! 1180: if(<2>stack->head) ! 1181: <2>dumptotemp(); ! 1182: <2>tabfree(); ! 1183: <2>merge(1); ! 1184: } else { ! 1185: FILE *f; ! 1186: <130>f = fileopen(oname, "w"); ! 1187: <129>printout(stack->head, f, oname); ! 1188: <129>fileclose(f, oname); ! 1189: } ! 1190: return <131>0; ! 1191: } ! 1192: ! 1193: void ! 1194: filelist(int argc, char **argv) ! 1195: <288>{ ! 1196: int i, j; ! 1197: <288>files = nofiles; ! 1198: <288>nfiles = argc - optind; ! 1199: if(<288>nfiles != 0) ! 1200: <260>files = argv + optind; ! 1201: else ! 1202: <28>nfiles = 1; ! 1203: if(<288>strcmp(argv[optind-1], "--") == 0) ! 1204: return<2>; ! 1205: for(<286>i=j=0; <1673>i<nfiles; <1387>i++) { ! 1206: if(<1387>strncmp(files[i], "-o", 2) == 0) { ! 1207: if(<6>files[i][2] != 0) ! 1208: <1>oname = files[i] + 2; ! 1209: else if(<5>i < argc-1) ! 1210: <5>oname = files[++i]; ! 1211: else ! 1212: <0>fatal("incomplete -o", "", 0); ! 1213: } else ! 1214: <1381>files[j++] = files[i]; ! 1215: } ! 1216: <286>files[j] = 0; ! 1217: <286>nfiles = j; ! 1218: <286>} ! 1219: ! 1220: void ! 1221: readin(void) ! 1222: <674>{ ! 1223: int n; ! 1224: struct rec *new; ! 1225: struct rec *p = <674>stack->tail; ! 1226: struct rec *r = <674>p? <529>succ(p): buffer; ! 1227: ! 1228: for(<674>;<342230>;<342230>) { ! 1229: if(<342904>bufmax-(uchar*)r < MINREC) { ! 1230: <78>sealstack(p); ! 1231: <78>dumptotemp(); ! 1232: <78>p = 0; ! 1233: <78>r = buffer; ! 1234: } ! 1235: <342904>r->next = (struct rec*)bufmax; ! 1236: <342904>new = getline(r, input); ! 1237: recenter: ! 1238: if(<342906>new == 0) { ! 1239: <342230>r->next = 0; ! 1240: if(<342230>p) ! 1241: <342017>p->next = r; ! 1242: <342230>p = r; ! 1243: <342230>r = succ(r); ! 1244: } else if(<676>new == ENDFILE) { ! 1245: <674>sealstack(p); ! 1246: return<674>; ! 1247: } else { ! 1248: <2>sealstack(p); ! 1249: <2>dumptotemp(); ! 1250: <2>p = 0; ! 1251: <2>r = buffer; ! 1252: <2>n = data(new)-(uchar*)new+new->dlen+new->klen; ! 1253: if(<2>(uchar*)r+n > bufmax) ! 1254: <0>fatal("monster record", "", 0); ! 1255: <2>memmove(r, new, n); ! 1256: <2>free(new); ! 1257: <2>new = 0; ! 1258: <2>goto recenter; ! 1259: } ! 1260: } ! 1261: } ! 1262: ! 1263: void ! 1264: sealstack(struct rec *p) ! 1265: <754>{ ! 1266: if(<754>p == 0) ! 1267: return<12>; ! 1268: <742>p->next = 0; ! 1269: if(<742>stack->head == 0) ! 1270: <213>stack->head = buffer; ! 1271: <742>stack->tail = p; ! 1272: <742>} ! 1273: ! 1274: void ! 1275: printout(struct rec *r, FILE *f, char *name) ! 1276: <211>{ ! 1277: int c, n; ! 1278: uchar *dp, *ep; ! 1279: for( <211>; <248661>r; <248450>r=r->next) { ! 1280: <248450>dp = data(r); ! 1281: <248450>n = r->dlen; ! 1282: <248450>ep = dp + n++; ! 1283: <248450>c = *ep; ! 1284: <248450>*ep = '\n'; ! 1285: if(<248450>fwrite((char*)dp, 1, n, f) != n) ! 1286: <0>fatal("error writing", name, 0); ! 1287: <248450>*ep = c; ! 1288: } ! 1289: <211>} ! 1290: ! 1291: void ! 1292: dumptotemp() ! 1293: <82>{ ! 1294: char *tempfile = <82>filename(nextfile++); ! 1295: FILE *temp = fileopen(<82>tempfile,"w"); ! 1296: ! 1297: if(<82>stack->head == 0) ! 1298: <0>fatal("monster record", "", 0); ! 1299: <82>stack->tail->next = 0; /* for good measure */ ! 1300: <82>sort(stack, 0); ! 1301: <82>printout(stack->head, temp, tempfile); ! 1302: <82>fileclose(temp, tempfile); ! 1303: <82>free(tempfile); ! 1304: <82>stack->head = stack->tail = 0; ! 1305: return<82>; ! 1306: } ! 1307: field.c: ! 1308: ! 1309: /* Copyright 1990, AT&T Bell Labs */ ! 1310: #include <stdlib.h> ! 1311: #include <ctype.h> ! 1312: #include "fsort.h" ! 1313: ! 1314: ! 1315: ! 1316: static char *modifiers(struct field*, char*, int); ! 1317: static char *keyspec(struct pos*, char*); ! 1318: static void globalmods(struct field*); ! 1319: static void chkfieldno(struct field*); ! 1320: ! 1321: struct field fields[NF] = { ! 1322: { 0, 0, 0, 0, 0, 0, 0, { 0, 0 }, { NP, 0 } } ! 1323: }; ! 1324: int nfields = 0; ! 1325: ! 1326: int tab; ! 1327: int signedrflag; ! 1328: int simplekeyed; ! 1329: ! 1330: #define blank(p) (*(p)==' ' || *(p)=='\t') ! 1331: ! 1332: enum { OLD, NEW }; ! 1333: ! 1334: /* interpret 1 or 2 arguments and return how many */ ! 1335: int ! 1336: fieldarg(char *argv1, char *argv2) ! 1337: <123>{ ! 1338: char *av1 = <123>argv1; ! 1339: char *av2 = <123>argv2; ! 1340: struct field *field; ! 1341: ! 1342: if(<123>av1[0] == '+' && <26>isdigit(av1[1])) { ! 1343: if(<26>++nfields >= NF) ! 1344: <0>fatal("too many fields", argv1, 0); ! 1345: <26>field = &fields[nfields]; ! 1346: <26>field->end.fieldno = NP+1; ! 1347: <26>field->style = OLD; ! 1348: ! 1349: <26>av1 = keyspec(&field->begin, av1+1); ! 1350: if(<26>*modifiers(field, av1, 0)) ! 1351: <0>goto bad; ! 1352: ! 1353: if(<26>av2==0 || <25>av2[0]!='-' || <12>!isdigit(av2[1])) ! 1354: return <14>1; ! 1355: <12>av2 = keyspec(&field->end, av2+1); ! 1356: <12>argv1 = argv2; /* in case of diagnostic */ ! 1357: if(<12>*modifiers(field, av2, 1)) ! 1358: <0>goto bad; ! 1359: return <12>2; ! 1360: } else if(<97>*modifiers(fields, av1+1, -1)) ! 1361: <0>goto bad; /* believed not to happen */ ! 1362: return <97>1; ! 1363: bad: ! 1364: <0>fatal("bad field specification", argv1, 0); ! 1365: return <0>0; /* dummy */ ! 1366: } ! 1367: ! 1368: void ! 1369: optionk(char *arg, struct field *fields, int *nfields) ! 1370: <216>{ ! 1371: char *a = <216>arg; ! 1372: struct field *field; ! 1373: if(<216>++*nfields >= NF) ! 1374: <0>fatal("too many fields", arg, 0); ! 1375: <216>field = &fields[*nfields]; ! 1376: <216>field->begin.charno = 1; ! 1377: <216>field->end.fieldno = NP+1; ! 1378: <216>field->style = NEW; ! 1379: ! 1380: <216>a = keyspec(&field->begin, a); ! 1381: <213>a = modifiers(field, a, 0); ! 1382: if(<213>*a == ',') { ! 1383: <116>a = keyspec(&field->end, a+1); ! 1384: <115>a = modifiers(field, a, 1); ! 1385: } ! 1386: if(<212>*a == 0) ! 1387: return<210>; ! 1388: bad: ! 1389: <2>fatal("bad -k specification", arg, 0); ! 1390: <0>} ! 1391: ! 1392: static char * ! 1393: keyspec(struct pos *p, char *arg) ! 1394: <370>{ ! 1395: if(<370>!isdigit(*arg)) ! 1396: <3>fatal("missing field number", "", 0); ! 1397: <367>p->fieldno = strtoul(arg, &arg, 10); ! 1398: if(<367>*arg == '.') ! 1399: if(<69>!isdigit(*++arg)) ! 1400: <1>fatal("missing character number", "", 0); ! 1401: else ! 1402: <68>p->charno = strtoul(arg, &arg, 10); ! 1403: return <366>arg; ! 1404: } ! 1405: ! 1406: /* keyed = 1 if there are fields present (+ options) or if ! 1407: numeric (-ng), translation (-f) or deletion (-idb) options ! 1408: are present. In these cases, a separate key is constructed ! 1409: for rsort. The key, however is not carried on ! 1410: intermediate files. (It would be interesting to try.) ! 1411: It must be reconstructed for the merge phase, and that ! 1412: may be expensive, since relatively few comparisons ! 1413: happen in that phase. simplekeyed = 1 if there are options, ! 1414: so that pure ascii comparison won't work, but no fields, no ! 1415: months, no numerics. */ ! 1416: ! 1417: void ! 1418: fieldwrapup(void) ! 1419: <288>{ ! 1420: int i; ! 1421: if(<288>nfields==0 && <145>aflag) ! 1422: <1>fatal("-a without -k", "", 0); ! 1423: if(<287>fields->coder == 0) <262>fields->coder = tcode; ! 1424: if(<287>fields->trans == 0) <270>fields->trans = ident; ! 1425: if(<287>fields->keep == 0) <269>fields->keep = all; ! 1426: for(<287>i=1; <487>i<=nfields; <200>i++) { ! 1427: <201>globalmods(&fields[i]); ! 1428: <201>chkfieldno(&fields[i]); ! 1429: } ! 1430: for(<286>i=1; <316>i<=naccum; <30>i++) { ! 1431: <34>chkaccum(&accum[i]); ! 1432: <30>chkfieldno(&accum[i]); ! 1433: } ! 1434: <282>signedrflag = fields->rflag? <24>-1: <258>1; /* used only by merge.c*/ ! 1435: <282>simplekeyed = nfields==0 && <144>fields->coder==tcode ! 1436: && <119>(fields->trans!=ident || <112>fields->keep!=all); ! 1437: if(<282>nfields==0 && <144>!keyed) /* used only by rsort.c */ ! 1438: <109>rflag = fields->rflag; ! 1439: if(<282>nfields > 0) ! 1440: <138>keyed = 1; ! 1441: <282>} ! 1442: ! 1443: static void ! 1444: conflict(void) ! 1445: <4>{ ! 1446: <4>warn("conflicting key types", "", 0); ! 1447: <4>} ! 1448: ! 1449: static void ! 1450: dupla(uchar **oldp, uchar *new) ! 1451: <48>{ ! 1452: if(<48>*oldp != 0 && <1>*oldp != new) ! 1453: <1>conflict(); ! 1454: <48>*oldp = new; ! 1455: <48>} ! 1456: ! 1457: static void ! 1458: duplb(int (**oldp)(uchar*,uchar*,int,struct field*), int (*new)(uchar*,uchar*,int,struct field*)) ! 1459: <56>{ ! 1460: if(<56>*oldp != 0 && <2>*oldp != new) ! 1461: <2>conflict(); ! 1462: <56>*oldp = new; ! 1463: <56>} ! 1464: ! 1465: /* eflag=-1 global flags, =0 field start, =1 field end */ ! 1466: ! 1467: static char * ! 1468: modifiers(struct field *field, char *argv1, int eflag) ! 1469: <463>{ ! 1470: for( <463>; <629>*argv1; <166>argv1++) { ! 1471: switch(<284>*argv1) { ! 1472: case 'b': if(<22>eflag==1) <6>field->eflag = 1; ! 1473: else <16>field->bflag = 1; <22>goto ckglob; ! 1474: case 'r': <40>field->rflag = 1; <40>goto ckglob; ! 1475: case 'f': <23>dupla(&field->trans, fold); <23>break; ! 1476: case 'd': <20>dupla(&field->keep, dict); <20>break; ! 1477: case 'i': <5>dupla(&field->keep, ascii); <5>break; ! 1478: case 'g': <10>duplb(&field->coder, gcode); <10>break; ! 1479: case 'n': <38>duplb(&field->coder, ncode); <38>break; ! 1480: case 'M': <8>duplb(&field->coder, Mcode); <8>break; ! 1481: default: ! 1482: <118>goto done; ! 1483: } ! 1484: <104>keyed = 1; ! 1485: ckglob: ! 1486: if(<166>field==fields && <97>nfields>0) ! 1487: <2>warn("field spec precedes global option",argv1,1); ! 1488: } ! 1489: done: ! 1490: if(<463>field->coder==ncode && <40>field->keep) ! 1491: <1>conflict(); ! 1492: return <463>argv1; ! 1493: } ! 1494: ! 1495: static void ! 1496: globalmods(struct field *field) ! 1497: <201>{ ! 1498: int flagged = <201>field->bflag | field->eflag | field->rflag; ! 1499: if(<201>!field->coder) <172>field->coder = tcode; ! 1500: else <29>flagged++; ! 1501: if(<201>!field->trans) <196>field->trans = ident; ! 1502: else <5>flagged++; ! 1503: if(<201>!field->keep) <197>field->keep = all; ! 1504: else <4>flagged++; ! 1505: if(<201>!flagged) { ! 1506: <146>field->coder = fields->coder; ! 1507: <146>field->trans = fields->trans; ! 1508: <146>field->keep = fields->keep; ! 1509: <146>field->rflag = fields->rflag; ! 1510: <146>field->bflag = fields->bflag; ! 1511: if(<146>field->style == NEW) ! 1512: <126>field->eflag = fields->bflag; ! 1513: } ! 1514: <201>} ! 1515: ! 1516: /* convert field representation from numbers given in arguments ! 1517: to a 0-origin first,last+1 representation, with a negative ! 1518: quantity for a character offset to the end of this field */ ! 1519: ! 1520: static void ! 1521: chkfieldno(struct field *field) ! 1522: <231>{ ! 1523: if(<231>field->style == NEW) { ! 1524: if(<205>--field->begin.fieldno < 0 || ! 1525: <204>--field->begin.charno < 0 || ! 1526: <204>--field->end.fieldno < 0) ! 1527: <1>fatal("improper 0 in field specifier", "", 0); ! 1528: if(<204>field->end.charno == 0) ! 1529: <180>field->end.charno--; ! 1530: } else if(<26>field->end.charno==0 && <22>field->end.fieldno>0) { ! 1531: if(<22>tab && <8>field->eflag) ! 1532: <0>fatal("skipping blanks right after tab char" ! 1533: " is ill-defined", "", 0); ! 1534: <22>field->end.fieldno--; ! 1535: <22>field->end.charno--; ! 1536: } ! 1537: if(<230>field->begin.fieldno > NP) ! 1538: <0>field->begin.fieldno = NP; ! 1539: if(<230>field->end.fieldno > NP) ! 1540: <0>field->end.fieldno = NP; ! 1541: /* fprintf(stderr,"%d %d.%d,%d.%d\n",field-fields,field->begin.fieldno, field->begin.charno,field->end.fieldno, field->end.charno);*/ ! 1542: <230>} ! 1543: ! 1544: int ! 1545: fieldcode(uchar *dp, uchar *kp, int len, uchar *b, struct field *fields, int nfields) ! 1546: <474734>{ ! 1547: uchar *posns[NP+1]; /* field start positions */ ! 1548: uchar *cp; ! 1549: struct field *field; ! 1550: uchar *op = <474734>kp; ! 1551: uchar *ep; ! 1552: uchar *bound = <474734>kp + MAXREC; ! 1553: int i; ! 1554: int np; ! 1555: if(<474734>bound > b) ! 1556: <155959>bound = b; ! 1557: <474734>posns[0] = dp; ! 1558: if(<474734>tab) ! 1559: for(<304>np=1, i=len, cp=dp; <6355>i>0 && <6051>np<NP; i-<6051>-) { ! 1560: if(<6051>*cp++ != tab) ! 1561: <4411>continue; ! 1562: <1640>posns[np++] = cp; ! 1563: } ! 1564: else ! 1565: for(<474430>np=1, i=len, cp=dp; <1110378>i>0 && <635948>np<NP; ) <635948>{ ! 1566: while(<1228760>blank(cp) && i><636001>0) ! 1567: <592812>cp++, i--; ! 1568: while(<3943779>!blank(cp) && i><3782124>0) ! 1569: <3307831>cp++, i--; ! 1570: <635948>posns[np++] = cp; ! 1571: } ! 1572: ! 1573: if(<474734>nfields > 0) ! 1574: <143100>field = &fields[1]; ! 1575: else ! 1576: <331634>field = &fields[0]; ! 1577: <474734>i = nfields; ! 1578: do { ! 1579: int t = <486184>field->begin.fieldno; ! 1580: uchar *xp = <486184>dp + len; ! 1581: if(<486184>t < np) { ! 1582: <486176>cp = posns[t]; ! 1583: if(<486176>field->bflag && <144>nfields) ! 1584: while(<454>cp<xp && <454>blank(cp)) ! 1585: <316>cp++; ! 1586: <486176>cp += field->begin.charno; ! 1587: if(<486176>cp > xp) ! 1588: <12>cp = xp; ! 1589: } else ! 1590: <8>cp = xp; ! 1591: <486184>t = field->end.fieldno; ! 1592: if(<486184>t < np) { ! 1593: if(<112104>field->end.charno < 0) { ! 1594: if(<111816>t >= np-1) ! 1595: <25>ep = xp; ! 1596: else { ! 1597: <111791>ep = posns[t+1]; ! 1598: if(<111791>tab) <22>ep--; ! 1599: } ! 1600: } else { ! 1601: <288>ep = posns[t]; ! 1602: if(<288>field->eflag) ! 1603: while(<262>ep<xp && <262>blank(ep)) ! 1604: <186>ep++; ! 1605: <288>ep += field->end.charno; ! 1606: } ! 1607: if(<112104>ep > xp) ! 1608: <28>ep = xp; ! 1609: else if(<112076>ep < cp) ! 1610: <10>ep = cp; ! 1611: } else ! 1612: <374080>ep = xp; ! 1613: <486184>t = ep - cp; ! 1614: if(<486184>field->coder != acode && <386494>op+room(t) > bound) ! 1615: return <17>-1; ! 1616: <486167>op += (*field->coder)(cp, op, ep-cp, field); ! 1617: <486167>field++; ! 1618: } while(<486167>--i > 0); ! 1619: return <474717>op - kp; ! 1620: } ! 1621: ! 1622: /* Encode text field subject to options -r -fdi -b. ! 1623: Fields are separated by 0 (or 255 if rflag is set) ! 1624: the anti-ambiguity stuff prevents such codes from ! 1625: happening otherwise by coding real zeros and ones ! 1626: as 0x0101 and 0x0102, and similarly for complements */ ! 1627: ! 1628: int ! 1629: tcode(uchar *dp, uchar *kp, int len, struct field *f) ! 1630: <12156>{ ! 1631: uchar *cp = <12156>kp; ! 1632: int c; ! 1633: uchar *keep = <12156>f->keep; ! 1634: uchar *trans = <12156>f->trans; ! 1635: int reverse = <12156>f->rflag? <106>~0: <12050>0; ! 1636: while(<211231>--len >= 0) { ! 1637: <199075>c = *dp++; ! 1638: if(<199075>keep[c]) { ! 1639: <198337>c = trans[c]; ! 1640: if(<198337>c <= 1) { /* anti-ambiguity */ ! 1641: <4>*cp++ = 1^reverse; ! 1642: <4>c++; ! 1643: } else if(<198333>c >= 254) { ! 1644: <4>*cp++ = 255^reverse; ! 1645: <4>c--; ! 1646: } ! 1647: <198337>*cp++ = c^reverse; ! 1648: } ! 1649: } ! 1650: <12156>*cp++ = reverse; ! 1651: return <12156>cp - kp; ! 1652: } ! 1653: ! 1654: static char *month[] = { "jan", "feb", "mar", "apr", "may", ! 1655: "jun", "jul", "aug", "sep", "oct", "nov", "dec" }; ! 1656: ! 1657: int ! 1658: Mcode(uchar *dp, uchar *kp, int len, struct field *f) ! 1659: <57>{ ! 1660: int j = <57>-1; ! 1661: int i; ! 1662: uchar *cp; ! 1663: for( <57>; <69>len>0; <12>dp++, len--) { ! 1664: if(<69>*dp!=' ' && <57>*dp!='\t') ! 1665: <57>break; ! 1666: } ! 1667: if(<57>len >= 3) ! 1668: while(<294>++j < 12) { ! 1669: <292>cp = (uchar*)month[j]; ! 1670: for(<292>i=0; <166>i<3; <166>i++) ! 1671: if(<410>(dp[i]|('a'-'A')) != *cp++) ! 1672: <244>break; ! 1673: if(<292>i >= 3) ! 1674: <48>break; ! 1675: } ! 1676: <57>*kp = j>=12? <2>0: <55>j+1; ! 1677: if(<57>f->rflag) ! 1678: <8>*kp ^= ~0; ! 1679: return <57>1; ! 1680: } ! 1681: tables.c: ! 1682: ! 1683: /* Copyright 1990, AT&T Bell Labs */ ! 1684: #include <stdlib.h> ! 1685: #include <string.h> ! 1686: #include <ctype.h> ! 1687: #include "fsort.h" ! 1688: ! 1689: /* STACK=1000 makes lots of room under normal conditions. ! 1690: But it can be broken. 40 cycles like this will do it: ! 1691: a,b,...z,za,zb,...zz,zza,zzb,...,zzz,zzza,... ! 1692: Minor changes to rsort() would allow the stack to be ! 1693: extended discontiguously. Pity we don't have alloca any more. ! 1694: */ ! 1695: ! 1696: #define BUFFER 6000000 ! 1697: #define MINBUF 10000 /* not worth trying */ ! 1698: #define STACK 1000 ! 1699: ! 1700: uchar *bufmax; ! 1701: struct rec *buffer; ! 1702: unsigned long bufsiz = BUFFER; ! 1703: struct rec endfile; ! 1704: struct list *stack; ! 1705: struct list *stackmax; ! 1706: ! 1707: uchar ident[256]; /* identity transform */ ! 1708: uchar fold[256]; /* fold upper case to lower */ ! 1709: ! 1710: uchar all[256]; /* all chars significant */ ! 1711: uchar dict[256]; /* sig chars for dictionary order */ ! 1712: uchar ascii[256]; /* ascii graphics significant */ ! 1713: ! 1714: void ! 1715: tabinit(void) ! 1716: <282>{ ! 1717: int i; ! 1718: <282>memset((char*)all,1,256); ! 1719: ! 1720: <282>memset((char*)(dict+'0'),1,10); ! 1721: <282>memset((char*)(dict+'A'),1,26); ! 1722: <282>memset((char*)(dict+'a'),1,26); ! 1723: <282>dict[' '] = dict['\t'] = 1; ! 1724: ! 1725: <282>memset((char*)(ascii+040),1,0137); /* 040-0176 */ ! 1726: ! 1727: for(<282>i=0; <72192>i<256; <72192>i++) ! 1728: <72192>fold[i] = ident[i] = i; ! 1729: for(<282>i='a'; <7332>i<='z'; <7332>i++) ! 1730: <7332>fold[i] += 'A' - 'a'; ! 1731: ! 1732: <282>stack = (struct list*)malloc(STACK*sizeof(*stack)); ! 1733: do { ! 1734: if(<282>(buffer=(struct rec*)malloc(bufsiz)) != 0) ! 1735: <282>break; ! 1736: } while(<0>(bufsiz/=2) > MINBUF); ! 1737: if(<282>buffer==0 || <282>stack==0) ! 1738: <0>fatal("can't get working space", "", 0); ! 1739: <282>bufmax = (uchar*)buffer + bufsiz - 2*sizeof(*buffer); ! 1740: <282>stack->head = stack->tail = 0; ! 1741: <282>stackmax = stack + STACK; ! 1742: <282>} ! 1743: ! 1744: void ! 1745: tabfree(void) ! 1746: <2>{ ! 1747: <2>free(stack); ! 1748: <2>free(buffer); ! 1749: <2>} ! 1750: ! 1751: void ! 1752: optiony(char *s) ! 1753: <5>{ ! 1754: long size = <5>atol(s); ! 1755: if(<5>!isdigit(s[0])) ! 1756: <0>fatal("no size for -y","",0); ! 1757: if(<5>size >= MINBUF/10) /* tiny helps debugging */ ! 1758: <5>bufsiz = size; ! 1759: else if(<0>size == 0) ! 1760: <0>bufsiz = 10L*BUFFER; ! 1761: else <0>fatal("-y too small", "", 0); ! 1762: <5>} ! 1763: cfiles.c: ! 1764: ! 1765: /* Copyright 1990, AT&T Bell Labs */ ! 1766: #include "fsort.h" ! 1767: #include <stdlib.h> ! 1768: #include <string.h> ! 1769: #include <signal.h> ! 1770: #include <errno.h> ! 1771: #include <sys/types.h> ! 1772: #include <sys/stat.h> ! 1773: ! 1774: #define SIGHUP 1 ! 1775: #define SIGINT 2 ! 1776: #define SIGQUIT 3 ! 1777: #define SIGPIPE 13 ! 1778: #define SIGTERM 15 ! 1779: ! 1780: extern int getpid(void); ! 1781: extern int access(char*, int); ! 1782: extern int unlink(char*); ! 1783: extern int stat(const char*, struct stat *); ! 1784: extern int cgets(char*, int, FILE*); ! 1785: ! 1786: FILE * ! 1787: fileopen(char *name, char *mode) ! 1788: <2052>{ ! 1789: FILE *f; ! 1790: if(<2052>strcmp(name,"-") == 0) ! 1791: if(<199>strcmp(mode, "r") == 0) ! 1792: <27>f = stdin; ! 1793: else { ! 1794: <172>setbuf(stdout,malloc(BUFSIZ)); ! 1795: <172>f = stdout; ! 1796: } ! 1797: else { ! 1798: if(<1853>strcmp(mode, "w") == 0 && ! 1799: <257>strcmp(name, oname) == 0 && ! 1800: <11>overwrite(0)) ! 1801: <4>setsigs(SIG_IGN); ! 1802: <1853>f = fopen(name, mode); ! 1803: } ! 1804: if(<2052>f == 0) ! 1805: <3>fatal("can't open", name, 0); ! 1806: return <2049>f; ! 1807: } ! 1808: ! 1809: void ! 1810: fileclose(FILE *f, char *name) ! 1811: <2041>{ ! 1812: if(<2041>fclose(f)==EOF && <1>name!=0) ! 1813: <1>fatal("error on", name, 0); ! 1814: <2040>} ! 1815: ! 1816: /* file name strings accumulate as garbage */ ! 1817: ! 1818: char * ! 1819: filename(int number) ! 1820: <849>{ ! 1821: char name[50]; ! 1822: char *s; ! 1823: int i; ! 1824: for(<849>i=0; <849>(s=tname[i])!=0; <0>i++) ! 1825: if(<849>access(s, 03) != -1) ! 1826: <849>break; ! 1827: if(<849>s == 0) ! 1828: <0>fatal("no accessible temp directory", "", 0); ! 1829: <849>sprintf(name, "%s/stm%.5d.%.4d", s, getpid(), number); ! 1830: <849>s = malloc(strlen(name) + 1); ! 1831: if(<849>s == 0) ! 1832: <0>fatal("out of space", "", 0); ! 1833: <849>strcpy(s, name); ! 1834: return <849>s; ! 1835: } ! 1836: ! 1837: /* if there is enough room in record r, getline puts ! 1838: a line of data there and returns 0; otherwise it ! 1839: returns a pointer to a new record. The record ! 1840: may be grown in stages; intermediate stages can ! 1841: be discarded, but the original cannot. */ ! 1842: ! 1843: static struct rec * ! 1844: newrec(struct rec *r, struct rec *retval) ! 1845: <83>{ ! 1846: int n = <83>(uchar*)r->next - data(r); ! 1847: int len = <83>(uchar*)r->next - (uchar*)r; ! 1848: struct rec *new = <83>(struct rec*)malloc(len + n); ! 1849: if(<83>new == 0) ! 1850: <0>fatal("no space for record", "", 0); ! 1851: <83>memmove(new, r, len); ! 1852: <83>new->next = (struct rec*)((uchar*)new + len + n); ! 1853: if(<83>retval) ! 1854: <24>free(retval); ! 1855: return <83>new; ! 1856: } ! 1857: ! 1858: struct rec* ! 1859: getline(struct rec *r, FILE *f) ! 1860: <627600>{ ! 1861: int n = <627600>0; ! 1862: int m; ! 1863: uchar *cp, *dp; ! 1864: struct rec *retval = <627600>0; ! 1865: ! 1866: if(<627600>feof(f)) /* in case newline was appended */ ! 1867: return <1>ENDFILE; ! 1868: for(<627599>;<133>;<133>) { /* usually executed once */ ! 1869: <627732>dp = data(r); ! 1870: <627732>cp = dp + n; ! 1871: <627732>m = (uchar*)r->next - cp; ! 1872: if(<627732>m <= 1) ! 1873: <66>retval = r = newrec(r, retval); ! 1874: else { ! 1875: <627666>m = cgets((char*)cp, m, f); ! 1876: if(<627666>m == 0) { ! 1877: if(<1611>n == 0) ! 1878: return <1610>ENDFILE; ! 1879: <1>warn("newline appended", "", 0); ! 1880: <1>break; ! 1881: } ! 1882: <626055>n += m; ! 1883: if(<626055>dp[n-1] == '\n') { ! 1884: <625988>n--; ! 1885: <625988>break; ! 1886: } ! 1887: } ! 1888: } ! 1889: ! 1890: <625989>r->dlen = n; ! 1891: if(<625989>n > MAXREC) ! 1892: <0>fatal("monster record", "", 0); ! 1893: if(<625989>!keyed) { ! 1894: <240956>r->klen = 0; /* hygiene */ ! 1895: return <240956>retval; ! 1896: } ! 1897: while(<385050>(n = fieldcode(data(r),key(r), r->dlen, ! 1898: (uchar*)r->next, fields, nfields)) < 0) ! 1899: <17>retval = r = newrec(r, retval); /* rare event */ ! 1900: if(<385033>n > MAXREC) ! 1901: <0>fatal("monster key", "", 0); ! 1902: <385033>r->klen = n; ! 1903: return <385033>retval; ! 1904: } ! 1905: ! 1906: static char *level = "warning"; ! 1907: ! 1908: void ! 1909: warn(char *m, char *s, int l) ! 1910: <54>{ ! 1911: <54>fprintf(stderr, "sort: %s: %s %.*s\n", ! 1912: level, m, l==0?<45>strlen(s):<9>l, s); ! 1913: <54>} ! 1914: ! 1915: void ! 1916: fatal(char *m, char *s, int l) ! 1917: <40>{ ! 1918: <40>level = "error"; ! 1919: <40>warn(m, s, l); ! 1920: if(<40>errno) ! 1921: <3>perror(""); ! 1922: <40>cleanup(1); ! 1923: <0>} ! 1924: ! 1925: int ! 1926: overwrite(int j) ! 1927: <60>{ ! 1928: struct stat sb1, sb2; ! 1929: if(<60>strcmp(oname, "-") == 0) ! 1930: return <46>0; ! 1931: if(<14>stat(oname, &sb1) == -1) ! 1932: return <4>0; ! 1933: for( <10>; <29>j<nfiles; <19>j++) { ! 1934: if(<26>strcmp(files[j], "-") == 0) ! 1935: <2>continue; ! 1936: if(<24>stat(files[j], &sb2) == -1) ! 1937: <0>fatal("cannot locate", files[j], 0); ! 1938: if(<24>sb1.st_dev==sb2.st_dev && <24>sb1.st_ino==sb2.st_ino) ! 1939: return <7>1; ! 1940: } ! 1941: return <3>0; ! 1942: } ! 1943: ! 1944: static int siglist[] = { SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGTERM }; ! 1945: ! 1946: void ! 1947: setsigs(void(*f)(int)) ! 1948: <326>{ ! 1949: int i; ! 1950: for(<326>i=0; <1956>i<sizeof(siglist)/sizeof(*siglist); <1630>i++) ! 1951: if(<1630>signal(siglist[i], f) == SIG_IGN) ! 1952: <0>signal(siglist[i], SIG_IGN); ! 1953: <326>} ! 1954: ! 1955: void ! 1956: cleanup(int i) ! 1957: <40>{ ! 1958: char *name; ! 1959: <40>setsigs(SIG_IGN); ! 1960: while(<40>--nextfile >= 0) { ! 1961: <0>name = filename(nextfile); ! 1962: <0>unlink(name); ! 1963: <0>free(name); ! 1964: } ! 1965: <40>exit(i); ! 1966: <0>} ! 1967: cgets.c: ! 1968: ! 1969: /* Copyright AT&T Bell Laboratories, 1993 */ ! 1970: #include <stdio.h> ! 1971: ! 1972: /* same as fgets, but returns a char count instead of first arg. ! 1973: * robust against null bytes in input */ ! 1974: ! 1975: int ! 1976: cgets(char *ptr, int n, FILE *iop) ! 1977: <627666>{ ! 1978: int l; ! 1979: char *s = <627666>ptr; ! 1980: unsigned char *t; ! 1981: while(<631159>--n > 0) { ! 1982: <631159>l = iop->_cnt; ! 1983: if(<631159>l > 0) { ! 1984: if(<627758>l > n) <277838>l = n; ! 1985: <627758>t = iop->_ptr; ! 1986: while(<8783600>--l >= 0 && <8781637>(*s++ = *t++) != '\n') ! 1987: <8155842>continue; ! 1988: <627758>l = t - iop->_ptr; ! 1989: <627758>iop->_ptr = t; ! 1990: <627758>iop->_cnt -= l; ! 1991: if(<627758>t[-1] == '\n' || <1963>(n -= l) <= 0) ! 1992: <625861>break; ! 1993: } ! 1994: <5298>l = getc(iop); ! 1995: if(<5298>l == EOF) ! 1996: <1612>break; ! 1997: <3686>*s++ = l; ! 1998: if(<3686>l == '\n') ! 1999: <193>break; ! 2000: } ! 2001: <627666>*s = 0; ! 2002: return <627666>s - ptr; ! 2003: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.