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