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