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*/
getl(f,n)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*/
clrl(f,n)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
movstr(s,t)83 movstr(s,t)
84 register char *s, *t;
85 {
86 while(*t++= *s++)
87 continue;
88 }
89
main(argc,argv)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*/
easysynch()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
output(a,b)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
change(a,b,c,d,s)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
range(a,b)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
cmp(s,t)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
dopen(f1,f2)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
progerr(s)263 progerr(s)
264 char *s;
265 {
266 error("program error ",s);
267 }
268
error(s,t)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*/
hardsynch()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