# 2.11BSD#431 - /usr/src/usr.bin/diff3/diff3.c

##### Functions

    change            X
    digit             X
    duplicate         X
    edit              X
    edscript          X
    getchange         X
    getline           X
    keep              X
    main              X
    merge             X
    number            X
    prange            X
    readin            X
    repos             X
    separate          X
    skip              X
    trouble           X

##### Variables

    cline             X
    d13               X
    d23               X
    de                X
    debug             X
    eflag             X
    f1mark            X
    f3mark            X
    last              X
    line              X
    oflag             X
    overlap           X
    overlapcnt        X

##### Macros

    NC                X

##### struct's

    diff              X
    range             X

       1: #if defined(DOSCCS) && !defined(lint)
       2: static char sccsid[] = "@(#)diff3.c	4.4.1 (2.11BSD GTE) 1/1/94";
       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: }

#### Defined functions

change defined in line 305; used 8 times

- in line 218-220(2), 230-231(2), 261-264(3), 349

digit defined in line 165; used 2 times

- in line 160, 174

duplicate defined in line 374; used 1 times

- in line 256

edit defined in line 417; used 1 times

- in line 266

edscript defined in line 435; used 1 times

- in line 292

getchange defined in line 170; used 1 times

- in line 121

getline defined in line 179; used 2 times

- in line 173, 361

keep defined in line 341; used 2 times

- in line 219, 229

main defined in line 58; never used
merge defined in line 196; used 1 times

- in line 101

number defined in line 155; used 4 times

- in line 127-136(4)

prange defined in line 323; used 2 times

- in line 310, 441

readin defined in line 112; used 2 times

- in line 94-95(2)

repos defined in line 402; used 2 times

- in line 393-398(2)

separate defined in line 295; used 3 times

- in line 217, 228, 260

skip defined in line 356; used 6 times

- in line 316-317(2), 382-383(2), 428-430(2)

trouble defined in line 409; used 3 times

- in line 362, 390, 448

#### Defined variables

cline defined in line 47; used 2 times

- in line 360-365(2)

d13 defined in line 28; used 4 times

- in line 94, 202-205(2), 238

d23 defined in line 29; used 4 times

- in line 95, 203-205(2), 246

de defined in line 38; used 12 times

- in line 425-429(6), 441-445(5), 455

debug defined in line 54; used 2 times

- in line 206, 313

eflag defined in line 52; used 11 times

- in line 62-79(6), 216, 227, 259, 291, 420

f1mark defined in line 55; used 2 times

- in line 90, 455

f3mark defined in line 55; used 2 times

- in line 91, 454

last defined in line 51; used 3 times

- in line 309, 346(2)

line defined in line 42; used 6 times

- in line 126, 174, 183-189(3), 364

oflag defined in line 53; used 6 times

- in line 62, 76-79(2), 89, 440, 451

overlap defined in line 39; used 3 times

- in line 423, 440, 451

overlapcnt defined in line 40; used 2 times

- in line 424, 458

sccsid defined in line 2; never used

#### Defined struct's

diff defined in line 25; used 12 times

- in line 28-29(4), 38(2), 114(2), 198(2), 418(2)

range defined in line 19; used 12 times

- in line 25(2), 306(2), 324(2), 342-345(4), 375(2)

#### Defined macros

NC defined in line 27; used 5 times

- in line 28-29(2), 38-39(2), 122

Last modified: 1994-01-11 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1922 |