xref: /original-bsd/usr.bin/diff/diffh/diffh.c (revision 30d60fbe)
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