1*32365Sbostic static char *sccsid = "@(#)old.fgrep.c	4.4 (Berkeley) 10/07/87";
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>
1321395Smckusick #include <sys/param.h>
1421395Smckusick #include <sys/stat.h>
151010Sbill 
1621395Smckusick #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;
30*32365Sbostic int	oflag;
311010Sbill int	sflag;
321010Sbill int	retcode = 0;
331010Sbill int	nfile;
341010Sbill long	blkno;
351010Sbill int	nsucc;
361010Sbill long	tln;
371010Sbill FILE	*wordf;
381010Sbill char	*argptr;
391010Sbill 
401010Sbill main(argc, argv)
411010Sbill char **argv;
421010Sbill {
431010Sbill 	while (--argc > 0 && (++argv)[0][0]=='-')
441010Sbill 		switch (argv[0][1]) {
451010Sbill 
461010Sbill 		case 's':
471010Sbill 			sflag++;
481010Sbill 			continue;
491010Sbill 
501010Sbill 		case 'h':
511010Sbill 			hflag = 0;
521010Sbill 			continue;
531010Sbill 
54*32365Sbostic 		case 'o':
55*32365Sbostic 			oflag++;
56*32365Sbostic 			continue;
57*32365Sbostic 
581010Sbill 		case 'b':
591010Sbill 			bflag++;
601010Sbill 			continue;
611010Sbill 
621010Sbill 		case 'c':
631010Sbill 			cflag++;
641010Sbill 			continue;
651010Sbill 
661010Sbill 		case 'e':
671010Sbill 			argc--;
681010Sbill 			argv++;
691010Sbill 			goto out;
701010Sbill 
711010Sbill 		case 'f':
721010Sbill 			fflag++;
731010Sbill 			continue;
741010Sbill 
751010Sbill 		case 'l':
761010Sbill 			lflag++;
771010Sbill 			continue;
781010Sbill 
791010Sbill 		case 'n':
801010Sbill 			nflag++;
811010Sbill 			continue;
821010Sbill 
831010Sbill 		case 'v':
841010Sbill 			vflag++;
851010Sbill 			continue;
861010Sbill 
871010Sbill 		case 'x':
881010Sbill 			xflag++;
891010Sbill 			continue;
901010Sbill 
911010Sbill 		case 'i':		/* Berkeley */
921010Sbill 		case 'y':		/* Btl */
931010Sbill 			yflag++;
941010Sbill 			continue;
951010Sbill 		default:
961010Sbill 			fprintf(stderr, "fgrep: unknown flag\n");
971010Sbill 			continue;
981010Sbill 		}
991010Sbill out:
1001010Sbill 	if (argc<=0)
1011010Sbill 		exit(2);
1021010Sbill 	if (fflag) {
1031010Sbill 		wordf = fopen(*argv, "r");
1041010Sbill 		if (wordf==NULL) {
1051010Sbill 			fprintf(stderr, "fgrep: can't open %s\n", *argv);
1061010Sbill 			exit(2);
1071010Sbill 		}
1081010Sbill 	}
1091010Sbill 	else argptr = *argv;
1101010Sbill 	argc--;
1111010Sbill 	argv++;
1121010Sbill 
1131010Sbill 	cgotofn();
1141010Sbill 	cfail();
1151010Sbill 	nfile = argc;
1161010Sbill 	if (argc<=0) {
1171010Sbill 		if (lflag) exit(1);
1181010Sbill 		execute((char *)NULL);
1191010Sbill 	}
1201010Sbill 	else while (--argc >= 0) {
1211010Sbill 		execute(*argv);
1221010Sbill 		argv++;
1231010Sbill 	}
1241010Sbill 	exit(retcode != 0 ? retcode : nsucc == 0);
1251010Sbill }
1261010Sbill 
1271010Sbill # define ccomp(a,b) (yflag ? lca(a)==lca(b) : a==b)
1281010Sbill # define lca(x) (isupper(x) ? tolower(x) : x)
1291010Sbill execute(file)
1301010Sbill char *file;
1311010Sbill {
1321010Sbill 	register struct words *c;
1331010Sbill 	register ccount;
1341010Sbill 	register char ch;
1351010Sbill 	register char *p;
13621395Smckusick 	static char *buf;
13721395Smckusick 	static int blksize;
13821395Smckusick 	struct stat stb;
1391010Sbill 	int f;
1401010Sbill 	int failed;
1411010Sbill 	char *nlp;
1421010Sbill 	if (file) {
1431010Sbill 		if ((f = open(file, 0)) < 0) {
1441010Sbill 			fprintf(stderr, "fgrep: can't open %s\n", file);
1451010Sbill 			retcode = 2;
1461010Sbill 			return;
1471010Sbill 		}
1481010Sbill 	}
1491010Sbill 	else f = 0;
15021395Smckusick 	if (buf == NULL) {
15121395Smckusick 		if (fstat(f, &stb) > 0 && stb.st_blksize > 0)
15221395Smckusick 			blksize = stb.st_blksize;
15321395Smckusick 		else
15421395Smckusick 			blksize = BLKSIZE;
15521395Smckusick 		buf = (char *)malloc(2*blksize);
15621395Smckusick 		if (buf == NULL) {
15721395Smckusick 			fprintf(stderr, "egrep: no memory for %s\n", file);
15821395Smckusick 			retcode = 2;
15921395Smckusick 			return;
16021395Smckusick 		}
16121395Smckusick 	}
1621010Sbill 	ccount = 0;
1631010Sbill 	failed = 0;
1641010Sbill 	lnum = 1;
1651010Sbill 	tln = 0;
1661010Sbill 	blkno = 0;
1671010Sbill 	p = buf;
1681010Sbill 	nlp = p;
1691010Sbill 	c = w;
1701010Sbill 	for (;;) {
1711010Sbill 		if (--ccount <= 0) {
17221395Smckusick 			if (p == &buf[2*blksize]) p = buf;
17321395Smckusick 			if (p > &buf[blksize]) {
17421395Smckusick 				if ((ccount = read(f, p, &buf[2*blksize] - p)) <= 0) break;
1751010Sbill 			}
17621395Smckusick 			else if ((ccount = read(f, p, blksize)) <= 0) break;
1771010Sbill 			blkno += ccount;
1781010Sbill 		}
1791010Sbill 		nstate:
1801010Sbill 			if (ccomp(c->inp, *p)) {
1811010Sbill 				c = c->nst;
1821010Sbill 			}
1831010Sbill 			else if (c->link != 0) {
1841010Sbill 				c = c->link;
1851010Sbill 				goto nstate;
1861010Sbill 			}
1871010Sbill 			else {
1881010Sbill 				c = c->fail;
1891010Sbill 				failed = 1;
1901010Sbill 				if (c==0) {
1911010Sbill 					c = w;
1921010Sbill 					istate:
1931010Sbill 					if (ccomp(c->inp ,  *p)) {
1941010Sbill 						c = c->nst;
1951010Sbill 					}
1961010Sbill 					else if (c->link != 0) {
1971010Sbill 						c = c->link;
1981010Sbill 						goto istate;
1991010Sbill 					}
2001010Sbill 				}
2011010Sbill 				else goto nstate;
2021010Sbill 			}
2031010Sbill 		if (c->out) {
2041010Sbill 			while (*p++ != '\n') {
2051010Sbill 				if (--ccount <= 0) {
20621395Smckusick 					if (p == &buf[2*blksize]) p = buf;
20721395Smckusick 					if (p > &buf[blksize]) {
20821395Smckusick 						if ((ccount = read(f, p, &buf[2*blksize] - p)) <= 0) break;
2091010Sbill 					}
21021395Smckusick 					else if ((ccount = read(f, p, blksize)) <= 0) break;
2111010Sbill 					blkno += ccount;
2121010Sbill 				}
2131010Sbill 			}
2141010Sbill 			if ( (vflag && (failed == 0 || xflag == 0)) || (vflag == 0 && xflag && failed) )
2151010Sbill 				goto nomatch;
2161010Sbill 	succeed:	nsucc = 1;
2171010Sbill 			if (cflag) tln++;
2181010Sbill 			else if (sflag)
2191010Sbill 				;	/* ugh */
2201010Sbill 			else if (lflag) {
2211010Sbill 				printf("%s\n", file);
2221010Sbill 				close(f);
2231010Sbill 				return;
2241010Sbill 			}
2251010Sbill 			else {
226*32365Sbostic 				if (nfile > 1 && hflag || oflag) printf("%s:", file);
22721395Smckusick 				if (bflag) printf("%ld:", (blkno-ccount-1)/DEV_BSIZE);
2281010Sbill 				if (nflag) printf("%ld:", lnum);
2291010Sbill 				if (p <= nlp) {
23021395Smckusick 					while (nlp < &buf[2*blksize]) putchar(*nlp++);
2311010Sbill 					nlp = buf;
2321010Sbill 				}
2331010Sbill 				while (nlp < p) putchar(*nlp++);
2341010Sbill 			}
2351010Sbill 	nomatch:	lnum++;
2361010Sbill 			nlp = p;
2371010Sbill 			c = w;
2381010Sbill 			failed = 0;
2391010Sbill 			continue;
2401010Sbill 		}
2411010Sbill 		if (*p++ == '\n')
2421010Sbill 			if (vflag) goto succeed;
2431010Sbill 			else {
2441010Sbill 				lnum++;
2451010Sbill 				nlp = p;
2461010Sbill 				c = w;
2471010Sbill 				failed = 0;
2481010Sbill 			}
2491010Sbill 	}
2501010Sbill 	close(f);
2511010Sbill 	if (cflag) {
2521010Sbill 		if (nfile > 1)
2531010Sbill 			printf("%s:", file);
2541010Sbill 		printf("%ld\n", tln);
2551010Sbill 	}
2561010Sbill }
2571010Sbill 
2581010Sbill getargc()
2591010Sbill {
2601010Sbill 	register c;
2611010Sbill 	if (wordf)
2621010Sbill 		return(getc(wordf));
2631010Sbill 	if ((c = *argptr++) == '\0')
2641010Sbill 		return(EOF);
2651010Sbill 	return(c);
2661010Sbill }
2671010Sbill 
2681010Sbill cgotofn() {
2691010Sbill 	register c;
2701010Sbill 	register struct words *s;
2711010Sbill 
2721010Sbill 	s = smax = w;
2731010Sbill nword:	for(;;) {
2741010Sbill 		c = getargc();
2751010Sbill 		if (c==EOF)
2761010Sbill 			return;
2771010Sbill 		if (c == '\n') {
2781010Sbill 			if (xflag) {
2791010Sbill 				for(;;) {
2801010Sbill 					if (s->inp == c) {
2811010Sbill 						s = s->nst;
2821010Sbill 						break;
2831010Sbill 					}
2841010Sbill 					if (s->inp == 0) goto nenter;
2851010Sbill 					if (s->link == 0) {
2861010Sbill 						if (smax >= &w[MAXSIZ -1]) overflo();
2871010Sbill 						s->link = ++smax;
2881010Sbill 						s = smax;
2891010Sbill 						goto nenter;
2901010Sbill 					}
2911010Sbill 					s = s->link;
2921010Sbill 				}
2931010Sbill 			}
2941010Sbill 			s->out = 1;
2951010Sbill 			s = w;
2961010Sbill 		} else {
2971010Sbill 		loop:	if (s->inp == c) {
2981010Sbill 				s = s->nst;
2991010Sbill 				continue;
3001010Sbill 			}
3011010Sbill 			if (s->inp == 0) goto enter;
3021010Sbill 			if (s->link == 0) {
3031010Sbill 				if (smax >= &w[MAXSIZ - 1]) overflo();
3041010Sbill 				s->link = ++smax;
3051010Sbill 				s = smax;
3061010Sbill 				goto enter;
3071010Sbill 			}
3081010Sbill 			s = s->link;
3091010Sbill 			goto loop;
3101010Sbill 		}
3111010Sbill 	}
3121010Sbill 
3131010Sbill 	enter:
3141010Sbill 	do {
3151010Sbill 		s->inp = c;
3161010Sbill 		if (smax >= &w[MAXSIZ - 1]) overflo();
3171010Sbill 		s->nst = ++smax;
3181010Sbill 		s = smax;
3191010Sbill 	} while ((c = getargc()) != '\n' && c!=EOF);
3201010Sbill 	if (xflag) {
3211010Sbill 	nenter:	s->inp = '\n';
3221010Sbill 		if (smax >= &w[MAXSIZ -1]) overflo();
3231010Sbill 		s->nst = ++smax;
3241010Sbill 	}
3251010Sbill 	smax->out = 1;
3261010Sbill 	s = w;
3271010Sbill 	if (c != EOF)
3281010Sbill 		goto nword;
3291010Sbill }
3301010Sbill 
3311010Sbill overflo() {
3321010Sbill 	fprintf(stderr, "wordlist too large\n");
3331010Sbill 	exit(2);
3341010Sbill }
3351010Sbill cfail() {
3361010Sbill 	struct words *queue[QSIZE];
3371010Sbill 	struct words **front, **rear;
3381010Sbill 	struct words *state;
3391010Sbill 	int bstart;
3401010Sbill 	register char c;
3411010Sbill 	register struct words *s;
3421010Sbill 	s = w;
3431010Sbill 	front = rear = queue;
3441010Sbill init:	if ((s->inp) != 0) {
3451010Sbill 		*rear++ = s->nst;
3461010Sbill 		if (rear >= &queue[QSIZE - 1]) overflo();
3471010Sbill 	}
3481010Sbill 	if ((s = s->link) != 0) {
3491010Sbill 		goto init;
3501010Sbill 	}
3511010Sbill 
3521010Sbill 	while (rear!=front) {
3531010Sbill 		s = *front;
3541010Sbill 		if (front == &queue[QSIZE-1])
3551010Sbill 			front = queue;
3561010Sbill 		else front++;
3571010Sbill 	cloop:	if ((c = s->inp) != 0) {
3581010Sbill 			bstart = 0;
3591010Sbill 			*rear = (q = s->nst);
3601010Sbill 			if (front < rear)
3611010Sbill 				if (rear >= &queue[QSIZE-1])
3621010Sbill 					if (front == queue) overflo();
3631010Sbill 					else rear = queue;
3641010Sbill 				else rear++;
3651010Sbill 			else
3661010Sbill 				if (++rear == front) overflo();
3671010Sbill 			state = s->fail;
3681010Sbill 		floop:	if (state == 0) {
3691010Sbill 				state = w;
3701010Sbill 				bstart = 1;
3711010Sbill 			}
3721010Sbill 			if (state->inp == c) {
3731010Sbill 			qloop:	q->fail = state->nst;
3741010Sbill 				if ((state->nst)->out == 1) q->out = 1;
3751010Sbill 				if ((q = q->link) != 0) goto qloop;
3761010Sbill 			}
3771010Sbill 			else if ((state = state->link) != 0)
3781010Sbill 				goto floop;
3791010Sbill 			else if(bstart == 0){
3801010Sbill 				state = 0;
3811010Sbill 				goto floop;
3821010Sbill 			}
3831010Sbill 		}
3841010Sbill 		if ((s = s->link) != 0)
3851010Sbill 			goto cloop;
3861010Sbill 	}
3871010Sbill }
388