Annotation of 3BSD/cmd/diff3/diff3.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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