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

Defined functions

change defined in line 278; used 8 times
digit defined in line 138; used 2 times
duplicate defined in line 347; used 1 times
edit defined in line 390; used 1 times
edscript defined in line 406; used 1 times
getchange defined in line 143; used 1 times
  • in line 94
getline defined in line 152; used 2 times
keep defined in line 314; used 2 times
main defined in line 45; never used
merge defined in line 169; used 1 times
  • in line 74
number defined in line 128; used 4 times
prange defined in line 296; used 2 times
readin defined in line 85; used 2 times
repos defined in line 375; used 2 times
separate defined in line 268; used 3 times
skip defined in line 329; used 6 times
trouble defined in line 382; used 3 times

Defined variables

cline defined in line 37; used 2 times
d13 defined in line 28; used 4 times
d23 defined in line 29; used 4 times
de defined in line 30; used 10 times
debug defined in line 43; used 2 times
eflag defined in line 42; used 8 times
last defined in line 41; used 3 times
linct defined in line 33; never used
line defined in line 31; used 6 times

Defined struct's

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

Defined macros

NC defined in line 21; used 4 times
Last modified: 1981-07-10
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1084
Valid CSS Valid XHTML 1.0 Strict