1*14464Ssam #ifndef lint
2*14464Ssam static char sccsid[] = "@(#)old.bin.grep.c	4.5 (Berkeley) 08/11/83";
3*14464Ssam #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;
466641Smckusick int	sflag;
476641Smckusick int	yflag;
4813484Ssam int	wflag;
4911579Sedward int	retcode = 0;
506641Smckusick int	circf;
516641Smckusick int	blkno;
526641Smckusick long	tln;
536641Smckusick int	nsucc;
546641Smckusick char	*braslist[NBRA];
556641Smckusick char	*braelist[NBRA];
566641Smckusick char	bittab[] = {
576641Smckusick 	1,
586641Smckusick 	2,
596641Smckusick 	4,
606641Smckusick 	8,
616641Smckusick 	16,
626641Smckusick 	32,
636641Smckusick 	64,
646641Smckusick 	128
656641Smckusick };
666641Smckusick 
676641Smckusick main(argc, argv)
686641Smckusick char **argv;
696641Smckusick {
706641Smckusick 	extern char _sobuf[];
716641Smckusick 	setbuf(stdout, _sobuf);
726641Smckusick 	while (--argc > 0 && (++argv)[0][0]=='-')
736641Smckusick 		switch (argv[0][1]) {
746641Smckusick 
7513484Ssam 		case 'i':
766641Smckusick 		case 'y':
776641Smckusick 			yflag++;
786641Smckusick 			continue;
796641Smckusick 
8013484Ssam 		case 'w':
8113484Ssam 			wflag++;
8213484Ssam 			continue;
8313484Ssam 
846641Smckusick 		case 'h':
856641Smckusick 			hflag = 0;
866641Smckusick 			continue;
876641Smckusick 
886641Smckusick 		case 's':
896641Smckusick 			sflag++;
906641Smckusick 			continue;
916641Smckusick 
926641Smckusick 		case 'v':
936641Smckusick 			vflag++;
946641Smckusick 			continue;
956641Smckusick 
966641Smckusick 		case 'b':
976641Smckusick 			bflag++;
986641Smckusick 			continue;
996641Smckusick 
1006641Smckusick 		case 'l':
1016641Smckusick 			lflag++;
1026641Smckusick 			continue;
1036641Smckusick 
1046641Smckusick 		case 'c':
1056641Smckusick 			cflag++;
1066641Smckusick 			continue;
1076641Smckusick 
1086641Smckusick 		case 'n':
1096641Smckusick 			nflag++;
1106641Smckusick 			continue;
1116641Smckusick 
1126641Smckusick 		case 'e':
1136641Smckusick 			--argc;
1146641Smckusick 			++argv;
1156641Smckusick 			goto out;
1166641Smckusick 
1176641Smckusick 		default:
1186641Smckusick 			errexit("grep: unknown flag\n", (char *)NULL);
1196641Smckusick 			continue;
1206641Smckusick 		}
1216641Smckusick out:
1226641Smckusick 	if (argc<=0)
1236641Smckusick 		exit(2);
1246641Smckusick 	if (yflag) {
1256641Smckusick 		register char *p, *s;
1266641Smckusick 		for (s = ybuf, p = *argv; *p; ) {
1276641Smckusick 			if (*p == '\\') {
1286641Smckusick 				*s++ = *p++;
1296641Smckusick 				if (*p)
1306641Smckusick 					*s++ = *p++;
1316641Smckusick 			} else if (*p == '[') {
1326641Smckusick 				while (*p != '\0' && *p != ']')
1336641Smckusick 					*s++ = *p++;
1346641Smckusick 			} else if (islower(*p)) {
1356641Smckusick 				*s++ = '[';
1366641Smckusick 				*s++ = toupper(*p);
1376641Smckusick 				*s++ = *p++;
1386641Smckusick 				*s++ = ']';
1396641Smckusick 			} else
1406641Smckusick 				*s++ = *p++;
1416641Smckusick 			if (s >= ybuf+ESIZE-5)
1426641Smckusick 				errexit("grep: argument too long\n", (char *)NULL);
1436641Smckusick 		}
1446641Smckusick 		*s = '\0';
1456641Smckusick 		*argv = ybuf;
1466641Smckusick 	}
1476641Smckusick 	compile(*argv);
1486641Smckusick 	nfile = --argc;
1496641Smckusick 	if (argc<=0) {
1506641Smckusick 		if (lflag)
1516641Smckusick 			exit(1);
1526641Smckusick 		execute((char *)NULL);
1536641Smckusick 	} else while (--argc >= 0) {
1546641Smckusick 		argv++;
1556641Smckusick 		execute(*argv);
1566641Smckusick 	}
15711579Sedward 	exit(retcode != 0 ? retcode : nsucc == 0);
1586641Smckusick }
1596641Smckusick 
1606641Smckusick compile(astr)
1616641Smckusick char *astr;
1626641Smckusick {
1636641Smckusick 	register c;
1646641Smckusick 	register char *ep, *sp;
1656641Smckusick 	char *cstart;
1666641Smckusick 	char *lastep;
1676641Smckusick 	int cclcnt;
1686641Smckusick 	char bracket[NBRA], *bracketp;
1696641Smckusick 	int closed;
1706641Smckusick 	char numbra;
1716641Smckusick 	char neg;
1726641Smckusick 
1736641Smckusick 	ep = expbuf;
1746641Smckusick 	sp = astr;
1756641Smckusick 	lastep = 0;
1766641Smckusick 	bracketp = bracket;
1776641Smckusick 	closed = numbra = 0;
1786641Smckusick 	if (*sp == '^') {
1796641Smckusick 		circf++;
1806641Smckusick 		sp++;
1816641Smckusick 	}
18213484Ssam 	if (wflag)
18313484Ssam 		*ep++ = CBRC;
1846641Smckusick 	for (;;) {
1856641Smckusick 		if (ep >= &expbuf[ESIZE])
1866641Smckusick 			goto cerror;
1876641Smckusick 		if ((c = *sp++) != '*')
1886641Smckusick 			lastep = ep;
1896641Smckusick 		switch (c) {
1906641Smckusick 
1916641Smckusick 		case '\0':
19213484Ssam 			if (wflag)
19313484Ssam 				*ep++ = CLET;
1946641Smckusick 			*ep++ = CEOF;
1956641Smckusick 			return;
1966641Smckusick 
1976641Smckusick 		case '.':
1986641Smckusick 			*ep++ = CDOT;
1996641Smckusick 			continue;
2006641Smckusick 
2016641Smckusick 		case '*':
20213484Ssam 			if (lastep==0 || *lastep==CBRA || *lastep==CKET ||
20313484Ssam 			    *lastep == CBRC || *lastep == CLET)
2046641Smckusick 				goto defchar;
2056641Smckusick 			*lastep |= STAR;
2066641Smckusick 			continue;
2076641Smckusick 
2086641Smckusick 		case '$':
2096641Smckusick 			if (*sp != '\0')
2106641Smckusick 				goto defchar;
2116641Smckusick 			*ep++ = CDOL;
2126641Smckusick 			continue;
2136641Smckusick 
2146641Smckusick 		case '[':
2156641Smckusick 			if(&ep[17] >= &expbuf[ESIZE])
2166641Smckusick 				goto cerror;
2176641Smckusick 			*ep++ = CCL;
2186641Smckusick 			neg = 0;
2196641Smckusick 			if((c = *sp++) == '^') {
2206641Smckusick 				neg = 1;
2216641Smckusick 				c = *sp++;
2226641Smckusick 			}
2236641Smckusick 			cstart = sp;
2246641Smckusick 			do {
2256641Smckusick 				if (c=='\0')
2266641Smckusick 					goto cerror;
2276641Smckusick 				if (c=='-' && sp>cstart && *sp!=']') {
2286641Smckusick 					for (c = sp[-2]; c<*sp; c++)
2296641Smckusick 						ep[c>>3] |= bittab[c&07];
2306641Smckusick 					sp++;
2316641Smckusick 				}
2326641Smckusick 				ep[c>>3] |= bittab[c&07];
2336641Smckusick 			} while((c = *sp++) != ']');
2346641Smckusick 			if(neg) {
2356641Smckusick 				for(cclcnt = 0; cclcnt < 16; cclcnt++)
2366641Smckusick 					ep[cclcnt] ^= -1;
2376641Smckusick 				ep[0] &= 0376;
2386641Smckusick 			}
2396641Smckusick 
2406641Smckusick 			ep += 16;
2416641Smckusick 
2426641Smckusick 			continue;
2436641Smckusick 
2446641Smckusick 		case '\\':
24513484Ssam 			if((c = *sp++) == 0)
24613484Ssam 				goto cerror;
24713484Ssam 			if(c == '<') {
24813484Ssam 				*ep++ = CBRC;
24913484Ssam 				continue;
25013484Ssam 			}
25113484Ssam 			if(c == '>') {
25213484Ssam 				*ep++ = CLET;
25313484Ssam 				continue;
25413484Ssam 			}
25513484Ssam 			if(c == '(') {
2566641Smckusick 				if(numbra >= NBRA) {
2576641Smckusick 					goto cerror;
2586641Smckusick 				}
2596641Smckusick 				*bracketp++ = numbra;
2606641Smckusick 				*ep++ = CBRA;
2616641Smckusick 				*ep++ = numbra++;
2626641Smckusick 				continue;
2636641Smckusick 			}
2646641Smckusick 			if(c == ')') {
2656641Smckusick 				if(bracketp <= bracket) {
2666641Smckusick 					goto cerror;
2676641Smckusick 				}
2686641Smckusick 				*ep++ = CKET;
2696641Smckusick 				*ep++ = *--bracketp;
2706641Smckusick 				closed++;
2716641Smckusick 				continue;
2726641Smckusick 			}
2736641Smckusick 
2746641Smckusick 			if(c >= '1' && c <= '9') {
2756641Smckusick 				if((c -= '1') >= closed)
2766641Smckusick 					goto cerror;
2776641Smckusick 				*ep++ = CBACK;
2786641Smckusick 				*ep++ = c;
2796641Smckusick 				continue;
2806641Smckusick 			}
2816641Smckusick 
2826641Smckusick 		defchar:
2836641Smckusick 		default:
2846641Smckusick 			*ep++ = CCHR;
2856641Smckusick 			*ep++ = c;
2866641Smckusick 		}
2876641Smckusick 	}
2886641Smckusick     cerror:
2896641Smckusick 	errexit("grep: RE error\n", (char *)NULL);
2906641Smckusick }
2916641Smckusick 
2926641Smckusick execute(file)
2936641Smckusick char *file;
2946641Smckusick {
2956641Smckusick 	register char *p1, *p2;
2966641Smckusick 	register c;
2976641Smckusick 
2986641Smckusick 	if (file) {
29911579Sedward 		if (freopen(file, "r", stdin) == NULL) {
30012096Smckusick 			perror(file);
30111579Sedward 			retcode = 2;
30211579Sedward 		}
3036641Smckusick 	}
3046641Smckusick 	lnum = 0;
3056641Smckusick 	tln = 0;
3066641Smckusick 	for (;;) {
3076641Smckusick 		lnum++;
3086641Smckusick 		p1 = linebuf;
3096641Smckusick 		while ((c = getchar()) != '\n') {
3106641Smckusick 			if (c == EOF) {
3116641Smckusick 				if (cflag) {
3126641Smckusick 					if (nfile>1)
3136641Smckusick 						printf("%s:", file);
3146641Smckusick 					printf("%D\n", tln);
3156641Smckusick 					fflush(stdout);
3166641Smckusick 				}
3176641Smckusick 				return;
3186641Smckusick 			}
3196641Smckusick 			*p1++ = c;
3206641Smckusick 			if (p1 >= &linebuf[LBSIZE-1])
3216641Smckusick 				break;
3226641Smckusick 		}
3236641Smckusick 		*p1++ = '\0';
3246641Smckusick 		p1 = linebuf;
3256641Smckusick 		p2 = expbuf;
3266641Smckusick 		if (circf) {
3276641Smckusick 			if (advance(p1, p2))
3286641Smckusick 				goto found;
3296641Smckusick 			goto nfound;
3306641Smckusick 		}
3316641Smckusick 		/* fast check for first character */
3326641Smckusick 		if (*p2==CCHR) {
3336641Smckusick 			c = p2[1];
3346641Smckusick 			do {
3356641Smckusick 				if (*p1!=c)
3366641Smckusick 					continue;
3376641Smckusick 				if (advance(p1, p2))
3386641Smckusick 					goto found;
3396641Smckusick 			} while (*p1++);
3406641Smckusick 			goto nfound;
3416641Smckusick 		}
3426641Smckusick 		/* regular algorithm */
3436641Smckusick 		do {
3446641Smckusick 			if (advance(p1, p2))
3456641Smckusick 				goto found;
3466641Smckusick 		} while (*p1++);
3476641Smckusick 	nfound:
3486641Smckusick 		if (vflag)
3496641Smckusick 			succeed(file);
3506641Smckusick 		continue;
3516641Smckusick 	found:
3526641Smckusick 		if (vflag==0)
3536641Smckusick 			succeed(file);
3546641Smckusick 	}
3556641Smckusick }
3566641Smckusick 
3576641Smckusick advance(lp, ep)
3586641Smckusick register char *lp, *ep;
3596641Smckusick {
3606641Smckusick 	register char *curlp;
3616641Smckusick 	char c;
3626641Smckusick 	char *bbeg;
3636641Smckusick 	int ct;
3646641Smckusick 
3656641Smckusick 	for (;;) switch (*ep++) {
3666641Smckusick 
3676641Smckusick 	case CCHR:
3686641Smckusick 		if (*ep++ == *lp++)
3696641Smckusick 			continue;
3706641Smckusick 		return(0);
3716641Smckusick 
3726641Smckusick 	case CDOT:
3736641Smckusick 		if (*lp++)
3746641Smckusick 			continue;
3756641Smckusick 		return(0);
3766641Smckusick 
3776641Smckusick 	case CDOL:
3786641Smckusick 		if (*lp==0)
3796641Smckusick 			continue;
3806641Smckusick 		return(0);
3816641Smckusick 
3826641Smckusick 	case CEOF:
3836641Smckusick 		return(1);
3846641Smckusick 
3856641Smckusick 	case CCL:
3866641Smckusick 		c = *lp++ & 0177;
3876641Smckusick 		if(ep[c>>3] & bittab[c & 07]) {
3886641Smckusick 			ep += 16;
3896641Smckusick 			continue;
3906641Smckusick 		}
3916641Smckusick 		return(0);
3926641Smckusick 	case CBRA:
3936641Smckusick 		braslist[*ep++] = lp;
3946641Smckusick 		continue;
3956641Smckusick 
3966641Smckusick 	case CKET:
3976641Smckusick 		braelist[*ep++] = lp;
3986641Smckusick 		continue;
3996641Smckusick 
4006641Smckusick 	case CBACK:
4016641Smckusick 		bbeg = braslist[*ep];
4026641Smckusick 		if (braelist[*ep]==0)
4036641Smckusick 			return(0);
4046641Smckusick 		ct = braelist[*ep++] - bbeg;
4056641Smckusick 		if(ecmp(bbeg, lp, ct)) {
4066641Smckusick 			lp += ct;
4076641Smckusick 			continue;
4086641Smckusick 		}
4096641Smckusick 		return(0);
4106641Smckusick 
4116641Smckusick 	case CBACK|STAR:
4126641Smckusick 		bbeg = braslist[*ep];
4136641Smckusick 		if (braelist[*ep]==0)
4146641Smckusick 			return(0);
4156641Smckusick 		ct = braelist[*ep++] - bbeg;
4166641Smckusick 		curlp = lp;
4176641Smckusick 		while(ecmp(bbeg, lp, ct))
4186641Smckusick 			lp += ct;
4196641Smckusick 		while(lp >= curlp) {
4206641Smckusick 			if(advance(lp, ep))	return(1);
4216641Smckusick 			lp -= ct;
4226641Smckusick 		}
4236641Smckusick 		return(0);
4246641Smckusick 
4256641Smckusick 
4266641Smckusick 	case CDOT|STAR:
4276641Smckusick 		curlp = lp;
4286641Smckusick 		while (*lp++);
4296641Smckusick 		goto star;
4306641Smckusick 
4316641Smckusick 	case CCHR|STAR:
4326641Smckusick 		curlp = lp;
4336641Smckusick 		while (*lp++ == *ep);
4346641Smckusick 		ep++;
4356641Smckusick 		goto star;
4366641Smckusick 
4376641Smckusick 	case CCL|STAR:
4386641Smckusick 		curlp = lp;
4396641Smckusick 		do {
4406641Smckusick 			c = *lp++ & 0177;
4416641Smckusick 		} while(ep[c>>3] & bittab[c & 07]);
4426641Smckusick 		ep += 16;
4436641Smckusick 		goto star;
4446641Smckusick 
4456641Smckusick 	star:
4466641Smckusick 		if(--lp == curlp) {
4476641Smckusick 			continue;
4486641Smckusick 		}
4496641Smckusick 
4506641Smckusick 		if(*ep == CCHR) {
4516641Smckusick 			c = ep[1];
4526641Smckusick 			do {
4536641Smckusick 				if(*lp != c)
4546641Smckusick 					continue;
4556641Smckusick 				if(advance(lp, ep))
4566641Smckusick 					return(1);
4576641Smckusick 			} while(lp-- > curlp);
4586641Smckusick 			return(0);
4596641Smckusick 		}
4606641Smckusick 
4616641Smckusick 		do {
4626641Smckusick 			if (advance(lp, ep))
4636641Smckusick 				return(1);
4646641Smckusick 		} while (lp-- > curlp);
4656641Smckusick 		return(0);
4666641Smckusick 
46713484Ssam 	case CBRC:
46813484Ssam 		if (lp == expbuf)
46913484Ssam 			continue;
47013484Ssam #define	uletter(c)	(isalpha(c) || (c) == '_')
47113484Ssam 		if (uletter(*lp) || isdigit(*lp))
47213484Ssam 			if (!uletter(lp[-1]) && !isdigit(lp[-1]))
47313484Ssam 				continue;
47413484Ssam 		return (0);
47513484Ssam 
47613484Ssam 	case CLET:
47713484Ssam 		if (!uletter(*lp) && !isdigit(*lp))
47813484Ssam 			continue;
47913484Ssam 		return (0);
48013484Ssam 
4816641Smckusick 	default:
4826641Smckusick 		errexit("grep RE botch\n", (char *)NULL);
4836641Smckusick 	}
4846641Smckusick }
4856641Smckusick 
4866641Smckusick succeed(f)
4876641Smckusick char *f;
4886641Smckusick {
4896641Smckusick 	nsucc = 1;
4906641Smckusick 	if (sflag)
4916641Smckusick 		return;
4926641Smckusick 	if (cflag) {
4936641Smckusick 		tln++;
4946641Smckusick 		return;
4956641Smckusick 	}
4966641Smckusick 	if (lflag) {
4976641Smckusick 		printf("%s\n", f);
4986641Smckusick 		fflush(stdout);
4996641Smckusick 		fseek(stdin, 0l, 2);
5006641Smckusick 		return;
5016641Smckusick 	}
5026641Smckusick 	if (nfile > 1 && hflag)
5036641Smckusick 		printf("%s:", f);
5046641Smckusick 	if (bflag)
5056641Smckusick 		printf("%u:", blkno);
5066641Smckusick 	if (nflag)
5076641Smckusick 		printf("%ld:", lnum);
5086641Smckusick 	printf("%s\n", linebuf);
5096641Smckusick 	fflush(stdout);
5106641Smckusick }
5116641Smckusick 
5126641Smckusick ecmp(a, b, count)
5136641Smckusick char	*a, *b;
5146641Smckusick {
5156641Smckusick 	register cc = count;
5166641Smckusick 	while(cc--)
5176641Smckusick 		if(*a++ != *b++)	return(0);
5186641Smckusick 	return(1);
5196641Smckusick }
5206641Smckusick 
5216641Smckusick errexit(s, f)
5226641Smckusick char *s, *f;
5236641Smckusick {
5246641Smckusick 	fprintf(stderr, s, f);
5256641Smckusick 	exit(2);
5266641Smckusick }
527