Annotation of 43BSDTahoe/usr.bin/diff3/diff3.c, revision 1.1.1.1

1.1       root        1: #ifndef lint
                      2: static char sccsid[] = "@(#)diff3.c    4.4 (Berkeley) 8/27/85";
                      3: #endif
                      4: 
                      5: #include <stdio.h>
                      6: 
                      7: /* diff3 - 3-way differential file comparison*/
                      8: 
                      9: /* diff3 [-ex3EX] d13 d23 f1 f2 f3 [m1 m3]
                     10:  *
                     11:  * d13 = diff report on f1 vs f3
                     12:  * d23 = diff report on f2 vs f3
                     13:  * f1, f2, f3 the 3 files
                     14:  * if changes in f1 overlap with changes in f3, m1 and m3 are used
                     15:  * to mark the overlaps; otherwise, the file names f1 and f3 are used
                     16:  * (only for options E and X).
                     17: */
                     18: 
                     19: struct  range {int from,to; };
                     20:        /* from is first in range of changed lines
                     21:         * to is last+1
                     22:         * from=to=line after point of insertion
                     23:        * for added lines
                     24:        */
                     25: struct diff {struct range old, new;};
                     26: 
                     27: #define NC 200
                     28: struct diff d13[NC];
                     29: struct diff d23[NC];
                     30: /* de is used to gather editing scripts,
                     31:  * that are later spewed out in reverse order.
                     32:  * its first element must be all zero
                     33:  * the "new" component of de contains line positions
                     34:  * or byte positions depending on when you look(!?)
                     35:  * array overlap indicates which sections in de correspond to
                     36:  * lines that are different in all three files.
                     37: */
                     38: struct diff de[NC];
                     39: char overlap[NC];
                     40: int  overlapcnt =0;
                     41: 
                     42: char line[256];
                     43: FILE *fp[3];
                     44: /*     the number of the last-read line in each file
                     45:  *     is kept in cline[0-2]
                     46: */
                     47: int cline[3];
                     48: /*     the latest known correspondence between line
                     49:  *     numbers of the 3 files is stored in last[1-3]
                     50: */
                     51: int last[4];
                     52: int eflag;
                     53: int oflag;      /* indicates whether to mark overlaps (-E or -X)*/
                     54: int debug  = 0;
                     55: char f1mark[40], f3mark[40]; /*markers for -E and -X*/
                     56: 
                     57: 
                     58: main(argc,argv)
                     59: char **argv;
                     60: {
                     61:        register i,m,n;
                     62:         eflag=0; oflag=0;
                     63:        if(*argv[1]=='-') {
                     64:                switch(argv[1][1]) {
                     65:                default:
                     66:                        eflag = 3;
                     67:                        break;
                     68:                case '3':
                     69:                        eflag = 2;
                     70:                        break;
                     71:                case 'x':
                     72:                        eflag = 1;
                     73:                         break;
                     74:                 case 'E':
                     75:                         eflag = 3;
                     76:                         oflag = 1;
                     77:                         break;
                     78:                 case 'X':
                     79:                         oflag = eflag = 1;
                     80:                         break;
                     81:                }
                     82:                argv++;
                     83:                argc--;
                     84:        }
                     85:        if(argc<6) {
                     86:                fprintf(stderr,"diff3: arg count\n");
                     87:                exit(1);
                     88:        }
                     89:         if (oflag) { 
                     90:                 (void)sprintf(f1mark,"<<<<<<< %s",argc>=7?argv[6]:argv[3]);
                     91:                 (void)sprintf(f3mark,">>>>>>> %s",argc>=8?argv[7]:argv[5]);
                     92:         }
                     93: 
                     94:        m = readin(argv[1],d13);
                     95:        n = readin(argv[2],d23);
                     96:        for(i=0;i<=2;i++)
                     97:                if((fp[i] = fopen(argv[i+3],"r")) == NULL) {
                     98:                        printf("diff3: can't open %s\n",argv[i+3]);
                     99:                        exit(1);
                    100:                }
                    101:        merge(m,n);
                    102: }
                    103: 
                    104: /*pick up the line numbers of allcahnges from
                    105:  * one change file
                    106:  * (this puts the numbers in a vector, which is not
                    107:  * strictly necessary, since the vector is processed
                    108:  * in one sequential pass. The vector could be optimized
                    109:  * out of existence)
                    110: */
                    111: 
                    112: readin(name,dd)
                    113: char *name;
                    114: struct diff *dd;
                    115: {
                    116:        register i;
                    117:        int a,b,c,d;
                    118:        char kind;
                    119:        char *p;
                    120:        fp[0] = fopen(name,"r");
                    121:        for(i=0;getchange(fp[0]);i++) {
                    122:                if(i>=NC) {
                    123:                        fprintf(stderr,"diff3: too many changes\n");
                    124:                        exit(0);
                    125:                }
                    126:                p = line;
                    127:                a = b = number(&p);
                    128:                if(*p==',') {
                    129:                        p++;
                    130:                        b = number(&p);
                    131:                }
                    132:                kind = *p++;
                    133:                c = d = number(&p);
                    134:                if(*p==',') {
                    135:                        p++;
                    136:                        d = number(&p);
                    137:                }
                    138:                if(kind=='a')
                    139:                        a++;
                    140:                if(kind=='d')
                    141:                        c++;
                    142:                b++;
                    143:                d++;
                    144:                dd[i].old.from = a;
                    145:                dd[i].old.to = b;
                    146:                dd[i].new.from = c;
                    147:                dd[i].new.to = d;
                    148:        }
                    149:        dd[i].old.from = dd[i-1].old.to;
                    150:        dd[i].new.from = dd[i-1].new.to;
                    151:        (void)fclose(fp[0]);
                    152:        return(i);
                    153: }
                    154: 
                    155: number(lc)
                    156: char **lc;
                    157: {
                    158:        register nn;
                    159:        nn = 0;
                    160:        while(digit(**lc))
                    161:                nn = nn*10 + *(*lc)++ - '0';
                    162:        return(nn);
                    163: }
                    164: 
                    165: digit(c)
                    166: {
                    167:        return(c>='0'&&c<='9');
                    168: }
                    169: 
                    170: getchange(b)
                    171: FILE *b;
                    172: {
                    173:        while(getline(b))
                    174:                if(digit(line[0]))
                    175:                        return(1);
                    176:        return(0);
                    177: }
                    178: 
                    179: getline(b)
                    180: FILE *b;
                    181: {
                    182:        register i, c;
                    183:        for(i=0;i<sizeof(line)-1;i++) {
                    184:                c = getc(b);
                    185:                if(c==EOF)
                    186:                        break;
                    187:                line[i] = c;
                    188:                if(c=='\n') {
                    189:                        line[++i] = 0;
                    190:                        return(i);
                    191:                }
                    192:        }
                    193:        return(0);
                    194: }
                    195: 
                    196: merge(m1,m2)
                    197: {
                    198:        register struct diff *d1, *d2, *d3;
                    199:        int dup;
                    200:        int j;
                    201:        int t1,t2;
                    202:        d1 = d13;
                    203:        d2 = d23;
                    204:        j = 0;
                    205:        for(;(t1 = d1<d13+m1) | (t2 = d2<d23+m2);) {
                    206:                if(debug) {
                    207:                        printf("%d,%d=%d,%d %d,%d=%d,%d\n",
                    208:                        d1->old.from,d1->old.to,
                    209:                        d1->new.from,d1->new.to,
                    210:                        d2->old.from,d2->old.to,
                    211:                        d2->new.from,d2->new.to);
                    212:                }
                    213: /*                     first file is different from others*/
                    214:                if(!t2||t1&&d1->new.to < d2->new.from) {
                    215: /*                     stuff peculiar to 1st file */
                    216:                        if(eflag==0) {
                    217:                                separate("1");
                    218:                                change(1,&d1->old,0);
                    219:                                keep(2,&d1->new);
                    220:                                change(3,&d1->new,0);
                    221:                        }
                    222:                        d1++;
                    223:                        continue;
                    224:                }
                    225: /*                     second file is different from others*/
                    226:                if(!t1||t2&&d2->new.to < d1->new.from) {
                    227:                        if(eflag==0) {
                    228:                                separate("2");
                    229:                                keep(1,&d2->new);
                    230:                                change(2,&d2->old,0);
                    231:                                change(3,&d2->new,0);
                    232:                        }
                    233:                        d2++;
                    234:                        continue;
                    235:                }
                    236: /*                     merge overlapping changes in first file
                    237:  *                     this happens after extension see below*/
                    238:                if(d1+1<d13+m1 &&
                    239:                   d1->new.to>=d1[1].new.from) {
                    240:                        d1[1].old.from = d1->old.from;
                    241:                        d1[1].new.from = d1->new.from;
                    242:                        d1++;
                    243:                        continue;
                    244:                }
                    245: /*                     merge overlapping changes in second*/
                    246:                if(d2+1<d23+m2 &&
                    247:                   d2->new.to>=d2[1].new.from) {
                    248:                        d2[1].old.from = d2->old.from;
                    249:                        d2[1].new.from = d2->new.from;
                    250:                        d2++;
                    251:                        continue;
                    252:                }
                    253: /*                     stuff peculiar to third file or different in all*/
                    254:                if(d1->new.from==d2->new.from&&
                    255:                   d1->new.to==d2->new.to) {
                    256:                        dup = duplicate(&d1->old,&d2->old);
                    257: /*                             dup=0 means all files differ
                    258:  *                             dup =1 meands files 1&2 identical*/
                    259:                        if(eflag==0) {
                    260:                                separate(dup?"3":"");
                    261:                                change(1,&d1->old,dup);
                    262:                                change(2,&d2->old,0);
                    263:                                d3 = d1->old.to>d1->old.from?d1:d2;
                    264:                                change(3,&d3->new,0);
                    265:                        } else
                    266:                                j = edit(d1,dup,j);
                    267:                        d1++;
                    268:                        d2++;
                    269:                        continue;
                    270:                }
                    271: /*                     overlapping changes from file1 & 2
                    272:  *                     extend changes appropriately to
                    273:  *                     make them coincide*/
                    274:                 if(d1->new.from<d2->new.from) {
                    275:                        d2->old.from -= d2->new.from-d1->new.from;
                    276:                        d2->new.from = d1->new.from;
                    277:                }
                    278:                else if(d2->new.from<d1->new.from) {
                    279:                        d1->old.from -= d1->new.from-d2->new.from;
                    280:                        d1->new.from = d2->new.from;
                    281:                }
                    282:                if(d1->new.to >d2->new.to) {
                    283:                        d2->old.to += d1->new.to - d2->new.to;
                    284:                        d2->new.to = d1->new.to;
                    285:                }
                    286:                else if(d2->new.to >d1->new.to) {
                    287:                        d1->old.to += d2->new.to - d1->new.to;
                    288:                        d1->new.to = d2->new.to;
                    289:                }
                    290:        }
                    291:        if(eflag)
                    292:                edscript(j);
                    293: }
                    294: 
                    295: separate(s)
                    296: char *s;
                    297: {
                    298:        printf("====%s\n",s);
                    299: }
                    300: 
                    301: /*     the range of ines rold.from thru rold.to in file i
                    302:  *     is to be changed. it is to be printed only if
                    303:  *     it does not duplicate something to be printed later
                    304: */
                    305: change(i,rold,dup)
                    306: struct range *rold;
                    307: {
                    308:        printf("%d:",i);
                    309:        last[i] = rold->to;
                    310:        prange(rold);
                    311:        if(dup)
                    312:                return;
                    313:        if(debug)
                    314:                return;
                    315:        i--;
                    316:        (void)skip(i,rold->from,(char *)0);
                    317:        (void)skip(i,rold->to,"  ");
                    318: }
                    319: 
                    320: /*     print the range of line numbers, rold.from  thru rold.to
                    321:  *     as n1,n2 or n1
                    322: */
                    323: prange(rold)
                    324: struct range *rold;
                    325: {
                    326:        if(rold->to<=rold->from)
                    327:                printf("%da\n",rold->from-1);
                    328:        else {
                    329:                printf("%d",rold->from);
                    330:                if(rold->to > rold->from+1)
                    331:                        printf(",%d",rold->to-1);
                    332:                printf("c\n");
                    333:        }
                    334: }
                    335: 
                    336: /*     no difference was reported by diff between file 1(or 2)
                    337:  *     and file 3, and an artificial dummy difference (trange)
                    338:  *     must be ginned up to correspond to the change reported
                    339:  *     in the other file
                    340: */
                    341: keep(i,rnew)
                    342: struct range *rnew;
                    343: {
                    344:        register delta;
                    345:        struct range trange;
                    346:        delta = last[3] - last[i];
                    347:        trange.from = rnew->from - delta;
                    348:        trange.to = rnew->to - delta;
                    349:        change(i,&trange,1);
                    350: }
                    351: 
                    352: /*     skip to just befor line number from in file i
                    353:  *     if "pr" is nonzero, print all skipped stuff
                    354:  * w   with string pr as a prefix
                    355: */
                    356: skip(i,from,pr)
                    357: char *pr;
                    358: {
                    359:        register j,n;
                    360:        for(n=0;cline[i]<from-1;n+=j) {
                    361:                if((j=getline(fp[i]))==0)
                    362:                        trouble();
                    363:                if(pr)
                    364:                        printf("%s%s",pr,line);
                    365:                cline[i]++;
                    366:        }
                    367:        return(n);
                    368: }
                    369: 
                    370: /*     return 1 or 0 according as the old range
                    371:  *     (in file 1) contains exactly the same data
                    372:  *     as the new range (in file 2)
                    373: */
                    374: duplicate(r1,r2)
                    375: struct range *r1, *r2;
                    376: {
                    377:        register c,d;
                    378:        register nchar;
                    379:        int nline;
                    380:        if(r1->to-r1->from != r2->to-r2->from)
                    381:                return(0);
                    382:        (void)skip(0,r1->from,(char *)0);
                    383:        (void)skip(1,r2->from,(char *)0);
                    384:        nchar = 0;
                    385:        for(nline=0;nline<r1->to-r1->from;nline++) {
                    386:                do {
                    387:                        c = getc(fp[0]);
                    388:                        d = getc(fp[1]);
                    389:                        if(c== -1||d== -1)
                    390:                                trouble();
                    391:                        nchar++;
                    392:                        if(c!=d) {
                    393:                                repos(nchar);
                    394:                                return(0);
                    395:                        }
                    396:                } while(c!= '\n');
                    397:        }
                    398:        repos(nchar);
                    399:        return(1);
                    400: }
                    401: 
                    402: repos(nchar)
                    403: {
                    404:        register i;
                    405:        for(i=0;i<2;i++) 
                    406:                (void)fseek(fp[i], (long)-nchar, 1);
                    407: }
                    408: 
                    409: trouble()
                    410: {
                    411:        fprintf(stderr,"diff3: logic error\n");
                    412:        abort();
                    413: }
                    414: 
                    415: /*     collect an editing script for later regurgitation
                    416: */
                    417: edit(diff,dup,j)
                    418: struct diff *diff;
                    419: {
                    420:        if(((dup+1)&eflag)==0)
                    421:                return(j);
                    422:        j++;
                    423:         overlap[j] = !dup;
                    424:         if (!dup) overlapcnt++;
                    425:        de[j].old.from = diff->old.from;
                    426:        de[j].old.to = diff->old.to;
                    427:        de[j].new.from = de[j-1].new.to
                    428:            +skip(2,diff->new.from,(char *)0);
                    429:        de[j].new.to = de[j].new.from
                    430:            +skip(2,diff->new.to,(char *)0);
                    431:        return(j);
                    432: }
                    433: 
                    434: /*             regurgitate */
                    435: edscript(n)
                    436: {
                    437:        register j,k;
                    438:        char block[BUFSIZ];
                    439:        for(n=n;n>0;n--) {
                    440:                 if (!oflag || !overlap[n]) 
                    441:                         prange(&de[n].old);
                    442:                 else
                    443:                         printf("%da\n=======\n", de[n].old.to -1);
                    444:                (void)fseek(fp[2], (long)de[n].new.from, 0);
                    445:                for(k=de[n].new.to-de[n].new.from;k>0;k-= j) {
                    446:                        j = k>BUFSIZ?BUFSIZ:k;
                    447:                        if(fread(block,1,j,fp[2])!=j)
                    448:                                trouble();
                    449:                        (void)fwrite(block, 1, j, stdout);
                    450:                }
                    451:                 if (!oflag || !overlap[n]) 
                    452:                         printf(".\n");
                    453:                 else {
                    454:                         printf("%s\n.\n",f3mark);
                    455:                         printf("%da\n%s\n.\n",de[n].old.from-1,f1mark);
                    456:                 }
                    457:        }
                    458:         exit(overlapcnt);
                    459: }

unix.superglobalmegacorp.com

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