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: }

Defined functions

change defined in line 305; used 8 times
digit defined in line 165; used 2 times
duplicate defined in line 374; used 1 times
edit defined in line 417; used 1 times
edscript defined in line 435; used 1 times
getchange defined in line 170; used 1 times
getline defined in line 179; used 2 times
keep defined in line 341; used 2 times
main defined in line 58; never used
merge defined in line 196; used 1 times
number defined in line 155; used 4 times
prange defined in line 323; used 2 times
readin defined in line 112; used 2 times
repos defined in line 402; used 2 times
separate defined in line 295; used 3 times
skip defined in line 356; used 6 times
trouble defined in line 409; used 3 times

Defined variables

cline defined in line 47; used 2 times
d13 defined in line 28; used 4 times
d23 defined in line 29; used 4 times
de defined in line 38; used 12 times
debug defined in line 54; used 2 times
eflag defined in line 52; used 11 times
f1mark defined in line 55; used 2 times
f3mark defined in line 55; used 2 times
last defined in line 51; used 3 times
line defined in line 42; used 6 times
oflag defined in line 53; used 6 times
overlap defined in line 39; used 3 times
overlapcnt defined in line 40; used 2 times
sccsid defined in line 2; never used

Defined struct's

diff defined in line 25; used 12 times
range defined in line 19; used 12 times

Defined macros

NC defined in line 27; used 5 times
Last modified: 1985-08-28
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1690
Valid CSS Valid XHTML 1.0 Strict