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