114464Ssam #ifndef lint
2*32365Sbostic static char sccsid[] = "@(#)old.bin.grep.c	4.7 (Berkeley) 10/07/87";
314464Ssam #endif
46641Smckusick 
56641Smckusick /*
66641Smckusick  * grep -- print lines matching (or not matching) a pattern
76641Smckusick  *
86641Smckusick  *	status returns:
96641Smckusick  *		0 - ok, and some matches
106641Smckusick  *		1 - ok, but no matches
116641Smckusick  *		2 - some error
126641Smckusick  */
136641Smckusick 
146641Smckusick #include <stdio.h>
156641Smckusick #include <ctype.h>
166641Smckusick 
176641Smckusick #define	CBRA	1
186641Smckusick #define	CCHR	2
196641Smckusick #define	CDOT	4
206641Smckusick #define	CCL	6
216641Smckusick #define	NCCL	8
226641Smckusick #define	CDOL	10
236641Smckusick #define	CEOF	11
246641Smckusick #define	CKET	12
2513484Ssam #define	CBRC	14
2613484Ssam #define	CLET	15
276641Smckusick #define	CBACK	18
286641Smckusick 
296641Smckusick #define	STAR	01
306641Smckusick 
316641Smckusick #define	LBSIZE	BUFSIZ
326641Smckusick #define	ESIZE	256
336641Smckusick #define	NBRA	9
346641Smckusick 
356641Smckusick char	expbuf[ESIZE];
366641Smckusick long	lnum;
376641Smckusick char	linebuf[LBSIZE+1];
386641Smckusick char	ybuf[ESIZE];
396641Smckusick int	bflag;
406641Smckusick int	lflag;
416641Smckusick int	nflag;
426641Smckusick int	cflag;
436641Smckusick int	vflag;
446641Smckusick int	nfile;
456641Smckusick int	hflag	= 1;
46*32365Sbostic int	oflag;
476641Smckusick int	sflag;
486641Smckusick int	yflag;
4913484Ssam int	wflag;
5011579Sedward int	retcode = 0;
516641Smckusick int	circf;
526641Smckusick int	blkno;
536641Smckusick long	tln;
546641Smckusick int	nsucc;
556641Smckusick char	*braslist[NBRA];
566641Smckusick char	*braelist[NBRA];
576641Smckusick char	bittab[] = {
586641Smckusick 	1,
596641Smckusick 	2,
606641Smckusick 	4,
616641Smckusick 	8,
626641Smckusick 	16,
636641Smckusick 	32,
646641Smckusick 	64,
656641Smckusick 	128
666641Smckusick };
676641Smckusick 
686641Smckusick main(argc, argv)
696641Smckusick char **argv;
706641Smckusick {
716641Smckusick 	while (--argc > 0 && (++argv)[0][0]=='-')
726641Smckusick 		switch (argv[0][1]) {
736641Smckusick 
7413484Ssam 		case 'i':
756641Smckusick 		case 'y':
766641Smckusick 			yflag++;
776641Smckusick 			continue;
786641Smckusick 
7913484Ssam 		case 'w':
8013484Ssam 			wflag++;
8113484Ssam 			continue;
8213484Ssam 
83*32365Sbostic 		case 'o':
84*32365Sbostic 			oflag++;
85*32365Sbostic 			continue;
86*32365Sbostic 
876641Smckusick 		case 'h':
886641Smckusick 			hflag = 0;
896641Smckusick 			continue;
906641Smckusick 
916641Smckusick 		case 's':
926641Smckusick 			sflag++;
936641Smckusick 			continue;
946641Smckusick 
956641Smckusick 		case 'v':
966641Smckusick 			vflag++;
976641Smckusick 			continue;
986641Smckusick 
996641Smckusick 		case 'b':
1006641Smckusick 			bflag++;
1016641Smckusick 			continue;
1026641Smckusick 
1036641Smckusick 		case 'l':
1046641Smckusick 			lflag++;
1056641Smckusick 			continue;
1066641Smckusick 
1076641Smckusick 		case 'c':
1086641Smckusick 			cflag++;
1096641Smckusick 			continue;
1106641Smckusick 
1116641Smckusick 		case 'n':
1126641Smckusick 			nflag++;
1136641Smckusick 			continue;
1146641Smckusick 
1156641Smckusick 		case 'e':
1166641Smckusick 			--argc;
1176641Smckusick 			++argv;
1186641Smckusick 			goto out;
1196641Smckusick 
1206641Smckusick 		default:
1216641Smckusick 			errexit("grep: unknown flag\n", (char *)NULL);
1226641Smckusick 			continue;
1236641Smckusick 		}
1246641Smckusick out:
1256641Smckusick 	if (argc<=0)
1266641Smckusick 		exit(2);
1276641Smckusick 	if (yflag) {
1286641Smckusick 		register char *p, *s;
1296641Smckusick 		for (s = ybuf, p = *argv; *p; ) {
1306641Smckusick 			if (*p == '\\') {
1316641Smckusick 				*s++ = *p++;
1326641Smckusick 				if (*p)
1336641Smckusick 					*s++ = *p++;
1346641Smckusick 			} else if (*p == '[') {
1356641Smckusick 				while (*p != '\0' && *p != ']')
1366641Smckusick 					*s++ = *p++;
1376641Smckusick 			} else if (islower(*p)) {
1386641Smckusick 				*s++ = '[';
1396641Smckusick 				*s++ = toupper(*p);
1406641Smckusick 				*s++ = *p++;
1416641Smckusick 				*s++ = ']';
1426641Smckusick 			} else
1436641Smckusick 				*s++ = *p++;
1446641Smckusick 			if (s >= ybuf+ESIZE-5)
1456641Smckusick 				errexit("grep: argument too long\n", (char *)NULL);
1466641Smckusick 		}
1476641Smckusick 		*s = '\0';
1486641Smckusick 		*argv = ybuf;
1496641Smckusick 	}
1506641Smckusick 	compile(*argv);
1516641Smckusick 	nfile = --argc;
1526641Smckusick 	if (argc<=0) {
1536641Smckusick 		if (lflag)
1546641Smckusick 			exit(1);
1556641Smckusick 		execute((char *)NULL);
1566641Smckusick 	} else while (--argc >= 0) {
1576641Smckusick 		argv++;
1586641Smckusick 		execute(*argv);
1596641Smckusick 	}
16011579Sedward 	exit(retcode != 0 ? retcode : nsucc == 0);
1616641Smckusick }
1626641Smckusick 
1636641Smckusick compile(astr)
1646641Smckusick char *astr;
1656641Smckusick {
1666641Smckusick 	register c;
1676641Smckusick 	register char *ep, *sp;
1686641Smckusick 	char *cstart;
1696641Smckusick 	char *lastep;
1706641Smckusick 	int cclcnt;
1716641Smckusick 	char bracket[NBRA], *bracketp;
1726641Smckusick 	int closed;
1736641Smckusick 	char numbra;
1746641Smckusick 	char neg;
1756641Smckusick 
1766641Smckusick 	ep = expbuf;
1776641Smckusick 	sp = astr;
1786641Smckusick 	lastep = 0;
1796641Smckusick 	bracketp = bracket;
1806641Smckusick 	closed = numbra = 0;
1816641Smckusick 	if (*sp == '^') {
1826641Smckusick 		circf++;
1836641Smckusick 		sp++;
1846641Smckusick 	}
18513484Ssam 	if (wflag)
18613484Ssam 		*ep++ = CBRC;
1876641Smckusick 	for (;;) {
1886641Smckusick 		if (ep >= &expbuf[ESIZE])
1896641Smckusick 			goto cerror;
1906641Smckusick 		if ((c = *sp++) != '*')
1916641Smckusick 			lastep = ep;
1926641Smckusick 		switch (c) {
1936641Smckusick 
1946641Smckusick 		case '\0':
19513484Ssam 			if (wflag)
19613484Ssam 				*ep++ = CLET;
1976641Smckusick 			*ep++ = CEOF;
1986641Smckusick 			return;
1996641Smckusick 
2006641Smckusick 		case '.':
2016641Smckusick 			*ep++ = CDOT;
2026641Smckusick 			continue;
2036641Smckusick 
2046641Smckusick 		case '*':
20513484Ssam 			if (lastep==0 || *lastep==CBRA || *lastep==CKET ||
20613484Ssam 			    *lastep == CBRC || *lastep == CLET)
2076641Smckusick 				goto defchar;
2086641Smckusick 			*lastep |= STAR;
2096641Smckusick 			continue;
2106641Smckusick 
2116641Smckusick 		case '$':
2126641Smckusick 			if (*sp != '\0')
2136641Smckusick 				goto defchar;
2146641Smckusick 			*ep++ = CDOL;
2156641Smckusick 			continue;
2166641Smckusick 
2176641Smckusick 		case '[':
2186641Smckusick 			if(&ep[17] >= &expbuf[ESIZE])
2196641Smckusick 				goto cerror;
2206641Smckusick 			*ep++ = CCL;
2216641Smckusick 			neg = 0;
2226641Smckusick 			if((c = *sp++) == '^') {
2236641Smckusick 				neg = 1;
2246641Smckusick 				c = *sp++;
2256641Smckusick 			}
2266641Smckusick 			cstart = sp;
2276641Smckusick 			do {
2286641Smckusick 				if (c=='\0')
2296641Smckusick 					goto cerror;
2306641Smckusick 				if (c=='-' && sp>cstart && *sp!=']') {
2316641Smckusick 					for (c = sp[-2]; c<*sp; c++)
2326641Smckusick 						ep[c>>3] |= bittab[c&07];
2336641Smckusick 					sp++;
2346641Smckusick 				}
2356641Smckusick 				ep[c>>3] |= bittab[c&07];
2366641Smckusick 			} while((c = *sp++) != ']');
2376641Smckusick 			if(neg) {
2386641Smckusick 				for(cclcnt = 0; cclcnt < 16; cclcnt++)
2396641Smckusick 					ep[cclcnt] ^= -1;
2406641Smckusick 				ep[0] &= 0376;
2416641Smckusick 			}
2426641Smckusick 
2436641Smckusick 			ep += 16;
2446641Smckusick 
2456641Smckusick 			continue;
2466641Smckusick 
2476641Smckusick 		case '\\':
24813484Ssam 			if((c = *sp++) == 0)
24913484Ssam 				goto cerror;
25013484Ssam 			if(c == '<') {
25113484Ssam 				*ep++ = CBRC;
25213484Ssam 				continue;
25313484Ssam 			}
25413484Ssam 			if(c == '>') {
25513484Ssam 				*ep++ = CLET;
25613484Ssam 				continue;
25713484Ssam 			}
25813484Ssam 			if(c == '(') {
2596641Smckusick 				if(numbra >= NBRA) {
2606641Smckusick 					goto cerror;
2616641Smckusick 				}
2626641Smckusick 				*bracketp++ = numbra;
2636641Smckusick 				*ep++ = CBRA;
2646641Smckusick 				*ep++ = numbra++;
2656641Smckusick 				continue;
2666641Smckusick 			}
2676641Smckusick 			if(c == ')') {
2686641Smckusick 				if(bracketp <= bracket) {
2696641Smckusick 					goto cerror;
2706641Smckusick 				}
2716641Smckusick 				*ep++ = CKET;
2726641Smckusick 				*ep++ = *--bracketp;
2736641Smckusick 				closed++;
2746641Smckusick 				continue;
2756641Smckusick 			}
2766641Smckusick 
2776641Smckusick 			if(c >= '1' && c <= '9') {
2786641Smckusick 				if((c -= '1') >= closed)
2796641Smckusick 					goto cerror;
2806641Smckusick 				*ep++ = CBACK;
2816641Smckusick 				*ep++ = c;
2826641Smckusick 				continue;
2836641Smckusick 			}
2846641Smckusick 
2856641Smckusick 		defchar:
2866641Smckusick 		default:
2876641Smckusick 			*ep++ = CCHR;
2886641Smckusick 			*ep++ = c;
2896641Smckusick 		}
2906641Smckusick 	}
2916641Smckusick     cerror:
2926641Smckusick 	errexit("grep: RE error\n", (char *)NULL);
2936641Smckusick }
2946641Smckusick 
2956641Smckusick execute(file)
2966641Smckusick char *file;
2976641Smckusick {
2986641Smckusick 	register char *p1, *p2;
2996641Smckusick 	register c;
3006641Smckusick 
3016641Smckusick 	if (file) {
30211579Sedward 		if (freopen(file, "r", stdin) == NULL) {
30312096Smckusick 			perror(file);
30411579Sedward 			retcode = 2;
30511579Sedward 		}
3066641Smckusick 	}
3076641Smckusick 	lnum = 0;
3086641Smckusick 	tln = 0;
3096641Smckusick 	for (;;) {
3106641Smckusick 		lnum++;
3116641Smckusick 		p1 = linebuf;
3126641Smckusick 		while ((c = getchar()) != '\n') {
3136641Smckusick 			if (c == EOF) {
3146641Smckusick 				if (cflag) {
3156641Smckusick 					if (nfile>1)
3166641Smckusick 						printf("%s:", file);
3176641Smckusick 					printf("%D\n", tln);
3186641Smckusick 					fflush(stdout);
3196641Smckusick 				}
3206641Smckusick 				return;
3216641Smckusick 			}
3226641Smckusick 			*p1++ = c;
3236641Smckusick 			if (p1 >= &linebuf[LBSIZE-1])
3246641Smckusick 				break;
3256641Smckusick 		}
3266641Smckusick 		*p1++ = '\0';
3276641Smckusick 		p1 = linebuf;
3286641Smckusick 		p2 = expbuf;
3296641Smckusick 		if (circf) {
3306641Smckusick 			if (advance(p1, p2))
3316641Smckusick 				goto found;
3326641Smckusick 			goto nfound;
3336641Smckusick 		}
3346641Smckusick 		/* fast check for first character */
3356641Smckusick 		if (*p2==CCHR) {
3366641Smckusick 			c = p2[1];
3376641Smckusick 			do {
3386641Smckusick 				if (*p1!=c)
3396641Smckusick 					continue;
3406641Smckusick 				if (advance(p1, p2))
3416641Smckusick 					goto found;
3426641Smckusick 			} while (*p1++);
3436641Smckusick 			goto nfound;
3446641Smckusick 		}
3456641Smckusick 		/* regular algorithm */
3466641Smckusick 		do {
3476641Smckusick 			if (advance(p1, p2))
3486641Smckusick 				goto found;
3496641Smckusick 		} while (*p1++);
3506641Smckusick 	nfound:
3516641Smckusick 		if (vflag)
3526641Smckusick 			succeed(file);
3536641Smckusick 		continue;
3546641Smckusick 	found:
3556641Smckusick 		if (vflag==0)
3566641Smckusick 			succeed(file);
3576641Smckusick 	}
3586641Smckusick }
3596641Smckusick 
3606641Smckusick advance(lp, ep)
3616641Smckusick register char *lp, *ep;
3626641Smckusick {
3636641Smckusick 	register char *curlp;
3646641Smckusick 	char c;
3656641Smckusick 	char *bbeg;
3666641Smckusick 	int ct;
3676641Smckusick 
3686641Smckusick 	for (;;) switch (*ep++) {
3696641Smckusick 
3706641Smckusick 	case CCHR:
3716641Smckusick 		if (*ep++ == *lp++)
3726641Smckusick 			continue;
3736641Smckusick 		return(0);
3746641Smckusick 
3756641Smckusick 	case CDOT:
3766641Smckusick 		if (*lp++)
3776641Smckusick 			continue;
3786641Smckusick 		return(0);
3796641Smckusick 
3806641Smckusick 	case CDOL:
3816641Smckusick 		if (*lp==0)
3826641Smckusick 			continue;
3836641Smckusick 		return(0);
3846641Smckusick 
3856641Smckusick 	case CEOF:
3866641Smckusick 		return(1);
3876641Smckusick 
3886641Smckusick 	case CCL:
3896641Smckusick 		c = *lp++ & 0177;
3906641Smckusick 		if(ep[c>>3] & bittab[c & 07]) {
3916641Smckusick 			ep += 16;
3926641Smckusick 			continue;
3936641Smckusick 		}
3946641Smckusick 		return(0);
3956641Smckusick 	case CBRA:
3966641Smckusick 		braslist[*ep++] = lp;
3976641Smckusick 		continue;
3986641Smckusick 
3996641Smckusick 	case CKET:
4006641Smckusick 		braelist[*ep++] = lp;
4016641Smckusick 		continue;
4026641Smckusick 
4036641Smckusick 	case CBACK:
4046641Smckusick 		bbeg = braslist[*ep];
4056641Smckusick 		if (braelist[*ep]==0)
4066641Smckusick 			return(0);
4076641Smckusick 		ct = braelist[*ep++] - bbeg;
4086641Smckusick 		if(ecmp(bbeg, lp, ct)) {
4096641Smckusick 			lp += ct;
4106641Smckusick 			continue;
4116641Smckusick 		}
4126641Smckusick 		return(0);
4136641Smckusick 
4146641Smckusick 	case CBACK|STAR:
4156641Smckusick 		bbeg = braslist[*ep];
4166641Smckusick 		if (braelist[*ep]==0)
4176641Smckusick 			return(0);
4186641Smckusick 		ct = braelist[*ep++] - bbeg;
4196641Smckusick 		curlp = lp;
4206641Smckusick 		while(ecmp(bbeg, lp, ct))
4216641Smckusick 			lp += ct;
4226641Smckusick 		while(lp >= curlp) {
4236641Smckusick 			if(advance(lp, ep))	return(1);
4246641Smckusick 			lp -= ct;
4256641Smckusick 		}
4266641Smckusick 		return(0);
4276641Smckusick 
4286641Smckusick 
4296641Smckusick 	case CDOT|STAR:
4306641Smckusick 		curlp = lp;
4316641Smckusick 		while (*lp++);
4326641Smckusick 		goto star;
4336641Smckusick 
4346641Smckusick 	case CCHR|STAR:
4356641Smckusick 		curlp = lp;
4366641Smckusick 		while (*lp++ == *ep);
4376641Smckusick 		ep++;
4386641Smckusick 		goto star;
4396641Smckusick 
4406641Smckusick 	case CCL|STAR:
4416641Smckusick 		curlp = lp;
4426641Smckusick 		do {
4436641Smckusick 			c = *lp++ & 0177;
4446641Smckusick 		} while(ep[c>>3] & bittab[c & 07]);
4456641Smckusick 		ep += 16;
4466641Smckusick 		goto star;
4476641Smckusick 
4486641Smckusick 	star:
4496641Smckusick 		if(--lp == curlp) {
4506641Smckusick 			continue;
4516641Smckusick 		}
4526641Smckusick 
4536641Smckusick 		if(*ep == CCHR) {
4546641Smckusick 			c = ep[1];
4556641Smckusick 			do {
4566641Smckusick 				if(*lp != c)
4576641Smckusick 					continue;
4586641Smckusick 				if(advance(lp, ep))
4596641Smckusick 					return(1);
4606641Smckusick 			} while(lp-- > curlp);
4616641Smckusick 			return(0);
4626641Smckusick 		}
4636641Smckusick 
4646641Smckusick 		do {
4656641Smckusick 			if (advance(lp, ep))
4666641Smckusick 				return(1);
4676641Smckusick 		} while (lp-- > curlp);
4686641Smckusick 		return(0);
4696641Smckusick 
47013484Ssam 	case CBRC:
47113484Ssam 		if (lp == expbuf)
47213484Ssam 			continue;
47313484Ssam #define	uletter(c)	(isalpha(c) || (c) == '_')
47413484Ssam 		if (uletter(*lp) || isdigit(*lp))
47513484Ssam 			if (!uletter(lp[-1]) && !isdigit(lp[-1]))
47613484Ssam 				continue;
47713484Ssam 		return (0);
47813484Ssam 
47913484Ssam 	case CLET:
48013484Ssam 		if (!uletter(*lp) && !isdigit(*lp))
48113484Ssam 			continue;
48213484Ssam 		return (0);
48313484Ssam 
4846641Smckusick 	default:
4856641Smckusick 		errexit("grep RE botch\n", (char *)NULL);
4866641Smckusick 	}
4876641Smckusick }
4886641Smckusick 
4896641Smckusick succeed(f)
4906641Smckusick char *f;
4916641Smckusick {
4926641Smckusick 	nsucc = 1;
4936641Smckusick 	if (sflag)
4946641Smckusick 		return;
4956641Smckusick 	if (cflag) {
4966641Smckusick 		tln++;
4976641Smckusick 		return;
4986641Smckusick 	}
4996641Smckusick 	if (lflag) {
5006641Smckusick 		printf("%s\n", f);
5016641Smckusick 		fflush(stdout);
5026641Smckusick 		fseek(stdin, 0l, 2);
5036641Smckusick 		return;
5046641Smckusick 	}
505*32365Sbostic 	if (nfile > 1 && hflag || oflag)
5066641Smckusick 		printf("%s:", f);
5076641Smckusick 	if (bflag)
5086641Smckusick 		printf("%u:", blkno);
5096641Smckusick 	if (nflag)
5106641Smckusick 		printf("%ld:", lnum);
5116641Smckusick 	printf("%s\n", linebuf);
5126641Smckusick 	fflush(stdout);
5136641Smckusick }
5146641Smckusick 
5156641Smckusick ecmp(a, b, count)
5166641Smckusick char	*a, *b;
5176641Smckusick {
5186641Smckusick 	register cc = count;
5196641Smckusick 	while(cc--)
5206641Smckusick 		if(*a++ != *b++)	return(0);
5216641Smckusick 	return(1);
5226641Smckusick }
5236641Smckusick 
5246641Smckusick errexit(s, f)
5256641Smckusick char *s, *f;
5266641Smckusick {
5276641Smckusick 	fprintf(stderr, s, f);
5286641Smckusick 	exit(2);
5296641Smckusick }
530