1 #if	!defined(lint) && defined(DOSCCS)
2 static	char sccsid[] = "@(#)diffh.c 4.4 11/27/85";
3 #endif
4 
5 #include <stdio.h>
6 #include <ctype.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <stdlib.h>
10 
11 #define C 3
12 #define RANGE 30
13 #define LEN 255
14 #define INF 16384
15 
16 char *text[2][RANGE];
17 long lineno[2] = {1, 1};	/*no. of 1st stored line in each file*/
18 int ntext[2];		/*number of stored lines in each*/
19 long n0,n1;		/*scan pointer in each*/
20 int bflag;
21 int debug = 0;
22 FILE *file[2];
23 
24 /* declarations */
25 void error(char *, char *);
26 char cmp(char *, char *);
27 void range(long, int);
28 void change(long, int, long, int, char *);
29 int output(int, int);
30 void progerr(char *);
31 int hardsynch();
32 int easysynch();
33 void movstr(char *, char *t);
34 void clrl(int, long);
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 	register int delta, nt;
42 again:
43 	delta = n - lineno[f];
44 	nt = ntext[f];
45 	if(delta<0)
46 		progerr("1");
47 	if(delta<nt)
48 		return(text[f][delta]);
49 	if(delta>nt)
50 		progerr("2");
51 	if(nt>=RANGE)
52 		progerr("3");
53 	if(feof(file[f]))
54 		return(NULL);
55 	t = text[f][nt];
56 	if(t==0) {
57 		t = text[f][nt] = malloc(LEN+1);
58 		if(t==NULL) {
59 			if(hardsynch())
60 				goto again;
61 			else
62 				progerr("5");
63 		}
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 void clrl(f,n)
73 long n;
74 {
75 	register int 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 void movstr(s,t)
84 register char *s, *t;
85 {
86 	while((*t++= *s++))
87 		continue;
88 }
89 
main(argc,argv)90 int 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 int easysynch()
133 {
134 	int i,j;
135 	register int 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 int output(a,b)
165 {
166 	register int 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 void 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 void 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 char 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 	}
246 	if(stat(f1,&statbuf)==-1)
247 		error("can't access ",f1);
248 	if((statbuf.st_mode&S_IFMT)==S_IFDIR) {
249 		for(bptr=b;(*bptr= *f1++);bptr++) ;
250 		*bptr++ = '/';
251 		for(eptr=f2;*eptr;eptr++)
252 			if(*eptr=='/'&&eptr[1]!=0&&eptr[1]!='/')
253 				f2 = eptr+1;
254 		while((*bptr++= *f2++)) ;
255 		f1 = b;
256 	}
257 	f = fopen(f1,"r");
258 	if(f==NULL)
259 		error("can't open",f1);
260 	return(f);
261 }
262 
263 
progerr(s)264 void progerr(s)
265 char *s;
266 {
267 	error("program error ",s);
268 }
269 
error(s,t)270 void error(s,t)
271 char *s,*t;
272 {
273 	fprintf(stderr,"diffh: %s%s\n",s,t);
274 	exit(2);
275 }
276 
277 	/*stub for resychronization beyond limits of text buf*/
hardsynch()278 int hardsynch()
279 {
280 	change(n0,INF,n1,INF,"c");
281 	printf("---change record omitted\n");
282 	error("can't resynchronize","");
283 	return(0);
284 }
285