Annotation of 43BSDReno/usr.bin/diff/diff3/diff3.c, revision 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.