1 static char sccsid[] = "@(#)diffh.c 4.4 11/27/85"; 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 register int status = 0; 81 82 while(*argv[1]=='-') { 83 argc--; 84 argv++; 85 while(*++argv[0]) 86 if(*argv[0]=='b') 87 bflag++; 88 } 89 if(argc!=3) 90 error("must have 2 file arguments",""); 91 file[0] = dopen(argv[1],argv[2]); 92 file[1] = dopen(argv[2],argv[1]); 93 for(;;) { 94 s0 = getl(0,++n0); 95 s1 = getl(1,++n1); 96 if(s0==NULL||s1==NULL) 97 break; 98 if(cmp(s0,s1)!=0) { 99 if(!easysynch()&&!hardsynch()) 100 progerr("5"); 101 status = 1; 102 } else { 103 clrl(0,n0); 104 clrl(1,n1); 105 } 106 } 107 if(s0==NULL&&s1==NULL) 108 exit(status); 109 if(s0==NULL) 110 output(-1,INF); 111 if(s1==NULL) 112 output(INF,-1); 113 exit(1); 114 } 115 116 /* synch on C successive matches*/ 117 easysynch() 118 { 119 int i,j; 120 register k,m; 121 char *s0,*s1; 122 for(i=j=1;i<RANGE&&j<RANGE;i++,j++) { 123 s0 = getl(0,n0+i); 124 if(s0==NULL) 125 return(output(INF,INF)); 126 for(k=C-1;k<j;k++) { 127 for(m=0;m<C;m++) 128 if(cmp(getl(0,n0+i-m), 129 getl(1,n1+k-m))!=0) 130 goto cont1; 131 return(output(i-C,k-C)); 132 cont1: ; 133 } 134 s1 = getl(1,n1+j); 135 if(s1==NULL) 136 return(output(INF,INF)); 137 for(k=C-1;k<=i;k++) { 138 for(m=0;m<C;m++) 139 if(cmp(getl(0,n0+k-m), 140 getl(1,n1+j-m))!=0) 141 goto cont2; 142 return(output(k-C,j-C)); 143 cont2: ; 144 } 145 } 146 return(0); 147 } 148 149 output(a,b) 150 { 151 register i; 152 char *s; 153 if(a<0) 154 change(n0-1,0,n1,b,"a"); 155 else if(b<0) 156 change(n0,a,n1-1,0,"d"); 157 else 158 change(n0,a,n1,b,"c"); 159 for(i=0;i<=a;i++) { 160 s = getl(0,n0+i); 161 if(s==NULL) 162 break; 163 printf("< %s",s); 164 clrl(0,n0+i); 165 } 166 n0 += i-1; 167 if(a>=0&&b>=0) 168 printf("---\n"); 169 for(i=0;i<=b;i++) { 170 s = getl(1,n1+i); 171 if(s==NULL) 172 break; 173 printf("> %s",s); 174 clrl(1,n1+i); 175 } 176 n1 += i-1; 177 return(1); 178 } 179 180 change(a,b,c,d,s) 181 long a,c; 182 char *s; 183 { 184 range(a,b); 185 printf("%s",s); 186 range(c,d); 187 printf("\n"); 188 } 189 190 range(a,b) 191 long a; 192 { 193 if(b==INF) 194 printf("%ld,$",a); 195 else if(b==0) 196 printf("%ld",a); 197 else 198 printf("%ld,%ld",a,a+b); 199 } 200 201 cmp(s,t) 202 char *s,*t; 203 { 204 if(debug) 205 printf("%s:%s\n",s,t); 206 for(;;){ 207 if(bflag&&isspace(*s)&&isspace(*t)) { 208 while(isspace(*++s)) ; 209 while(isspace(*++t)) ; 210 } 211 if(*s!=*t||*s==0) 212 break; 213 s++; 214 t++; 215 } 216 return(*s-*t); 217 } 218 219 FILE *dopen(f1,f2) 220 char *f1,*f2; 221 { 222 FILE *f; 223 char b[100],*bptr,*eptr; 224 struct stat statbuf; 225 if(cmp(f1,"-")==0) 226 if(cmp(f2,"-")==0) 227 error("can't do - -",""); 228 else 229 return(stdin); 230 if(stat(f1,&statbuf)==-1) 231 error("can't access ",f1); 232 if((statbuf.st_mode&S_IFMT)==S_IFDIR) { 233 for(bptr=b;*bptr= *f1++;bptr++) ; 234 *bptr++ = '/'; 235 for(eptr=f2;*eptr;eptr++) 236 if(*eptr=='/'&&eptr[1]!=0&&eptr[1]!='/') 237 f2 = eptr+1; 238 while(*bptr++= *f2++) ; 239 f1 = b; 240 } 241 f = fopen(f1,"r"); 242 if(f==NULL) 243 error("can't open",f1); 244 return(f); 245 } 246 247 248 progerr(s) 249 char *s; 250 { 251 error("program error ",s); 252 } 253 254 error(s,t) 255 char *s,*t; 256 { 257 fprintf(stderr,"diffh: %s%s\n",s,t); 258 exit(2); 259 } 260 261 /*stub for resychronization beyond limits of text buf*/ 262 hardsynch() 263 { 264 change(n0,INF,n1,INF,"c"); 265 printf("---change record omitted\n"); 266 error("can't resynchronize",""); 267 return(0); 268 } 269