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