|
|
1.1 ! root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.