1 /*-
2  * Copyright (c) 1991, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.proprietary.c%
6  */
7 
8 #ifndef lint
9 static char copyright[] =
10 "@(#) Copyright (c) 1991, 1993\n\
11 	The Regents of the University of California.  All rights reserved.\n";
12 #endif /* not lint */
13 
14 #ifndef lint
15 static char sccsid[] = "@(#)old.fgrep.c	8.1 (Berkeley) 06/06/93";
16 #endif /* not lint */
17 
18 /*
19  * fgrep -- print all lines containing any of a set of keywords
20  *
21  *	status returns:
22  *		0 - ok, and some matches
23  *		1 - ok, but no matches
24  *		2 - some error
25  */
26 
27 #include <stdio.h>
28 #include <ctype.h>
29 #include <sys/param.h>
30 #include <sys/stat.h>
31 
32 #define BLKSIZE 8192
33 #define	MAXSIZ 6000
34 #define QSIZE 400
35 struct words {
36 	char 	inp;
37 	char	out;
38 	struct	words *nst;
39 	struct	words *link;
40 	struct	words *fail;
41 } w[MAXSIZ], *smax, *q;
42 
43 long	lnum;
44 int	bflag, cflag, fflag, lflag, nflag, vflag, xflag, yflag;
45 int	hflag	= 1;
46 int	oflag;
47 int	sflag;
48 int	retcode = 0;
49 int	nfile;
50 long	blkno;
51 int	nsucc;
52 long	tln;
53 FILE	*wordf;
54 char	*argptr;
55 
56 main(argc, argv)
57 char **argv;
58 {
59 	while (--argc > 0 && (++argv)[0][0]=='-')
60 		switch (argv[0][1]) {
61 
62 		case 's':
63 			sflag++;
64 			continue;
65 
66 		case 'h':
67 			hflag = 0;
68 			continue;
69 
70 		case 'o':
71 			oflag++;
72 			continue;
73 
74 		case 'b':
75 			bflag++;
76 			continue;
77 
78 		case 'c':
79 			cflag++;
80 			continue;
81 
82 		case 'e':
83 			argc--;
84 			argv++;
85 			goto out;
86 
87 		case 'f':
88 			fflag++;
89 			continue;
90 
91 		case 'l':
92 			lflag++;
93 			continue;
94 
95 		case 'n':
96 			nflag++;
97 			continue;
98 
99 		case 'v':
100 			vflag++;
101 			continue;
102 
103 		case 'x':
104 			xflag++;
105 			continue;
106 
107 		case 'i':		/* Berkeley */
108 		case 'y':		/* Btl */
109 			yflag++;
110 			continue;
111 		default:
112 			fprintf(stderr, "fgrep: unknown flag\n");
113 			continue;
114 		}
115 out:
116 	if (argc<=0)
117 		exit(2);
118 	if (fflag) {
119 		wordf = fopen(*argv, "r");
120 		if (wordf==NULL) {
121 			fprintf(stderr, "fgrep: can't open %s\n", *argv);
122 			exit(2);
123 		}
124 	}
125 	else argptr = *argv;
126 	argc--;
127 	argv++;
128 
129 	cgotofn();
130 	cfail();
131 	nfile = argc;
132 	if (argc<=0) {
133 		if (lflag) exit(1);
134 		execute((char *)NULL);
135 	}
136 	else while (--argc >= 0) {
137 		execute(*argv);
138 		argv++;
139 	}
140 	exit(retcode != 0 ? retcode : nsucc == 0);
141 }
142 
143 # define ccomp(a,b) (yflag ? lca(a)==lca(b) : a==b)
144 # define lca(x) (isupper(x) ? tolower(x) : x)
145 execute(file)
146 char *file;
147 {
148 	register struct words *c;
149 	register ccount;
150 	register char ch;
151 	register char *p;
152 	static char *buf;
153 	static int blksize;
154 	struct stat stb;
155 	int f;
156 	int failed;
157 	char *nlp;
158 	if (file) {
159 		if ((f = open(file, 0)) < 0) {
160 			fprintf(stderr, "fgrep: can't open %s\n", file);
161 			retcode = 2;
162 			return;
163 		}
164 	}
165 	else f = 0;
166 	if (buf == NULL) {
167 		if (fstat(f, &stb) > 0 && stb.st_blksize > 0)
168 			blksize = stb.st_blksize;
169 		else
170 			blksize = BLKSIZE;
171 		buf = (char *)malloc(2*blksize);
172 		if (buf == NULL) {
173 			fprintf(stderr, "egrep: no memory for %s\n", file);
174 			retcode = 2;
175 			return;
176 		}
177 	}
178 	ccount = 0;
179 	failed = 0;
180 	lnum = 1;
181 	tln = 0;
182 	blkno = 0;
183 	p = buf;
184 	nlp = p;
185 	c = w;
186 	for (;;) {
187 		if (--ccount <= 0) {
188 			if (p == &buf[2*blksize]) p = buf;
189 			if (p > &buf[blksize]) {
190 				if ((ccount = read(f, p, &buf[2*blksize] - p)) <= 0) break;
191 			}
192 			else if ((ccount = read(f, p, blksize)) <= 0) break;
193 			blkno += ccount;
194 		}
195 		nstate:
196 			if (ccomp(c->inp, *p)) {
197 				c = c->nst;
198 			}
199 			else if (c->link != 0) {
200 				c = c->link;
201 				goto nstate;
202 			}
203 			else {
204 				c = c->fail;
205 				failed = 1;
206 				if (c==0) {
207 					c = w;
208 					istate:
209 					if (ccomp(c->inp ,  *p)) {
210 						c = c->nst;
211 					}
212 					else if (c->link != 0) {
213 						c = c->link;
214 						goto istate;
215 					}
216 				}
217 				else goto nstate;
218 			}
219 		if (c->out) {
220 			while (*p++ != '\n') {
221 				if (--ccount <= 0) {
222 					if (p == &buf[2*blksize]) p = buf;
223 					if (p > &buf[blksize]) {
224 						if ((ccount = read(f, p, &buf[2*blksize] - p)) <= 0) break;
225 					}
226 					else if ((ccount = read(f, p, blksize)) <= 0) break;
227 					blkno += ccount;
228 				}
229 			}
230 			if ( (vflag && (failed == 0 || xflag == 0)) || (vflag == 0 && xflag && failed) )
231 				goto nomatch;
232 	succeed:	nsucc = 1;
233 			if (cflag) tln++;
234 			else if (sflag)
235 				;	/* ugh */
236 			else if (lflag) {
237 				printf("%s\n", file);
238 				close(f);
239 				return;
240 			}
241 			else {
242 				if (nfile > 1 && hflag || oflag) printf("%s:", file);
243 				if (bflag) printf("%ld:", (blkno-ccount-1)/DEV_BSIZE);
244 				if (nflag) printf("%ld:", lnum);
245 				if (p <= nlp) {
246 					while (nlp < &buf[2*blksize]) putchar(*nlp++);
247 					nlp = buf;
248 				}
249 				while (nlp < p) putchar(*nlp++);
250 			}
251 	nomatch:	lnum++;
252 			nlp = p;
253 			c = w;
254 			failed = 0;
255 			continue;
256 		}
257 		if (*p++ == '\n')
258 			if (vflag) goto succeed;
259 			else {
260 				lnum++;
261 				nlp = p;
262 				c = w;
263 				failed = 0;
264 			}
265 	}
266 	close(f);
267 	if (cflag) {
268 		if (nfile > 1)
269 			printf("%s:", file);
270 		printf("%ld\n", tln);
271 	}
272 }
273 
274 getargc()
275 {
276 	register c;
277 	if (wordf)
278 		return(getc(wordf));
279 	if ((c = *argptr++) == '\0')
280 		return(EOF);
281 	return(c);
282 }
283 
284 cgotofn() {
285 	register c;
286 	register struct words *s;
287 
288 	s = smax = w;
289 nword:	for(;;) {
290 		c = getargc();
291 		if (c==EOF)
292 			return;
293 		if (c == '\n') {
294 			if (xflag) {
295 				for(;;) {
296 					if (s->inp == c) {
297 						s = s->nst;
298 						break;
299 					}
300 					if (s->inp == 0) goto nenter;
301 					if (s->link == 0) {
302 						if (smax >= &w[MAXSIZ -1]) overflo();
303 						s->link = ++smax;
304 						s = smax;
305 						goto nenter;
306 					}
307 					s = s->link;
308 				}
309 			}
310 			s->out = 1;
311 			s = w;
312 		} else {
313 		loop:	if (s->inp == c) {
314 				s = s->nst;
315 				continue;
316 			}
317 			if (s->inp == 0) goto enter;
318 			if (s->link == 0) {
319 				if (smax >= &w[MAXSIZ - 1]) overflo();
320 				s->link = ++smax;
321 				s = smax;
322 				goto enter;
323 			}
324 			s = s->link;
325 			goto loop;
326 		}
327 	}
328 
329 	enter:
330 	do {
331 		s->inp = c;
332 		if (smax >= &w[MAXSIZ - 1]) overflo();
333 		s->nst = ++smax;
334 		s = smax;
335 	} while ((c = getargc()) != '\n' && c!=EOF);
336 	if (xflag) {
337 	nenter:	s->inp = '\n';
338 		if (smax >= &w[MAXSIZ -1]) overflo();
339 		s->nst = ++smax;
340 	}
341 	smax->out = 1;
342 	s = w;
343 	if (c != EOF)
344 		goto nword;
345 }
346 
347 overflo() {
348 	fprintf(stderr, "wordlist too large\n");
349 	exit(2);
350 }
351 cfail() {
352 	struct words *queue[QSIZE];
353 	struct words **front, **rear;
354 	struct words *state;
355 	int bstart;
356 	register char c;
357 	register struct words *s;
358 	s = w;
359 	front = rear = queue;
360 init:	if ((s->inp) != 0) {
361 		*rear++ = s->nst;
362 		if (rear >= &queue[QSIZE - 1]) overflo();
363 	}
364 	if ((s = s->link) != 0) {
365 		goto init;
366 	}
367 
368 	while (rear!=front) {
369 		s = *front;
370 		if (front == &queue[QSIZE-1])
371 			front = queue;
372 		else front++;
373 	cloop:	if ((c = s->inp) != 0) {
374 			bstart = 0;
375 			*rear = (q = s->nst);
376 			if (front < rear)
377 				if (rear >= &queue[QSIZE-1])
378 					if (front == queue) overflo();
379 					else rear = queue;
380 				else rear++;
381 			else
382 				if (++rear == front) overflo();
383 			state = s->fail;
384 		floop:	if (state == 0) {
385 				state = w;
386 				bstart = 1;
387 			}
388 			if (state->inp == c) {
389 			qloop:	q->fail = state->nst;
390 				if ((state->nst)->out == 1) q->out = 1;
391 				if ((q = q->link) != 0) goto qloop;
392 			}
393 			else if ((state = state->link) != 0)
394 				goto floop;
395 			else if(bstart == 0){
396 				state = 0;
397 				goto floop;
398 			}
399 		}
400 		if ((s = s->link) != 0)
401 			goto cloop;
402 	}
403 }
404