1*8726Smckusick static char *sccsid = "@(#)old.fgrep.c	4.2 (Berkeley) 10/20/82";
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 
11*8726Smckusick #include <stdio.h>
12*8726Smckusick #include <ctype.h>
131010Sbill 
141010Sbill #define	MAXSIZ 6000
151010Sbill #define QSIZE 400
161010Sbill struct words {
171010Sbill 	char 	inp;
181010Sbill 	char	out;
191010Sbill 	struct	words *nst;
201010Sbill 	struct	words *link;
211010Sbill 	struct	words *fail;
221010Sbill } w[MAXSIZ], *smax, *q;
231010Sbill 
241010Sbill long	lnum;
251010Sbill int	bflag, cflag, fflag, lflag, nflag, vflag, xflag, yflag;
261010Sbill int	hflag	= 1;
271010Sbill int	sflag;
281010Sbill int	retcode = 0;
291010Sbill int	nfile;
301010Sbill long	blkno;
311010Sbill int	nsucc;
321010Sbill long	tln;
331010Sbill FILE	*wordf;
341010Sbill char	*argptr;
351010Sbill 
361010Sbill main(argc, argv)
371010Sbill char **argv;
381010Sbill {
391010Sbill 	while (--argc > 0 && (++argv)[0][0]=='-')
401010Sbill 		switch (argv[0][1]) {
411010Sbill 
421010Sbill 		case 's':
431010Sbill 			sflag++;
441010Sbill 			continue;
451010Sbill 
461010Sbill 		case 'h':
471010Sbill 			hflag = 0;
481010Sbill 			continue;
491010Sbill 
501010Sbill 		case 'b':
511010Sbill 			bflag++;
521010Sbill 			continue;
531010Sbill 
541010Sbill 		case 'c':
551010Sbill 			cflag++;
561010Sbill 			continue;
571010Sbill 
581010Sbill 		case 'e':
591010Sbill 			argc--;
601010Sbill 			argv++;
611010Sbill 			goto out;
621010Sbill 
631010Sbill 		case 'f':
641010Sbill 			fflag++;
651010Sbill 			continue;
661010Sbill 
671010Sbill 		case 'l':
681010Sbill 			lflag++;
691010Sbill 			continue;
701010Sbill 
711010Sbill 		case 'n':
721010Sbill 			nflag++;
731010Sbill 			continue;
741010Sbill 
751010Sbill 		case 'v':
761010Sbill 			vflag++;
771010Sbill 			continue;
781010Sbill 
791010Sbill 		case 'x':
801010Sbill 			xflag++;
811010Sbill 			continue;
821010Sbill 
831010Sbill 		case 'i':		/* Berkeley */
841010Sbill 		case 'y':		/* Btl */
851010Sbill 			yflag++;
861010Sbill 			continue;
871010Sbill 		default:
881010Sbill 			fprintf(stderr, "fgrep: unknown flag\n");
891010Sbill 			continue;
901010Sbill 		}
911010Sbill out:
921010Sbill 	if (argc<=0)
931010Sbill 		exit(2);
941010Sbill 	if (fflag) {
951010Sbill 		wordf = fopen(*argv, "r");
961010Sbill 		if (wordf==NULL) {
971010Sbill 			fprintf(stderr, "fgrep: can't open %s\n", *argv);
981010Sbill 			exit(2);
991010Sbill 		}
1001010Sbill 	}
1011010Sbill 	else argptr = *argv;
1021010Sbill 	argc--;
1031010Sbill 	argv++;
1041010Sbill 
1051010Sbill 	cgotofn();
1061010Sbill 	cfail();
1071010Sbill 	nfile = argc;
1081010Sbill 	if (argc<=0) {
1091010Sbill 		if (lflag) exit(1);
1101010Sbill 		execute((char *)NULL);
1111010Sbill 	}
1121010Sbill 	else while (--argc >= 0) {
1131010Sbill 		execute(*argv);
1141010Sbill 		argv++;
1151010Sbill 	}
1161010Sbill 	exit(retcode != 0 ? retcode : nsucc == 0);
1171010Sbill }
1181010Sbill 
1191010Sbill # define ccomp(a,b) (yflag ? lca(a)==lca(b) : a==b)
1201010Sbill # define lca(x) (isupper(x) ? tolower(x) : x)
1211010Sbill execute(file)
1221010Sbill char *file;
1231010Sbill {
1241010Sbill 	register struct words *c;
1251010Sbill 	register ccount;
1261010Sbill 	register char ch;
1271010Sbill 	register char *p;
1281010Sbill 	char buf[2*BUFSIZ];
1291010Sbill 	int f;
1301010Sbill 	int failed;
1311010Sbill 	char *nlp;
1321010Sbill 	if (file) {
1331010Sbill 		if ((f = open(file, 0)) < 0) {
1341010Sbill 			fprintf(stderr, "fgrep: can't open %s\n", file);
1351010Sbill 			retcode = 2;
1361010Sbill 			return;
1371010Sbill 		}
1381010Sbill 	}
1391010Sbill 	else f = 0;
1401010Sbill 	ccount = 0;
1411010Sbill 	failed = 0;
1421010Sbill 	lnum = 1;
1431010Sbill 	tln = 0;
1441010Sbill 	blkno = 0;
1451010Sbill 	p = buf;
1461010Sbill 	nlp = p;
1471010Sbill 	c = w;
1481010Sbill 	for (;;) {
1491010Sbill 		if (--ccount <= 0) {
1501010Sbill 			if (p == &buf[2*BUFSIZ]) p = buf;
1511010Sbill 			if (p > &buf[BUFSIZ]) {
1521010Sbill 				if ((ccount = read(f, p, &buf[2*BUFSIZ] - p)) <= 0) break;
1531010Sbill 			}
1541010Sbill 			else if ((ccount = read(f, p, BUFSIZ)) <= 0) break;
1551010Sbill 			blkno += ccount;
1561010Sbill 		}
1571010Sbill 		nstate:
1581010Sbill 			if (ccomp(c->inp, *p)) {
1591010Sbill 				c = c->nst;
1601010Sbill 			}
1611010Sbill 			else if (c->link != 0) {
1621010Sbill 				c = c->link;
1631010Sbill 				goto nstate;
1641010Sbill 			}
1651010Sbill 			else {
1661010Sbill 				c = c->fail;
1671010Sbill 				failed = 1;
1681010Sbill 				if (c==0) {
1691010Sbill 					c = w;
1701010Sbill 					istate:
1711010Sbill 					if (ccomp(c->inp ,  *p)) {
1721010Sbill 						c = c->nst;
1731010Sbill 					}
1741010Sbill 					else if (c->link != 0) {
1751010Sbill 						c = c->link;
1761010Sbill 						goto istate;
1771010Sbill 					}
1781010Sbill 				}
1791010Sbill 				else goto nstate;
1801010Sbill 			}
1811010Sbill 		if (c->out) {
1821010Sbill 			while (*p++ != '\n') {
1831010Sbill 				if (--ccount <= 0) {
1841010Sbill 					if (p == &buf[2*BUFSIZ]) p = buf;
1851010Sbill 					if (p > &buf[BUFSIZ]) {
1861010Sbill 						if ((ccount = read(f, p, &buf[2&BUFSIZ] - p)) <= 0) break;
1871010Sbill 					}
1881010Sbill 					else if ((ccount = read(f, p, BUFSIZ)) <= 0) break;
1891010Sbill 					blkno += ccount;
1901010Sbill 				}
1911010Sbill 			}
1921010Sbill 			if ( (vflag && (failed == 0 || xflag == 0)) || (vflag == 0 && xflag && failed) )
1931010Sbill 				goto nomatch;
1941010Sbill 	succeed:	nsucc = 1;
1951010Sbill 			if (cflag) tln++;
1961010Sbill 			else if (sflag)
1971010Sbill 				;	/* ugh */
1981010Sbill 			else if (lflag) {
1991010Sbill 				printf("%s\n", file);
2001010Sbill 				close(f);
2011010Sbill 				return;
2021010Sbill 			}
2031010Sbill 			else {
2041010Sbill 				if (nfile > 1 && hflag) printf("%s:", file);
2051010Sbill 				if (bflag) printf("%ld:", (blkno-ccount-1)/BUFSIZ);
2061010Sbill 				if (nflag) printf("%ld:", lnum);
2071010Sbill 				if (p <= nlp) {
2081010Sbill 					while (nlp < &buf[2*BUFSIZ]) putchar(*nlp++);
2091010Sbill 					nlp = buf;
2101010Sbill 				}
2111010Sbill 				while (nlp < p) putchar(*nlp++);
2121010Sbill 			}
2131010Sbill 	nomatch:	lnum++;
2141010Sbill 			nlp = p;
2151010Sbill 			c = w;
2161010Sbill 			failed = 0;
2171010Sbill 			continue;
2181010Sbill 		}
2191010Sbill 		if (*p++ == '\n')
2201010Sbill 			if (vflag) goto succeed;
2211010Sbill 			else {
2221010Sbill 				lnum++;
2231010Sbill 				nlp = p;
2241010Sbill 				c = w;
2251010Sbill 				failed = 0;
2261010Sbill 			}
2271010Sbill 	}
2281010Sbill 	close(f);
2291010Sbill 	if (cflag) {
2301010Sbill 		if (nfile > 1)
2311010Sbill 			printf("%s:", file);
2321010Sbill 		printf("%ld\n", tln);
2331010Sbill 	}
2341010Sbill }
2351010Sbill 
2361010Sbill getargc()
2371010Sbill {
2381010Sbill 	register c;
2391010Sbill 	if (wordf)
2401010Sbill 		return(getc(wordf));
2411010Sbill 	if ((c = *argptr++) == '\0')
2421010Sbill 		return(EOF);
2431010Sbill 	return(c);
2441010Sbill }
2451010Sbill 
2461010Sbill cgotofn() {
2471010Sbill 	register c;
2481010Sbill 	register struct words *s;
2491010Sbill 
2501010Sbill 	s = smax = w;
2511010Sbill nword:	for(;;) {
2521010Sbill 		c = getargc();
2531010Sbill 		if (c==EOF)
2541010Sbill 			return;
2551010Sbill 		if (c == '\n') {
2561010Sbill 			if (xflag) {
2571010Sbill 				for(;;) {
2581010Sbill 					if (s->inp == c) {
2591010Sbill 						s = s->nst;
2601010Sbill 						break;
2611010Sbill 					}
2621010Sbill 					if (s->inp == 0) goto nenter;
2631010Sbill 					if (s->link == 0) {
2641010Sbill 						if (smax >= &w[MAXSIZ -1]) overflo();
2651010Sbill 						s->link = ++smax;
2661010Sbill 						s = smax;
2671010Sbill 						goto nenter;
2681010Sbill 					}
2691010Sbill 					s = s->link;
2701010Sbill 				}
2711010Sbill 			}
2721010Sbill 			s->out = 1;
2731010Sbill 			s = w;
2741010Sbill 		} else {
2751010Sbill 		loop:	if (s->inp == c) {
2761010Sbill 				s = s->nst;
2771010Sbill 				continue;
2781010Sbill 			}
2791010Sbill 			if (s->inp == 0) goto enter;
2801010Sbill 			if (s->link == 0) {
2811010Sbill 				if (smax >= &w[MAXSIZ - 1]) overflo();
2821010Sbill 				s->link = ++smax;
2831010Sbill 				s = smax;
2841010Sbill 				goto enter;
2851010Sbill 			}
2861010Sbill 			s = s->link;
2871010Sbill 			goto loop;
2881010Sbill 		}
2891010Sbill 	}
2901010Sbill 
2911010Sbill 	enter:
2921010Sbill 	do {
2931010Sbill 		s->inp = c;
2941010Sbill 		if (smax >= &w[MAXSIZ - 1]) overflo();
2951010Sbill 		s->nst = ++smax;
2961010Sbill 		s = smax;
2971010Sbill 	} while ((c = getargc()) != '\n' && c!=EOF);
2981010Sbill 	if (xflag) {
2991010Sbill 	nenter:	s->inp = '\n';
3001010Sbill 		if (smax >= &w[MAXSIZ -1]) overflo();
3011010Sbill 		s->nst = ++smax;
3021010Sbill 	}
3031010Sbill 	smax->out = 1;
3041010Sbill 	s = w;
3051010Sbill 	if (c != EOF)
3061010Sbill 		goto nword;
3071010Sbill }
3081010Sbill 
3091010Sbill overflo() {
3101010Sbill 	fprintf(stderr, "wordlist too large\n");
3111010Sbill 	exit(2);
3121010Sbill }
3131010Sbill cfail() {
3141010Sbill 	struct words *queue[QSIZE];
3151010Sbill 	struct words **front, **rear;
3161010Sbill 	struct words *state;
3171010Sbill 	int bstart;
3181010Sbill 	register char c;
3191010Sbill 	register struct words *s;
3201010Sbill 	s = w;
3211010Sbill 	front = rear = queue;
3221010Sbill init:	if ((s->inp) != 0) {
3231010Sbill 		*rear++ = s->nst;
3241010Sbill 		if (rear >= &queue[QSIZE - 1]) overflo();
3251010Sbill 	}
3261010Sbill 	if ((s = s->link) != 0) {
3271010Sbill 		goto init;
3281010Sbill 	}
3291010Sbill 
3301010Sbill 	while (rear!=front) {
3311010Sbill 		s = *front;
3321010Sbill 		if (front == &queue[QSIZE-1])
3331010Sbill 			front = queue;
3341010Sbill 		else front++;
3351010Sbill 	cloop:	if ((c = s->inp) != 0) {
3361010Sbill 			bstart = 0;
3371010Sbill 			*rear = (q = s->nst);
3381010Sbill 			if (front < rear)
3391010Sbill 				if (rear >= &queue[QSIZE-1])
3401010Sbill 					if (front == queue) overflo();
3411010Sbill 					else rear = queue;
3421010Sbill 				else rear++;
3431010Sbill 			else
3441010Sbill 				if (++rear == front) overflo();
3451010Sbill 			state = s->fail;
3461010Sbill 		floop:	if (state == 0) {
3471010Sbill 				state = w;
3481010Sbill 				bstart = 1;
3491010Sbill 			}
3501010Sbill 			if (state->inp == c) {
3511010Sbill 			qloop:	q->fail = state->nst;
3521010Sbill 				if ((state->nst)->out == 1) q->out = 1;
3531010Sbill 				if ((q = q->link) != 0) goto qloop;
3541010Sbill 			}
3551010Sbill 			else if ((state = state->link) != 0)
3561010Sbill 				goto floop;
3571010Sbill 			else if(bstart == 0){
3581010Sbill 				state = 0;
3591010Sbill 				goto floop;
3601010Sbill 			}
3611010Sbill 		}
3621010Sbill 		if ((s = s->link) != 0)
3631010Sbill 			goto cloop;
3641010Sbill 	}
3651010Sbill }
366