xref: /original-bsd/old/refer/refer/glue5.c (revision 93152bbe)
1 /*-
2  * %sccs.include.proprietary.c%
3  */
4 
5 #ifndef lint
6 static char sccsid[] = "@(#)glue5.c	4.3 (Berkeley) 04/18/91";
7 #endif /* not lint */
8 
9 #include <stdio.h>
10 #include <ctype.h>
11 /*
12  * fgrep -- print all lines containing any of a set of keywords
13  *
14  *	status returns:
15  *		0 - ok, and some matches
16  *		1 - ok, but no matches
17  *		2 - some error
18  */
19 #define	MAXSIZ 700
20 #define QSIZE 400
21 struct words {
22 	char 	inp;
23 	char	out;
24 	struct	words *nst;
25 	struct	words *link;
26 	struct	words *fail;
27 }
28 *www, *smax, *q;
29 
30 char	buf[2*BUFSIZ];
31 int	nsucc;
32 int	need;
33 char	*instr;
34 int	inct;
35 int	rflag;
36 int	xargc;
37 char	**xargv;
38 int	numwords;
39 int	nfound;
40 static int flag = 0;
41 
42 fgrep(argc, argv)
43 char **argv;
44 {
45 	nsucc = need = inct = rflag = numwords = nfound = 0;
46 	instr = 0;
47 	flag = 0;
48 	if (www==0)
49 		www = (struct words *) zalloc(MAXSIZ, sizeof (*www));
50 	if (www==NULL)
51 		err("Can't get space for machines", 0);
52 	for (q=www; q<www+MAXSIZ; q++) {
53 		q->inp =0; q->out =0; q->nst =0; q->link =0; q->fail =0;
54 	}
55 	xargc = argc-1;
56 	xargv = argv+1;
57 	while (xargc>0 && xargv[0][0]=='-')
58 		{
59 		switch(xargv[0][1])
60 			{
61 			case 'r': /* return value only */
62 				rflag++;
63 				break;
64 			case 'n': /* number of answers needed */
65 				need = (int) xargv[1];
66 				xargv++; xargc--;
67 				break;
68 			case 'i':
69 				instr = xargv[1];
70 				inct = (int) xargv[2]+2;
71 # if D2
72 fprintf(stderr,"inct %d xargv.2. %o %d\n",inct, xargv[2],xargv[2]);
73 # endif
74 				xargv += 2; xargc -= 2;
75 				break;
76 			}
77 		xargv++; xargc--;
78 		}
79 	if (xargc<=0)
80 		{
81 		write (2, "bad fgrep call\n", 15);
82 		exit(2);
83 		}
84 # if D1
85 	fprintf(stderr, "before cgoto\n");
86 # endif
87 	cgotofn();
88 # if D1
89 	fprintf(stderr, "before cfail\n");
90 # endif
91 	cfail();
92 # if D1
93 	fprintf(stderr, "before execute instr %.20s\n", instr? instr: "");
94 	fprintf(stderr, "end of string %d %c %c %c\n", inct, instr[inct-3],
95 		instr[inct-2], instr[inct-1]);
96 # endif
97 	execute();
98 # if D1
99 	fprintf(stderr, "returning nsucc %d\n", nsucc);
100 	fprintf(stderr, "fgrep done www %o\n",www);
101 # endif
102 	return(nsucc == 0);
103 }
104 
105 execute()
106 {
107 	register char *p;
108 	register struct words *c;
109 	register ch;
110 	register ccount;
111 	int f;
112 	char *nlp;
113 	f=0;
114 	ccount = instr ? inct : 0;
115 	nfound=0;
116 	p = instr ? instr : buf;
117 	if (need == 0) need = numwords;
118 	nlp = p;
119 	c = www;
120 # if D2
121 fprintf(stderr, "in execute ccount %d inct %d\n",ccount, inct );
122 # endif
123 	for (;;) {
124 # if D3
125 fprintf(stderr, "down ccount\n");
126 # endif
127 		if (--ccount <= 0) {
128 # if D2
129 fprintf(stderr, "ex loop ccount %d instr %o\n",ccount, instr);
130 # endif
131 			if (instr) break;
132 			if (p == &buf[2*BUFSIZ]) p = buf;
133 			if (p > &buf[BUFSIZ]) {
134 				if ((ccount = read(f, p, &buf[2*BUFSIZ] - p)) <= 0) break;
135 			}
136 			else if ((ccount = read(f, p, BUFSIZ)) <= 0) break;
137 # if D2
138 fprintf(stderr, " normal read %d bytres\n", ccount);
139 {char xx[20]; sprintf(xx, "they are %%.%ds\n", ccount);
140 fprintf(stderr, xx, p);
141 }
142 # endif
143 		}
144 nstate:
145 		ch = *p;
146 # if D2
147 fprintf(stderr, "roaming along in ex ch %c c %o\n",ch,c);
148 # endif
149 		if (isupper(ch)) ch |= 040;
150 		if (c->inp == ch) {
151 			c = c->nst;
152 		}
153 		else if (c->link != 0) {
154 			c = c->link;
155 			goto nstate;
156 		}
157 		else {
158 			c = c->fail;
159 			if (c==0) {
160 				c = www;
161 istate:
162 				if (c->inp == ch) {
163 					c = c->nst;
164 				}
165 				else if (c->link != 0) {
166 					c = c->link;
167 					goto istate;
168 				}
169 			}
170 			else goto nstate;
171 		}
172 		if (c->out && new (c)) {
173 # if D2
174 fprintf(stderr, " found: nfound %d need %d\n",nfound,need);
175 # endif
176 			if (++nfound >= need)
177 			{
178 # if D1
179 fprintf(stderr, "found, p %o nlp %o ccount %d buf %o buf[2*BUFSIZ] %o\n",p,nlp,ccount,buf,buf+2*BUFSIZ);
180 # endif
181 				if (instr==0)
182 				while (*p++ != '\n') {
183 # if D3
184 fprintf(stderr, "down ccount2\n");
185 # endif
186 					if (--ccount <= 0) {
187 						if (p == &buf[2*BUFSIZ]) p = buf;
188 						if (p > &buf[BUFSIZ]) {
189 							if ((ccount = read(f, p, &buf[2*BUFSIZ] - p)) <= 0) break;
190 						}
191 						else if ((ccount = read(f, p, BUFSIZ)) <= 0) break;
192 # if D2
193 fprintf(stderr, " read %d bytes\n",ccount);
194 { char xx[20]; sprintf(xx, "they are %%.%ds\n", ccount);
195 fprintf(stderr, xx, p);
196 }
197 # endif
198 					}
199 				}
200 				nsucc = 1;
201 				if (rflag==0)
202 					{
203 # if D2
204 fprintf(stderr, "p %o nlp %o buf %o\n",p,nlp,buf);
205 if (p>nlp)
206 {write (2, "XX\n", 3); write (2, nlp, p-nlp); write (2, "XX\n", 3);}
207 # endif
208 					if (p > nlp) write(1, nlp, p-nlp);
209 					else {
210 						write(1, nlp, &buf[2*BUFSIZ] - nlp);
211 						write(1, buf, p-&buf[0]);
212 						}
213 					if (p[-1]!= '\n') write (1, "\n", 1);
214 					}
215 				if (instr==0)
216 					{
217 					nlp = p;
218 					c = www;
219 					nfound=0;
220 					}
221 			}
222 			else
223 				ccount++;
224 			continue;
225 		}
226 # if D2
227 fprintf(stderr, "nr end loop p %o\n",p);
228 # endif
229 		if (instr)
230 			p++;
231 		else
232 		if (*p++ == '\n')
233 		{
234 			nlp = p;
235 			c = www;
236 			nfound=0;
237 		}
238 	}
239 	if (instr==0)
240 		close(f);
241 }
242 
243 cgotofn() {
244 	register c;
245 	register struct words *s;
246 	s = smax = www;
247 nword:
248 	for(;;) {
249 # if D1
250 	fprintf(stderr, " in for loop c now %o %c\n",c, c>' ' ? c : ' ');
251 # endif
252 		if ((c = gch())==0) return;
253 		else if (c == '\n') {
254 			s->out = 1;
255 			s = www;
256 		}
257 		else {
258 loop:
259 			if (s->inp == c) {
260 				s = s->nst;
261 				continue;
262 			}
263 			if (s->inp == 0) goto enter;
264 			if (s->link == 0) {
265 				if (smax >= &www[MAXSIZ - 1]) overflo();
266 				s->link = ++smax;
267 				s = smax;
268 				goto enter;
269 			}
270 			s = s->link;
271 			goto loop;
272 		}
273 	}
274 
275 enter:
276 	do {
277 		s->inp = c;
278 		if (smax >= &www[MAXSIZ - 1]) overflo();
279 		s->nst = ++smax;
280 		s = smax;
281 	}
282 	while ((c = gch()) != '\n');
283 	smax->out = 1;
284 	s = www;
285 	numwords++;
286 	goto nword;
287 
288 }
289 
290 gch()
291 {
292 	static char *s;
293 	if (flag==0)
294 	{
295 		flag=1;
296 		s = *xargv++;
297 # if D1
298 	fprintf(stderr, "next arg is %s xargc %d\n",s,xargc);
299 # endif
300 		if (xargc-- <=0) return(0);
301 	}
302 	if (*s) return(*s++);
303 	for(flag=0; flag<2*BUFSIZ; flag++)
304 		buf[flag]=0;
305 	flag=0;
306 	return('\n');
307 }
308 
309 overflo() {
310 	write(2,"wordlist too large\n", 19);
311 	exit(2);
312 }
313 cfail() {
314 	struct words *queue[QSIZE];
315 	struct words **front, **rear;
316 	struct words *state;
317 	register char c;
318 	register struct words *s;
319 	s = www;
320 	front = rear = queue;
321 init:
322 	if ((s->inp) != 0) {
323 		*rear++ = s->nst;
324 		if (rear >= &queue[QSIZE - 1]) overflo();
325 	}
326 	if ((s = s->link) != 0) {
327 		goto init;
328 	}
329 
330 	while (rear!=front) {
331 		s = *front;
332 		if (front == &queue[QSIZE-1])
333 			front = queue;
334 		else front++;
335 cloop:
336 		if ((c = s->inp) != 0) {
337 			*rear = (q = s->nst);
338 			if (front < rear)
339 				if (rear >= &queue[QSIZE-1])
340 					if (front == queue) overflo();
341 					else rear = queue;
342 			else rear++;
343 			else
344 				if (++rear == front) overflo();
345 			state = s->fail;
346 floop:
347 			if (state == 0) state = www;
348 			if (state->inp == c) {
349 				q->fail = state->nst;
350 				if ((state->nst)->out == 1) q->out = 1;
351 				continue;
352 			}
353 			else if ((state = state->link) != 0)
354 				goto floop;
355 		}
356 		if ((s = s->link) != 0)
357 			goto cloop;
358 	}
359 }
360 
361 static int seen[50];
362 new (x)
363 {
364 	int i;
365 	for(i=0; i<nfound; i++)
366 		if (seen[i]==x)
367 			return(0);
368 	seen[i]=x;
369 	return(1);
370 }
371