Annotation of 42BSD/usr.bin/diff3/diff3.c, revision 1.1

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

unix.superglobalmegacorp.com

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