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