Annotation of researchv10no/cmd/sort/bprint.out, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.