1: #include <stdio.h> 2: #include <ctype.h> 3: #include <sys/types.h> 4: #include <sys/stat.h> 5: 6: #define C 3 7: #define RANGE 30 8: #define LEN 255 9: #define INF 16384 10: 11: char *text[2][RANGE]; 12: long lineno[2] = {1, 1}; /*no. of 1st stored line in each file*/ 13: int ntext[2]; /*number of stored lines in each*/ 14: long n0,n1; /*scan pointer in each*/ 15: int bflag; 16: int debug = 0; 17: FILE *file[2]; 18: 19: /* return pointer to line n of file f*/ 20: char *getl(f,n) 21: long n; 22: { 23: register char *t; 24: char *malloc(); 25: register delta, nt; 26: again: 27: delta = n - lineno[f]; 28: nt = ntext[f]; 29: if(delta<0) 30: progerr("1"); 31: if(delta<nt) 32: return(text[f][delta]); 33: if(delta>nt) 34: progerr("2"); 35: if(nt>=RANGE) 36: progerr("3"); 37: if(feof(file[f])) 38: return(NULL); 39: t = text[f][nt]; 40: if(t==0) { 41: t = text[f][nt] = malloc(LEN+1); 42: if(t==NULL) 43: if(hardsynch()) 44: goto again; 45: else 46: progerr("5"); 47: } 48: t = fgets(t,LEN,file[f]); 49: if(t!=NULL) 50: ntext[f]++; 51: return(t); 52: } 53: 54: /*remove thru line n of file f from storage*/ 55: clrl(f,n) 56: long n; 57: { 58: register i,j; 59: j = n-lineno[f]+1; 60: for(i=0;i+j<ntext[f];i++) 61: movstr(text[f][i+j],text[f][i]); 62: lineno[f] = n+1; 63: ntext[f] -= j; 64: } 65: 66: movstr(s,t) 67: register char *s, *t; 68: { 69: while(*t++= *s++) 70: continue; 71: } 72: 73: main(argc,argv) 74: char **argv; 75: { 76: char *s0,*s1; 77: FILE *dopen(); 78: if(*argv[1]=='-') { 79: argc--; 80: argv++; 81: while(*++argv[0]) 82: if(*argv[0]=='b') 83: bflag++; 84: } 85: if(argc!=3) 86: error("must have 2 file arguments",""); 87: file[0] = dopen(argv[1],argv[2]); 88: file[1] = dopen(argv[2],argv[1]); 89: for(;;) { 90: s0 = getl(0,++n0); 91: s1 = getl(1,++n1); 92: if(s0==NULL||s1==NULL) 93: break; 94: if(cmp(s0,s1)!=0) { 95: if(!easysynch()&&!hardsynch()) 96: progerr("5"); 97: } else { 98: clrl(0,n0); 99: clrl(1,n1); 100: } 101: } 102: if(s0==NULL&&s1==NULL) 103: return; 104: if(s0==NULL) 105: output(-1,INF); 106: if(s1==NULL) 107: output(INF,-1); 108: } 109: 110: /* synch on C successive matches*/ 111: easysynch() 112: { 113: int i,j; 114: register k,m; 115: char *s0,*s1; 116: for(i=j=1;i<RANGE&&j<RANGE;i++,j++) { 117: s0 = getl(0,n0+i); 118: if(s0==NULL) 119: return(output(INF,INF)); 120: for(k=C-1;k<j;k++) { 121: for(m=0;m<C;m++) 122: if(cmp(getl(0,n0+i-m), 123: getl(1,n1+k-m))!=0) 124: goto cont1; 125: return(output(i-C,k-C)); 126: cont1: ; 127: } 128: s1 = getl(1,n1+j); 129: if(s1==NULL) 130: return(output(INF,INF)); 131: for(k=C-1;k<=i;k++) { 132: for(m=0;m<C;m++) 133: if(cmp(getl(0,n0+k-m), 134: getl(1,n1+j-m))!=0) 135: goto cont2; 136: return(output(k-C,j-C)); 137: cont2: ; 138: } 139: } 140: return(0); 141: } 142: 143: output(a,b) 144: { 145: register i; 146: char *s; 147: if(a<0) 148: change(n0-1,0,n1,b,"a"); 149: else if(b<0) 150: change(n0,a,n1-1,0,"d"); 151: else 152: change(n0,a,n1,b,"c"); 153: for(i=0;i<=a;i++) { 154: s = getl(0,n0+i); 155: if(s==NULL) 156: break; 157: printf("< %s",s); 158: clrl(0,n0+i); 159: } 160: n0 += i-1; 161: if(a>=0&&b>=0) 162: printf("---\n"); 163: for(i=0;i<=b;i++) { 164: s = getl(1,n1+i); 165: if(s==NULL) 166: break; 167: printf("> %s",s); 168: clrl(1,n1+i); 169: } 170: n1 += i-1; 171: return(1); 172: } 173: 174: change(a,b,c,d,s) 175: long a,c; 176: char *s; 177: { 178: range(a,b); 179: printf("%s",s); 180: range(c,d); 181: printf("\n"); 182: } 183: 184: range(a,b) 185: long a; 186: { 187: if(b==INF) 188: printf("%ld,$",a); 189: else if(b==0) 190: printf("%ld",a); 191: else 192: printf("%ld,%ld",a,a+b); 193: } 194: 195: cmp(s,t) 196: char *s,*t; 197: { 198: if(debug) 199: printf("%s:%s\n",s,t); 200: for(;;){ 201: if(bflag&&isspace(*s)&&isspace(*t)) { 202: while(isspace(*++s)) ; 203: while(isspace(*++t)) ; 204: } 205: if(*s!=*t||*s==0) 206: break; 207: s++; 208: t++; 209: } 210: return(*s-*t); 211: } 212: 213: FILE *dopen(f1,f2) 214: char *f1,*f2; 215: { 216: FILE *f; 217: char b[100],*bptr,*eptr; 218: struct stat statbuf; 219: if(cmp(f1,"-")==0) 220: if(cmp(f2,"-")==0) 221: error("can't do - -",""); 222: else 223: return(stdin); 224: if(stat(f1,&statbuf)==-1) 225: error("can't access ",f1); 226: if((statbuf.st_mode&S_IFMT)==S_IFDIR) { 227: for(bptr=b;*bptr= *f1++;bptr++) ; 228: *bptr++ = '/'; 229: for(eptr=f2;*eptr;eptr++) 230: if(*eptr=='/'&&eptr[1]!=0&&eptr[1]!='/') 231: f2 = eptr+1; 232: while(*bptr++= *f2++) ; 233: f1 = b; 234: } 235: f = fopen(f1,"r"); 236: if(f==NULL) 237: error("can't open",f1); 238: return(f); 239: } 240: 241: 242: progerr(s) 243: char *s; 244: { 245: error("program error ",s); 246: } 247: 248: error(s,t) 249: char *s,*t; 250: { 251: fprintf(stderr,"diffh: %s%s\n",s,t); 252: exit(1); 253: } 254: 255: /*stub for resychronization beyond limits of text buf*/ 256: hardsynch() 257: { 258: change(n0,INF,n1,INF,"c"); 259: printf("---change record omitted\n"); 260: error("can't resynchronize",""); 261: return(0); 262: }