148264Sbostic /*-
2*62021Sbostic  * Copyright (c) 1991, 1993
3*62021Sbostic  *	The Regents of the University of California.  All rights reserved.
448264Sbostic  *
548264Sbostic  * %sccs.include.proprietary.c%
648264Sbostic  */
748264Sbostic 
814464Ssam #ifndef lint
9*62021Sbostic static char copyright[] =
10*62021Sbostic "@(#) Copyright (c) 1991, 1993\n\
11*62021Sbostic 	The Regents of the University of California.  All rights reserved.\n";
1248264Sbostic #endif /* not lint */
136641Smckusick 
1448264Sbostic #ifndef lint
15*62021Sbostic static char sccsid[] = "@(#)old.bin.grep.c	8.1 (Berkeley) 06/06/93";
1648264Sbostic #endif /* not lint */
1748264Sbostic 
186641Smckusick /*
196641Smckusick  * grep -- print lines matching (or not matching) a pattern
206641Smckusick  *
216641Smckusick  *	status returns:
226641Smckusick  *		0 - ok, and some matches
236641Smckusick  *		1 - ok, but no matches
246641Smckusick  *		2 - some error
256641Smckusick  */
266641Smckusick 
276641Smckusick #include <stdio.h>
286641Smckusick #include <ctype.h>
296641Smckusick 
306641Smckusick #define	CBRA	1
316641Smckusick #define	CCHR	2
326641Smckusick #define	CDOT	4
336641Smckusick #define	CCL	6
346641Smckusick #define	NCCL	8
356641Smckusick #define	CDOL	10
366641Smckusick #define	CEOF	11
376641Smckusick #define	CKET	12
3813484Ssam #define	CBRC	14
3913484Ssam #define	CLET	15
406641Smckusick #define	CBACK	18
416641Smckusick 
426641Smckusick #define	STAR	01
436641Smckusick 
446641Smckusick #define	LBSIZE	BUFSIZ
456641Smckusick #define	ESIZE	256
466641Smckusick #define	NBRA	9
476641Smckusick 
486641Smckusick char	expbuf[ESIZE];
496641Smckusick long	lnum;
506641Smckusick char	linebuf[LBSIZE+1];
516641Smckusick char	ybuf[ESIZE];
526641Smckusick int	bflag;
536641Smckusick int	lflag;
546641Smckusick int	nflag;
556641Smckusick int	cflag;
566641Smckusick int	vflag;
576641Smckusick int	nfile;
586641Smckusick int	hflag	= 1;
5932365Sbostic int	oflag;
606641Smckusick int	sflag;
616641Smckusick int	yflag;
6213484Ssam int	wflag;
6311579Sedward int	retcode = 0;
646641Smckusick int	circf;
656641Smckusick int	blkno;
666641Smckusick long	tln;
676641Smckusick int	nsucc;
686641Smckusick char	*braslist[NBRA];
696641Smckusick char	*braelist[NBRA];
706641Smckusick char	bittab[] = {
716641Smckusick 	1,
726641Smckusick 	2,
736641Smckusick 	4,
746641Smckusick 	8,
756641Smckusick 	16,
766641Smckusick 	32,
776641Smckusick 	64,
786641Smckusick 	128
796641Smckusick };
806641Smckusick 
main(argc,argv)816641Smckusick main(argc, argv)
8233378Sbostic 	int argc;
8333378Sbostic 	char **argv;
846641Smckusick {
8533378Sbostic 	extern char *optarg;
8633378Sbostic 	extern int optind;
8733378Sbostic 	int ch;
886641Smckusick 
8954252Sbostic 	while ((ch = getopt(argc, argv, "iywohsvblcne:")) != EOF)
9033378Sbostic 		switch((char)ch) {
9113484Ssam 		case 'i':
926641Smckusick 		case 'y':
936641Smckusick 			yflag++;
9433378Sbostic 			break;
9513484Ssam 		case 'w':
9613484Ssam 			wflag++;
9733378Sbostic 			break;
9832365Sbostic 		case 'o':
9932365Sbostic 			oflag++;
10033378Sbostic 			break;
1016641Smckusick 		case 'h':
1026641Smckusick 			hflag = 0;
10333378Sbostic 			break;
1046641Smckusick 		case 's':
1056641Smckusick 			sflag++;
10633378Sbostic 			break;
1076641Smckusick 		case 'v':
1086641Smckusick 			vflag++;
10933378Sbostic 			break;
1106641Smckusick 		case 'b':
1116641Smckusick 			bflag++;
11233378Sbostic 			break;
1136641Smckusick 		case 'l':
1146641Smckusick 			lflag++;
11533378Sbostic 			break;
1166641Smckusick 		case 'c':
1176641Smckusick 			cflag++;
11833378Sbostic 			break;
1196641Smckusick 		case 'n':
1206641Smckusick 			nflag++;
12133378Sbostic 			break;
1226641Smckusick 		case 'e':
12354252Sbostic 			argv += optind - 1;
12454252Sbostic 			argc -= optind - 1;
12533378Sbostic 			*argv = optarg;
1266641Smckusick 			goto out;
12733378Sbostic 		case '?':
1286641Smckusick 		default:
1296641Smckusick 			errexit("grep: unknown flag\n", (char *)NULL);
1306641Smckusick 		}
13133378Sbostic 	argv += optind;
13233378Sbostic 	argc -= optind;
13333378Sbostic 
1346641Smckusick out:
1356641Smckusick 	if (argc<=0)
1366641Smckusick 		exit(2);
1376641Smckusick 	if (yflag) {
1386641Smckusick 		register char *p, *s;
1396641Smckusick 		for (s = ybuf, p = *argv; *p; ) {
1406641Smckusick 			if (*p == '\\') {
1416641Smckusick 				*s++ = *p++;
1426641Smckusick 				if (*p)
1436641Smckusick 					*s++ = *p++;
1446641Smckusick 			} else if (*p == '[') {
1456641Smckusick 				while (*p != '\0' && *p != ']')
1466641Smckusick 					*s++ = *p++;
1476641Smckusick 			} else if (islower(*p)) {
1486641Smckusick 				*s++ = '[';
1496641Smckusick 				*s++ = toupper(*p);
1506641Smckusick 				*s++ = *p++;
1516641Smckusick 				*s++ = ']';
1526641Smckusick 			} else
1536641Smckusick 				*s++ = *p++;
1546641Smckusick 			if (s >= ybuf+ESIZE-5)
1556641Smckusick 				errexit("grep: argument too long\n", (char *)NULL);
1566641Smckusick 		}
1576641Smckusick 		*s = '\0';
1586641Smckusick 		*argv = ybuf;
1596641Smckusick 	}
1606641Smckusick 	compile(*argv);
1616641Smckusick 	nfile = --argc;
1626641Smckusick 	if (argc<=0) {
1636641Smckusick 		if (lflag)
1646641Smckusick 			exit(1);
1656641Smckusick 		execute((char *)NULL);
1666641Smckusick 	} else while (--argc >= 0) {
1676641Smckusick 		argv++;
1686641Smckusick 		execute(*argv);
1696641Smckusick 	}
17011579Sedward 	exit(retcode != 0 ? retcode : nsucc == 0);
1716641Smckusick }
1726641Smckusick 
compile(astr)1736641Smckusick compile(astr)
1746641Smckusick char *astr;
1756641Smckusick {
1766641Smckusick 	register c;
1776641Smckusick 	register char *ep, *sp;
1786641Smckusick 	char *cstart;
1796641Smckusick 	char *lastep;
1806641Smckusick 	int cclcnt;
1816641Smckusick 	char bracket[NBRA], *bracketp;
1826641Smckusick 	int closed;
1836641Smckusick 	char numbra;
1846641Smckusick 	char neg;
1856641Smckusick 
1866641Smckusick 	ep = expbuf;
1876641Smckusick 	sp = astr;
1886641Smckusick 	lastep = 0;
1896641Smckusick 	bracketp = bracket;
1906641Smckusick 	closed = numbra = 0;
1916641Smckusick 	if (*sp == '^') {
1926641Smckusick 		circf++;
1936641Smckusick 		sp++;
1946641Smckusick 	}
19513484Ssam 	if (wflag)
19613484Ssam 		*ep++ = CBRC;
1976641Smckusick 	for (;;) {
1986641Smckusick 		if (ep >= &expbuf[ESIZE])
1996641Smckusick 			goto cerror;
2006641Smckusick 		if ((c = *sp++) != '*')
2016641Smckusick 			lastep = ep;
2026641Smckusick 		switch (c) {
2036641Smckusick 
2046641Smckusick 		case '\0':
20513484Ssam 			if (wflag)
20613484Ssam 				*ep++ = CLET;
2076641Smckusick 			*ep++ = CEOF;
2086641Smckusick 			return;
2096641Smckusick 
2106641Smckusick 		case '.':
2116641Smckusick 			*ep++ = CDOT;
2126641Smckusick 			continue;
2136641Smckusick 
2146641Smckusick 		case '*':
21513484Ssam 			if (lastep==0 || *lastep==CBRA || *lastep==CKET ||
21613484Ssam 			    *lastep == CBRC || *lastep == CLET)
2176641Smckusick 				goto defchar;
2186641Smckusick 			*lastep |= STAR;
2196641Smckusick 			continue;
2206641Smckusick 
2216641Smckusick 		case '$':
2226641Smckusick 			if (*sp != '\0')
2236641Smckusick 				goto defchar;
2246641Smckusick 			*ep++ = CDOL;
2256641Smckusick 			continue;
2266641Smckusick 
2276641Smckusick 		case '[':
2286641Smckusick 			if(&ep[17] >= &expbuf[ESIZE])
2296641Smckusick 				goto cerror;
2306641Smckusick 			*ep++ = CCL;
2316641Smckusick 			neg = 0;
2326641Smckusick 			if((c = *sp++) == '^') {
2336641Smckusick 				neg = 1;
2346641Smckusick 				c = *sp++;
2356641Smckusick 			}
2366641Smckusick 			cstart = sp;
2376641Smckusick 			do {
2386641Smckusick 				if (c=='\0')
2396641Smckusick 					goto cerror;
2406641Smckusick 				if (c=='-' && sp>cstart && *sp!=']') {
2416641Smckusick 					for (c = sp[-2]; c<*sp; c++)
2426641Smckusick 						ep[c>>3] |= bittab[c&07];
2436641Smckusick 					sp++;
2446641Smckusick 				}
2456641Smckusick 				ep[c>>3] |= bittab[c&07];
2466641Smckusick 			} while((c = *sp++) != ']');
2476641Smckusick 			if(neg) {
2486641Smckusick 				for(cclcnt = 0; cclcnt < 16; cclcnt++)
2496641Smckusick 					ep[cclcnt] ^= -1;
2506641Smckusick 				ep[0] &= 0376;
2516641Smckusick 			}
2526641Smckusick 
2536641Smckusick 			ep += 16;
2546641Smckusick 
2556641Smckusick 			continue;
2566641Smckusick 
2576641Smckusick 		case '\\':
25813484Ssam 			if((c = *sp++) == 0)
25913484Ssam 				goto cerror;
26013484Ssam 			if(c == '<') {
26113484Ssam 				*ep++ = CBRC;
26213484Ssam 				continue;
26313484Ssam 			}
26413484Ssam 			if(c == '>') {
26513484Ssam 				*ep++ = CLET;
26613484Ssam 				continue;
26713484Ssam 			}
26813484Ssam 			if(c == '(') {
2696641Smckusick 				if(numbra >= NBRA) {
2706641Smckusick 					goto cerror;
2716641Smckusick 				}
2726641Smckusick 				*bracketp++ = numbra;
2736641Smckusick 				*ep++ = CBRA;
2746641Smckusick 				*ep++ = numbra++;
2756641Smckusick 				continue;
2766641Smckusick 			}
2776641Smckusick 			if(c == ')') {
2786641Smckusick 				if(bracketp <= bracket) {
2796641Smckusick 					goto cerror;
2806641Smckusick 				}
2816641Smckusick 				*ep++ = CKET;
2826641Smckusick 				*ep++ = *--bracketp;
2836641Smckusick 				closed++;
2846641Smckusick 				continue;
2856641Smckusick 			}
2866641Smckusick 
2876641Smckusick 			if(c >= '1' && c <= '9') {
2886641Smckusick 				if((c -= '1') >= closed)
2896641Smckusick 					goto cerror;
2906641Smckusick 				*ep++ = CBACK;
2916641Smckusick 				*ep++ = c;
2926641Smckusick 				continue;
2936641Smckusick 			}
2946641Smckusick 
2956641Smckusick 		defchar:
2966641Smckusick 		default:
2976641Smckusick 			*ep++ = CCHR;
2986641Smckusick 			*ep++ = c;
2996641Smckusick 		}
3006641Smckusick 	}
3016641Smckusick     cerror:
3026641Smckusick 	errexit("grep: RE error\n", (char *)NULL);
3036641Smckusick }
3046641Smckusick 
execute(file)3056641Smckusick execute(file)
3066641Smckusick char *file;
3076641Smckusick {
3086641Smckusick 	register char *p1, *p2;
3096641Smckusick 	register c;
3106641Smckusick 
3116641Smckusick 	if (file) {
31211579Sedward 		if (freopen(file, "r", stdin) == NULL) {
31312096Smckusick 			perror(file);
31411579Sedward 			retcode = 2;
31511579Sedward 		}
3166641Smckusick 	}
3176641Smckusick 	lnum = 0;
3186641Smckusick 	tln = 0;
3196641Smckusick 	for (;;) {
3206641Smckusick 		lnum++;
3216641Smckusick 		p1 = linebuf;
3226641Smckusick 		while ((c = getchar()) != '\n') {
3236641Smckusick 			if (c == EOF) {
3246641Smckusick 				if (cflag) {
3256641Smckusick 					if (nfile>1)
3266641Smckusick 						printf("%s:", file);
3276641Smckusick 					printf("%D\n", tln);
3286641Smckusick 					fflush(stdout);
3296641Smckusick 				}
3306641Smckusick 				return;
3316641Smckusick 			}
3326641Smckusick 			*p1++ = c;
3336641Smckusick 			if (p1 >= &linebuf[LBSIZE-1])
3346641Smckusick 				break;
3356641Smckusick 		}
3366641Smckusick 		*p1++ = '\0';
3376641Smckusick 		p1 = linebuf;
3386641Smckusick 		p2 = expbuf;
3396641Smckusick 		if (circf) {
3406641Smckusick 			if (advance(p1, p2))
3416641Smckusick 				goto found;
3426641Smckusick 			goto nfound;
3436641Smckusick 		}
3446641Smckusick 		/* fast check for first character */
3456641Smckusick 		if (*p2==CCHR) {
3466641Smckusick 			c = p2[1];
3476641Smckusick 			do {
3486641Smckusick 				if (*p1!=c)
3496641Smckusick 					continue;
3506641Smckusick 				if (advance(p1, p2))
3516641Smckusick 					goto found;
3526641Smckusick 			} while (*p1++);
3536641Smckusick 			goto nfound;
3546641Smckusick 		}
3556641Smckusick 		/* regular algorithm */
3566641Smckusick 		do {
3576641Smckusick 			if (advance(p1, p2))
3586641Smckusick 				goto found;
3596641Smckusick 		} while (*p1++);
3606641Smckusick 	nfound:
3616641Smckusick 		if (vflag)
3626641Smckusick 			succeed(file);
3636641Smckusick 		continue;
3646641Smckusick 	found:
3656641Smckusick 		if (vflag==0)
3666641Smckusick 			succeed(file);
3676641Smckusick 	}
3686641Smckusick }
3696641Smckusick 
advance(lp,ep)3706641Smckusick advance(lp, ep)
3716641Smckusick register char *lp, *ep;
3726641Smckusick {
3736641Smckusick 	register char *curlp;
3746641Smckusick 	char c;
3756641Smckusick 	char *bbeg;
3766641Smckusick 	int ct;
3776641Smckusick 
3786641Smckusick 	for (;;) switch (*ep++) {
3796641Smckusick 
3806641Smckusick 	case CCHR:
3816641Smckusick 		if (*ep++ == *lp++)
3826641Smckusick 			continue;
3836641Smckusick 		return(0);
3846641Smckusick 
3856641Smckusick 	case CDOT:
3866641Smckusick 		if (*lp++)
3876641Smckusick 			continue;
3886641Smckusick 		return(0);
3896641Smckusick 
3906641Smckusick 	case CDOL:
3916641Smckusick 		if (*lp==0)
3926641Smckusick 			continue;
3936641Smckusick 		return(0);
3946641Smckusick 
3956641Smckusick 	case CEOF:
3966641Smckusick 		return(1);
3976641Smckusick 
3986641Smckusick 	case CCL:
3996641Smckusick 		c = *lp++ & 0177;
4006641Smckusick 		if(ep[c>>3] & bittab[c & 07]) {
4016641Smckusick 			ep += 16;
4026641Smckusick 			continue;
4036641Smckusick 		}
4046641Smckusick 		return(0);
4056641Smckusick 	case CBRA:
4066641Smckusick 		braslist[*ep++] = lp;
4076641Smckusick 		continue;
4086641Smckusick 
4096641Smckusick 	case CKET:
4106641Smckusick 		braelist[*ep++] = lp;
4116641Smckusick 		continue;
4126641Smckusick 
4136641Smckusick 	case CBACK:
4146641Smckusick 		bbeg = braslist[*ep];
4156641Smckusick 		if (braelist[*ep]==0)
4166641Smckusick 			return(0);
4176641Smckusick 		ct = braelist[*ep++] - bbeg;
4186641Smckusick 		if(ecmp(bbeg, lp, ct)) {
4196641Smckusick 			lp += ct;
4206641Smckusick 			continue;
4216641Smckusick 		}
4226641Smckusick 		return(0);
4236641Smckusick 
4246641Smckusick 	case CBACK|STAR:
4256641Smckusick 		bbeg = braslist[*ep];
4266641Smckusick 		if (braelist[*ep]==0)
4276641Smckusick 			return(0);
4286641Smckusick 		ct = braelist[*ep++] - bbeg;
4296641Smckusick 		curlp = lp;
4306641Smckusick 		while(ecmp(bbeg, lp, ct))
4316641Smckusick 			lp += ct;
4326641Smckusick 		while(lp >= curlp) {
4336641Smckusick 			if(advance(lp, ep))	return(1);
4346641Smckusick 			lp -= ct;
4356641Smckusick 		}
4366641Smckusick 		return(0);
4376641Smckusick 
4386641Smckusick 
4396641Smckusick 	case CDOT|STAR:
4406641Smckusick 		curlp = lp;
4416641Smckusick 		while (*lp++);
4426641Smckusick 		goto star;
4436641Smckusick 
4446641Smckusick 	case CCHR|STAR:
4456641Smckusick 		curlp = lp;
4466641Smckusick 		while (*lp++ == *ep);
4476641Smckusick 		ep++;
4486641Smckusick 		goto star;
4496641Smckusick 
4506641Smckusick 	case CCL|STAR:
4516641Smckusick 		curlp = lp;
4526641Smckusick 		do {
4536641Smckusick 			c = *lp++ & 0177;
4546641Smckusick 		} while(ep[c>>3] & bittab[c & 07]);
4556641Smckusick 		ep += 16;
4566641Smckusick 		goto star;
4576641Smckusick 
4586641Smckusick 	star:
4596641Smckusick 		if(--lp == curlp) {
4606641Smckusick 			continue;
4616641Smckusick 		}
4626641Smckusick 
4636641Smckusick 		if(*ep == CCHR) {
4646641Smckusick 			c = ep[1];
4656641Smckusick 			do {
4666641Smckusick 				if(*lp != c)
4676641Smckusick 					continue;
4686641Smckusick 				if(advance(lp, ep))
4696641Smckusick 					return(1);
4706641Smckusick 			} while(lp-- > curlp);
4716641Smckusick 			return(0);
4726641Smckusick 		}
4736641Smckusick 
4746641Smckusick 		do {
4756641Smckusick 			if (advance(lp, ep))
4766641Smckusick 				return(1);
4776641Smckusick 		} while (lp-- > curlp);
4786641Smckusick 		return(0);
4796641Smckusick 
48013484Ssam 	case CBRC:
48113484Ssam 		if (lp == expbuf)
48213484Ssam 			continue;
48313484Ssam #define	uletter(c)	(isalpha(c) || (c) == '_')
48413484Ssam 		if (uletter(*lp) || isdigit(*lp))
48513484Ssam 			if (!uletter(lp[-1]) && !isdigit(lp[-1]))
48613484Ssam 				continue;
48713484Ssam 		return (0);
48813484Ssam 
48913484Ssam 	case CLET:
49013484Ssam 		if (!uletter(*lp) && !isdigit(*lp))
49113484Ssam 			continue;
49213484Ssam 		return (0);
49313484Ssam 
4946641Smckusick 	default:
4956641Smckusick 		errexit("grep RE botch\n", (char *)NULL);
4966641Smckusick 	}
4976641Smckusick }
4986641Smckusick 
succeed(f)4996641Smckusick succeed(f)
5006641Smckusick char *f;
5016641Smckusick {
5026641Smckusick 	nsucc = 1;
5036641Smckusick 	if (sflag)
5046641Smckusick 		return;
5056641Smckusick 	if (cflag) {
5066641Smckusick 		tln++;
5076641Smckusick 		return;
5086641Smckusick 	}
5096641Smckusick 	if (lflag) {
5106641Smckusick 		printf("%s\n", f);
5116641Smckusick 		fflush(stdout);
5126641Smckusick 		fseek(stdin, 0l, 2);
5136641Smckusick 		return;
5146641Smckusick 	}
51532365Sbostic 	if (nfile > 1 && hflag || oflag)
5166641Smckusick 		printf("%s:", f);
5176641Smckusick 	if (bflag)
5186641Smckusick 		printf("%u:", blkno);
5196641Smckusick 	if (nflag)
5206641Smckusick 		printf("%ld:", lnum);
5216641Smckusick 	printf("%s\n", linebuf);
5226641Smckusick 	fflush(stdout);
5236641Smckusick }
5246641Smckusick 
ecmp(a,b,count)5256641Smckusick ecmp(a, b, count)
5266641Smckusick char	*a, *b;
5276641Smckusick {
5286641Smckusick 	register cc = count;
5296641Smckusick 	while(cc--)
5306641Smckusick 		if(*a++ != *b++)	return(0);
5316641Smckusick 	return(1);
5326641Smckusick }
5336641Smckusick 
errexit(s,f)5346641Smckusick errexit(s, f)
5356641Smckusick char *s, *f;
5366641Smckusick {
5376641Smckusick 	fprintf(stderr, s, f);
5386641Smckusick 	exit(2);
5396641Smckusick }
540