1*21395Smckusick static char *sccsid = "@(#)old.fgrep.c	4.3 (Berkeley) 05/30/85";
21010Sbill /*
31010Sbill  * fgrep -- print all lines containing any of a set of keywords
41010Sbill  *
51010Sbill  *	status returns:
61010Sbill  *		0 - ok, and some matches
71010Sbill  *		1 - ok, but no matches
81010Sbill  *		2 - some error
91010Sbill  */
101010Sbill 
118726Smckusick #include <stdio.h>
128726Smckusick #include <ctype.h>
13*21395Smckusick #include <sys/param.h>
14*21395Smckusick #include <sys/stat.h>
151010Sbill 
16*21395Smckusick #define BLKSIZE 8192
171010Sbill #define	MAXSIZ 6000
181010Sbill #define QSIZE 400
191010Sbill struct words {
201010Sbill 	char 	inp;
211010Sbill 	char	out;
221010Sbill 	struct	words *nst;
231010Sbill 	struct	words *link;
241010Sbill 	struct	words *fail;
251010Sbill } w[MAXSIZ], *smax, *q;
261010Sbill 
271010Sbill long	lnum;
281010Sbill int	bflag, cflag, fflag, lflag, nflag, vflag, xflag, yflag;
291010Sbill int	hflag	= 1;
301010Sbill int	sflag;
311010Sbill int	retcode = 0;
321010Sbill int	nfile;
331010Sbill long	blkno;
341010Sbill int	nsucc;
351010Sbill long	tln;
361010Sbill FILE	*wordf;
371010Sbill char	*argptr;
381010Sbill 
391010Sbill main(argc, argv)
401010Sbill char **argv;
411010Sbill {
421010Sbill 	while (--argc > 0 && (++argv)[0][0]=='-')
431010Sbill 		switch (argv[0][1]) {
441010Sbill 
451010Sbill 		case 's':
461010Sbill 			sflag++;
471010Sbill 			continue;
481010Sbill 
491010Sbill 		case 'h':
501010Sbill 			hflag = 0;
511010Sbill 			continue;
521010Sbill 
531010Sbill 		case 'b':
541010Sbill 			bflag++;
551010Sbill 			continue;
561010Sbill 
571010Sbill 		case 'c':
581010Sbill 			cflag++;
591010Sbill 			continue;
601010Sbill 
611010Sbill 		case 'e':
621010Sbill 			argc--;
631010Sbill 			argv++;
641010Sbill 			goto out;
651010Sbill 
661010Sbill 		case 'f':
671010Sbill 			fflag++;
681010Sbill 			continue;
691010Sbill 
701010Sbill 		case 'l':
711010Sbill 			lflag++;
721010Sbill 			continue;
731010Sbill 
741010Sbill 		case 'n':
751010Sbill 			nflag++;
761010Sbill 			continue;
771010Sbill 
781010Sbill 		case 'v':
791010Sbill 			vflag++;
801010Sbill 			continue;
811010Sbill 
821010Sbill 		case 'x':
831010Sbill 			xflag++;
841010Sbill 			continue;
851010Sbill 
861010Sbill 		case 'i':		/* Berkeley */
871010Sbill 		case 'y':		/* Btl */
881010Sbill 			yflag++;
891010Sbill 			continue;
901010Sbill 		default:
911010Sbill 			fprintf(stderr, "fgrep: unknown flag\n");
921010Sbill 			continue;
931010Sbill 		}
941010Sbill out:
951010Sbill 	if (argc<=0)
961010Sbill 		exit(2);
971010Sbill 	if (fflag) {
981010Sbill 		wordf = fopen(*argv, "r");
991010Sbill 		if (wordf==NULL) {
1001010Sbill 			fprintf(stderr, "fgrep: can't open %s\n", *argv);
1011010Sbill 			exit(2);
1021010Sbill 		}
1031010Sbill 	}
1041010Sbill 	else argptr = *argv;
1051010Sbill 	argc--;
1061010Sbill 	argv++;
1071010Sbill 
1081010Sbill 	cgotofn();
1091010Sbill 	cfail();
1101010Sbill 	nfile = argc;
1111010Sbill 	if (argc<=0) {
1121010Sbill 		if (lflag) exit(1);
1131010Sbill 		execute((char *)NULL);
1141010Sbill 	}
1151010Sbill 	else while (--argc >= 0) {
1161010Sbill 		execute(*argv);
1171010Sbill 		argv++;
1181010Sbill 	}
1191010Sbill 	exit(retcode != 0 ? retcode : nsucc == 0);
1201010Sbill }
1211010Sbill 
1221010Sbill # define ccomp(a,b) (yflag ? lca(a)==lca(b) : a==b)
1231010Sbill # define lca(x) (isupper(x) ? tolower(x) : x)
1241010Sbill execute(file)
1251010Sbill char *file;
1261010Sbill {
1271010Sbill 	register struct words *c;
1281010Sbill 	register ccount;
1291010Sbill 	register char ch;
1301010Sbill 	register char *p;
131*21395Smckusick 	static char *buf;
132*21395Smckusick 	static int blksize;
133*21395Smckusick 	struct stat stb;
1341010Sbill 	int f;
1351010Sbill 	int failed;
1361010Sbill 	char *nlp;
1371010Sbill 	if (file) {
1381010Sbill 		if ((f = open(file, 0)) < 0) {
1391010Sbill 			fprintf(stderr, "fgrep: can't open %s\n", file);
1401010Sbill 			retcode = 2;
1411010Sbill 			return;
1421010Sbill 		}
1431010Sbill 	}
1441010Sbill 	else f = 0;
145*21395Smckusick 	if (buf == NULL) {
146*21395Smckusick 		if (fstat(f, &stb) > 0 && stb.st_blksize > 0)
147*21395Smckusick 			blksize = stb.st_blksize;
148*21395Smckusick 		else
149*21395Smckusick 			blksize = BLKSIZE;
150*21395Smckusick 		buf = (char *)malloc(2*blksize);
151*21395Smckusick 		if (buf == NULL) {
152*21395Smckusick 			fprintf(stderr, "egrep: no memory for %s\n", file);
153*21395Smckusick 			retcode = 2;
154*21395Smckusick 			return;
155*21395Smckusick 		}
156*21395Smckusick 	}
1571010Sbill 	ccount = 0;
1581010Sbill 	failed = 0;
1591010Sbill 	lnum = 1;
1601010Sbill 	tln = 0;
1611010Sbill 	blkno = 0;
1621010Sbill 	p = buf;
1631010Sbill 	nlp = p;
1641010Sbill 	c = w;
1651010Sbill 	for (;;) {
1661010Sbill 		if (--ccount <= 0) {
167*21395Smckusick 			if (p == &buf[2*blksize]) p = buf;
168*21395Smckusick 			if (p > &buf[blksize]) {
169*21395Smckusick 				if ((ccount = read(f, p, &buf[2*blksize] - p)) <= 0) break;
1701010Sbill 			}
171*21395Smckusick 			else if ((ccount = read(f, p, blksize)) <= 0) break;
1721010Sbill 			blkno += ccount;
1731010Sbill 		}
1741010Sbill 		nstate:
1751010Sbill 			if (ccomp(c->inp, *p)) {
1761010Sbill 				c = c->nst;
1771010Sbill 			}
1781010Sbill 			else if (c->link != 0) {
1791010Sbill 				c = c->link;
1801010Sbill 				goto nstate;
1811010Sbill 			}
1821010Sbill 			else {
1831010Sbill 				c = c->fail;
1841010Sbill 				failed = 1;
1851010Sbill 				if (c==0) {
1861010Sbill 					c = w;
1871010Sbill 					istate:
1881010Sbill 					if (ccomp(c->inp ,  *p)) {
1891010Sbill 						c = c->nst;
1901010Sbill 					}
1911010Sbill 					else if (c->link != 0) {
1921010Sbill 						c = c->link;
1931010Sbill 						goto istate;
1941010Sbill 					}
1951010Sbill 				}
1961010Sbill 				else goto nstate;
1971010Sbill 			}
1981010Sbill 		if (c->out) {
1991010Sbill 			while (*p++ != '\n') {
2001010Sbill 				if (--ccount <= 0) {
201*21395Smckusick 					if (p == &buf[2*blksize]) p = buf;
202*21395Smckusick 					if (p > &buf[blksize]) {
203*21395Smckusick 						if ((ccount = read(f, p, &buf[2*blksize] - p)) <= 0) break;
2041010Sbill 					}
205*21395Smckusick 					else if ((ccount = read(f, p, blksize)) <= 0) break;
2061010Sbill 					blkno += ccount;
2071010Sbill 				}
2081010Sbill 			}
2091010Sbill 			if ( (vflag && (failed == 0 || xflag == 0)) || (vflag == 0 && xflag && failed) )
2101010Sbill 				goto nomatch;
2111010Sbill 	succeed:	nsucc = 1;
2121010Sbill 			if (cflag) tln++;
2131010Sbill 			else if (sflag)
2141010Sbill 				;	/* ugh */
2151010Sbill 			else if (lflag) {
2161010Sbill 				printf("%s\n", file);
2171010Sbill 				close(f);
2181010Sbill 				return;
2191010Sbill 			}
2201010Sbill 			else {
2211010Sbill 				if (nfile > 1 && hflag) printf("%s:", file);
222*21395Smckusick 				if (bflag) printf("%ld:", (blkno-ccount-1)/DEV_BSIZE);
2231010Sbill 				if (nflag) printf("%ld:", lnum);
2241010Sbill 				if (p <= nlp) {
225*21395Smckusick 					while (nlp < &buf[2*blksize]) putchar(*nlp++);
2261010Sbill 					nlp = buf;
2271010Sbill 				}
2281010Sbill 				while (nlp < p) putchar(*nlp++);
2291010Sbill 			}
2301010Sbill 	nomatch:	lnum++;
2311010Sbill 			nlp = p;
2321010Sbill 			c = w;
2331010Sbill 			failed = 0;
2341010Sbill 			continue;
2351010Sbill 		}
2361010Sbill 		if (*p++ == '\n')
2371010Sbill 			if (vflag) goto succeed;
2381010Sbill 			else {
2391010Sbill 				lnum++;
2401010Sbill 				nlp = p;
2411010Sbill 				c = w;
2421010Sbill 				failed = 0;
2431010Sbill 			}
2441010Sbill 	}
2451010Sbill 	close(f);
2461010Sbill 	if (cflag) {
2471010Sbill 		if (nfile > 1)
2481010Sbill 			printf("%s:", file);
2491010Sbill 		printf("%ld\n", tln);
2501010Sbill 	}
2511010Sbill }
2521010Sbill 
2531010Sbill getargc()
2541010Sbill {
2551010Sbill 	register c;
2561010Sbill 	if (wordf)
2571010Sbill 		return(getc(wordf));
2581010Sbill 	if ((c = *argptr++) == '\0')
2591010Sbill 		return(EOF);
2601010Sbill 	return(c);
2611010Sbill }
2621010Sbill 
2631010Sbill cgotofn() {
2641010Sbill 	register c;
2651010Sbill 	register struct words *s;
2661010Sbill 
2671010Sbill 	s = smax = w;
2681010Sbill nword:	for(;;) {
2691010Sbill 		c = getargc();
2701010Sbill 		if (c==EOF)
2711010Sbill 			return;
2721010Sbill 		if (c == '\n') {
2731010Sbill 			if (xflag) {
2741010Sbill 				for(;;) {
2751010Sbill 					if (s->inp == c) {
2761010Sbill 						s = s->nst;
2771010Sbill 						break;
2781010Sbill 					}
2791010Sbill 					if (s->inp == 0) goto nenter;
2801010Sbill 					if (s->link == 0) {
2811010Sbill 						if (smax >= &w[MAXSIZ -1]) overflo();
2821010Sbill 						s->link = ++smax;
2831010Sbill 						s = smax;
2841010Sbill 						goto nenter;
2851010Sbill 					}
2861010Sbill 					s = s->link;
2871010Sbill 				}
2881010Sbill 			}
2891010Sbill 			s->out = 1;
2901010Sbill 			s = w;
2911010Sbill 		} else {
2921010Sbill 		loop:	if (s->inp == c) {
2931010Sbill 				s = s->nst;
2941010Sbill 				continue;
2951010Sbill 			}
2961010Sbill 			if (s->inp == 0) goto enter;
2971010Sbill 			if (s->link == 0) {
2981010Sbill 				if (smax >= &w[MAXSIZ - 1]) overflo();
2991010Sbill 				s->link = ++smax;
3001010Sbill 				s = smax;
3011010Sbill 				goto enter;
3021010Sbill 			}
3031010Sbill 			s = s->link;
3041010Sbill 			goto loop;
3051010Sbill 		}
3061010Sbill 	}
3071010Sbill 
3081010Sbill 	enter:
3091010Sbill 	do {
3101010Sbill 		s->inp = c;
3111010Sbill 		if (smax >= &w[MAXSIZ - 1]) overflo();
3121010Sbill 		s->nst = ++smax;
3131010Sbill 		s = smax;
3141010Sbill 	} while ((c = getargc()) != '\n' && c!=EOF);
3151010Sbill 	if (xflag) {
3161010Sbill 	nenter:	s->inp = '\n';
3171010Sbill 		if (smax >= &w[MAXSIZ -1]) overflo();
3181010Sbill 		s->nst = ++smax;
3191010Sbill 	}
3201010Sbill 	smax->out = 1;
3211010Sbill 	s = w;
3221010Sbill 	if (c != EOF)
3231010Sbill 		goto nword;
3241010Sbill }
3251010Sbill 
3261010Sbill overflo() {
3271010Sbill 	fprintf(stderr, "wordlist too large\n");
3281010Sbill 	exit(2);
3291010Sbill }
3301010Sbill cfail() {
3311010Sbill 	struct words *queue[QSIZE];
3321010Sbill 	struct words **front, **rear;
3331010Sbill 	struct words *state;
3341010Sbill 	int bstart;
3351010Sbill 	register char c;
3361010Sbill 	register struct words *s;
3371010Sbill 	s = w;
3381010Sbill 	front = rear = queue;
3391010Sbill init:	if ((s->inp) != 0) {
3401010Sbill 		*rear++ = s->nst;
3411010Sbill 		if (rear >= &queue[QSIZE - 1]) overflo();
3421010Sbill 	}
3431010Sbill 	if ((s = s->link) != 0) {
3441010Sbill 		goto init;
3451010Sbill 	}
3461010Sbill 
3471010Sbill 	while (rear!=front) {
3481010Sbill 		s = *front;
3491010Sbill 		if (front == &queue[QSIZE-1])
3501010Sbill 			front = queue;
3511010Sbill 		else front++;
3521010Sbill 	cloop:	if ((c = s->inp) != 0) {
3531010Sbill 			bstart = 0;
3541010Sbill 			*rear = (q = s->nst);
3551010Sbill 			if (front < rear)
3561010Sbill 				if (rear >= &queue[QSIZE-1])
3571010Sbill 					if (front == queue) overflo();
3581010Sbill 					else rear = queue;
3591010Sbill 				else rear++;
3601010Sbill 			else
3611010Sbill 				if (++rear == front) overflo();
3621010Sbill 			state = s->fail;
3631010Sbill 		floop:	if (state == 0) {
3641010Sbill 				state = w;
3651010Sbill 				bstart = 1;
3661010Sbill 			}
3671010Sbill 			if (state->inp == c) {
3681010Sbill 			qloop:	q->fail = state->nst;
3691010Sbill 				if ((state->nst)->out == 1) q->out = 1;
3701010Sbill 				if ((q = q->link) != 0) goto qloop;
3711010Sbill 			}
3721010Sbill 			else if ((state = state->link) != 0)
3731010Sbill 				goto floop;
3741010Sbill 			else if(bstart == 0){
3751010Sbill 				state = 0;
3761010Sbill 				goto floop;
3771010Sbill 			}
3781010Sbill 		}
3791010Sbill 		if ((s = s->link) != 0)
3801010Sbill 			goto cloop;
3811010Sbill 	}
3821010Sbill }
383