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