Annotation of researchv10dc/cmd/diff3/diff3.c, revision 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[512];
        !           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>512?512: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.