1*13484Ssam /*	old.bin.grep.c	4.4	83/06/30	*/
26641Smckusick 
36641Smckusick /*
46641Smckusick  * grep -- print lines matching (or not matching) a pattern
56641Smckusick  *
66641Smckusick  *	status returns:
76641Smckusick  *		0 - ok, and some matches
86641Smckusick  *		1 - ok, but no matches
96641Smckusick  *		2 - some error
106641Smckusick  */
116641Smckusick 
126641Smckusick #include <stdio.h>
136641Smckusick #include <ctype.h>
146641Smckusick 
156641Smckusick #define	CBRA	1
166641Smckusick #define	CCHR	2
176641Smckusick #define	CDOT	4
186641Smckusick #define	CCL	6
196641Smckusick #define	NCCL	8
206641Smckusick #define	CDOL	10
216641Smckusick #define	CEOF	11
226641Smckusick #define	CKET	12
23*13484Ssam #define	CBRC	14
24*13484Ssam #define	CLET	15
256641Smckusick #define	CBACK	18
266641Smckusick 
276641Smckusick #define	STAR	01
286641Smckusick 
296641Smckusick #define	LBSIZE	BUFSIZ
306641Smckusick #define	ESIZE	256
316641Smckusick #define	NBRA	9
326641Smckusick 
336641Smckusick char	expbuf[ESIZE];
346641Smckusick long	lnum;
356641Smckusick char	linebuf[LBSIZE+1];
366641Smckusick char	ybuf[ESIZE];
376641Smckusick int	bflag;
386641Smckusick int	lflag;
396641Smckusick int	nflag;
406641Smckusick int	cflag;
416641Smckusick int	vflag;
426641Smckusick int	nfile;
436641Smckusick int	hflag	= 1;
446641Smckusick int	sflag;
456641Smckusick int	yflag;
46*13484Ssam int	wflag;
4711579Sedward int	retcode = 0;
486641Smckusick int	circf;
496641Smckusick int	blkno;
506641Smckusick long	tln;
516641Smckusick int	nsucc;
526641Smckusick char	*braslist[NBRA];
536641Smckusick char	*braelist[NBRA];
546641Smckusick char	bittab[] = {
556641Smckusick 	1,
566641Smckusick 	2,
576641Smckusick 	4,
586641Smckusick 	8,
596641Smckusick 	16,
606641Smckusick 	32,
616641Smckusick 	64,
626641Smckusick 	128
636641Smckusick };
646641Smckusick 
656641Smckusick main(argc, argv)
666641Smckusick char **argv;
676641Smckusick {
686641Smckusick 	extern char _sobuf[];
696641Smckusick 	setbuf(stdout, _sobuf);
706641Smckusick 	while (--argc > 0 && (++argv)[0][0]=='-')
716641Smckusick 		switch (argv[0][1]) {
726641Smckusick 
73*13484Ssam 		case 'i':
746641Smckusick 		case 'y':
756641Smckusick 			yflag++;
766641Smckusick 			continue;
776641Smckusick 
78*13484Ssam 		case 'w':
79*13484Ssam 			wflag++;
80*13484Ssam 			continue;
81*13484Ssam 
826641Smckusick 		case 'h':
836641Smckusick 			hflag = 0;
846641Smckusick 			continue;
856641Smckusick 
866641Smckusick 		case 's':
876641Smckusick 			sflag++;
886641Smckusick 			continue;
896641Smckusick 
906641Smckusick 		case 'v':
916641Smckusick 			vflag++;
926641Smckusick 			continue;
936641Smckusick 
946641Smckusick 		case 'b':
956641Smckusick 			bflag++;
966641Smckusick 			continue;
976641Smckusick 
986641Smckusick 		case 'l':
996641Smckusick 			lflag++;
1006641Smckusick 			continue;
1016641Smckusick 
1026641Smckusick 		case 'c':
1036641Smckusick 			cflag++;
1046641Smckusick 			continue;
1056641Smckusick 
1066641Smckusick 		case 'n':
1076641Smckusick 			nflag++;
1086641Smckusick 			continue;
1096641Smckusick 
1106641Smckusick 		case 'e':
1116641Smckusick 			--argc;
1126641Smckusick 			++argv;
1136641Smckusick 			goto out;
1146641Smckusick 
1156641Smckusick 		default:
1166641Smckusick 			errexit("grep: unknown flag\n", (char *)NULL);
1176641Smckusick 			continue;
1186641Smckusick 		}
1196641Smckusick out:
1206641Smckusick 	if (argc<=0)
1216641Smckusick 		exit(2);
1226641Smckusick 	if (yflag) {
1236641Smckusick 		register char *p, *s;
1246641Smckusick 		for (s = ybuf, p = *argv; *p; ) {
1256641Smckusick 			if (*p == '\\') {
1266641Smckusick 				*s++ = *p++;
1276641Smckusick 				if (*p)
1286641Smckusick 					*s++ = *p++;
1296641Smckusick 			} else if (*p == '[') {
1306641Smckusick 				while (*p != '\0' && *p != ']')
1316641Smckusick 					*s++ = *p++;
1326641Smckusick 			} else if (islower(*p)) {
1336641Smckusick 				*s++ = '[';
1346641Smckusick 				*s++ = toupper(*p);
1356641Smckusick 				*s++ = *p++;
1366641Smckusick 				*s++ = ']';
1376641Smckusick 			} else
1386641Smckusick 				*s++ = *p++;
1396641Smckusick 			if (s >= ybuf+ESIZE-5)
1406641Smckusick 				errexit("grep: argument too long\n", (char *)NULL);
1416641Smckusick 		}
1426641Smckusick 		*s = '\0';
1436641Smckusick 		*argv = ybuf;
1446641Smckusick 	}
1456641Smckusick 	compile(*argv);
1466641Smckusick 	nfile = --argc;
1476641Smckusick 	if (argc<=0) {
1486641Smckusick 		if (lflag)
1496641Smckusick 			exit(1);
1506641Smckusick 		execute((char *)NULL);
1516641Smckusick 	} else while (--argc >= 0) {
1526641Smckusick 		argv++;
1536641Smckusick 		execute(*argv);
1546641Smckusick 	}
15511579Sedward 	exit(retcode != 0 ? retcode : nsucc == 0);
1566641Smckusick }
1576641Smckusick 
1586641Smckusick compile(astr)
1596641Smckusick char *astr;
1606641Smckusick {
1616641Smckusick 	register c;
1626641Smckusick 	register char *ep, *sp;
1636641Smckusick 	char *cstart;
1646641Smckusick 	char *lastep;
1656641Smckusick 	int cclcnt;
1666641Smckusick 	char bracket[NBRA], *bracketp;
1676641Smckusick 	int closed;
1686641Smckusick 	char numbra;
1696641Smckusick 	char neg;
1706641Smckusick 
1716641Smckusick 	ep = expbuf;
1726641Smckusick 	sp = astr;
1736641Smckusick 	lastep = 0;
1746641Smckusick 	bracketp = bracket;
1756641Smckusick 	closed = numbra = 0;
1766641Smckusick 	if (*sp == '^') {
1776641Smckusick 		circf++;
1786641Smckusick 		sp++;
1796641Smckusick 	}
180*13484Ssam 	if (wflag)
181*13484Ssam 		*ep++ = CBRC;
1826641Smckusick 	for (;;) {
1836641Smckusick 		if (ep >= &expbuf[ESIZE])
1846641Smckusick 			goto cerror;
1856641Smckusick 		if ((c = *sp++) != '*')
1866641Smckusick 			lastep = ep;
1876641Smckusick 		switch (c) {
1886641Smckusick 
1896641Smckusick 		case '\0':
190*13484Ssam 			if (wflag)
191*13484Ssam 				*ep++ = CLET;
1926641Smckusick 			*ep++ = CEOF;
1936641Smckusick 			return;
1946641Smckusick 
1956641Smckusick 		case '.':
1966641Smckusick 			*ep++ = CDOT;
1976641Smckusick 			continue;
1986641Smckusick 
1996641Smckusick 		case '*':
200*13484Ssam 			if (lastep==0 || *lastep==CBRA || *lastep==CKET ||
201*13484Ssam 			    *lastep == CBRC || *lastep == CLET)
2026641Smckusick 				goto defchar;
2036641Smckusick 			*lastep |= STAR;
2046641Smckusick 			continue;
2056641Smckusick 
2066641Smckusick 		case '$':
2076641Smckusick 			if (*sp != '\0')
2086641Smckusick 				goto defchar;
2096641Smckusick 			*ep++ = CDOL;
2106641Smckusick 			continue;
2116641Smckusick 
2126641Smckusick 		case '[':
2136641Smckusick 			if(&ep[17] >= &expbuf[ESIZE])
2146641Smckusick 				goto cerror;
2156641Smckusick 			*ep++ = CCL;
2166641Smckusick 			neg = 0;
2176641Smckusick 			if((c = *sp++) == '^') {
2186641Smckusick 				neg = 1;
2196641Smckusick 				c = *sp++;
2206641Smckusick 			}
2216641Smckusick 			cstart = sp;
2226641Smckusick 			do {
2236641Smckusick 				if (c=='\0')
2246641Smckusick 					goto cerror;
2256641Smckusick 				if (c=='-' && sp>cstart && *sp!=']') {
2266641Smckusick 					for (c = sp[-2]; c<*sp; c++)
2276641Smckusick 						ep[c>>3] |= bittab[c&07];
2286641Smckusick 					sp++;
2296641Smckusick 				}
2306641Smckusick 				ep[c>>3] |= bittab[c&07];
2316641Smckusick 			} while((c = *sp++) != ']');
2326641Smckusick 			if(neg) {
2336641Smckusick 				for(cclcnt = 0; cclcnt < 16; cclcnt++)
2346641Smckusick 					ep[cclcnt] ^= -1;
2356641Smckusick 				ep[0] &= 0376;
2366641Smckusick 			}
2376641Smckusick 
2386641Smckusick 			ep += 16;
2396641Smckusick 
2406641Smckusick 			continue;
2416641Smckusick 
2426641Smckusick 		case '\\':
243*13484Ssam 			if((c = *sp++) == 0)
244*13484Ssam 				goto cerror;
245*13484Ssam 			if(c == '<') {
246*13484Ssam 				*ep++ = CBRC;
247*13484Ssam 				continue;
248*13484Ssam 			}
249*13484Ssam 			if(c == '>') {
250*13484Ssam 				*ep++ = CLET;
251*13484Ssam 				continue;
252*13484Ssam 			}
253*13484Ssam 			if(c == '(') {
2546641Smckusick 				if(numbra >= NBRA) {
2556641Smckusick 					goto cerror;
2566641Smckusick 				}
2576641Smckusick 				*bracketp++ = numbra;
2586641Smckusick 				*ep++ = CBRA;
2596641Smckusick 				*ep++ = numbra++;
2606641Smckusick 				continue;
2616641Smckusick 			}
2626641Smckusick 			if(c == ')') {
2636641Smckusick 				if(bracketp <= bracket) {
2646641Smckusick 					goto cerror;
2656641Smckusick 				}
2666641Smckusick 				*ep++ = CKET;
2676641Smckusick 				*ep++ = *--bracketp;
2686641Smckusick 				closed++;
2696641Smckusick 				continue;
2706641Smckusick 			}
2716641Smckusick 
2726641Smckusick 			if(c >= '1' && c <= '9') {
2736641Smckusick 				if((c -= '1') >= closed)
2746641Smckusick 					goto cerror;
2756641Smckusick 				*ep++ = CBACK;
2766641Smckusick 				*ep++ = c;
2776641Smckusick 				continue;
2786641Smckusick 			}
2796641Smckusick 
2806641Smckusick 		defchar:
2816641Smckusick 		default:
2826641Smckusick 			*ep++ = CCHR;
2836641Smckusick 			*ep++ = c;
2846641Smckusick 		}
2856641Smckusick 	}
2866641Smckusick     cerror:
2876641Smckusick 	errexit("grep: RE error\n", (char *)NULL);
2886641Smckusick }
2896641Smckusick 
2906641Smckusick execute(file)
2916641Smckusick char *file;
2926641Smckusick {
2936641Smckusick 	register char *p1, *p2;
2946641Smckusick 	register c;
2956641Smckusick 
2966641Smckusick 	if (file) {
29711579Sedward 		if (freopen(file, "r", stdin) == NULL) {
29812096Smckusick 			perror(file);
29911579Sedward 			retcode = 2;
30011579Sedward 		}
3016641Smckusick 	}
3026641Smckusick 	lnum = 0;
3036641Smckusick 	tln = 0;
3046641Smckusick 	for (;;) {
3056641Smckusick 		lnum++;
3066641Smckusick 		p1 = linebuf;
3076641Smckusick 		while ((c = getchar()) != '\n') {
3086641Smckusick 			if (c == EOF) {
3096641Smckusick 				if (cflag) {
3106641Smckusick 					if (nfile>1)
3116641Smckusick 						printf("%s:", file);
3126641Smckusick 					printf("%D\n", tln);
3136641Smckusick 					fflush(stdout);
3146641Smckusick 				}
3156641Smckusick 				return;
3166641Smckusick 			}
3176641Smckusick 			*p1++ = c;
3186641Smckusick 			if (p1 >= &linebuf[LBSIZE-1])
3196641Smckusick 				break;
3206641Smckusick 		}
3216641Smckusick 		*p1++ = '\0';
3226641Smckusick 		p1 = linebuf;
3236641Smckusick 		p2 = expbuf;
3246641Smckusick 		if (circf) {
3256641Smckusick 			if (advance(p1, p2))
3266641Smckusick 				goto found;
3276641Smckusick 			goto nfound;
3286641Smckusick 		}
3296641Smckusick 		/* fast check for first character */
3306641Smckusick 		if (*p2==CCHR) {
3316641Smckusick 			c = p2[1];
3326641Smckusick 			do {
3336641Smckusick 				if (*p1!=c)
3346641Smckusick 					continue;
3356641Smckusick 				if (advance(p1, p2))
3366641Smckusick 					goto found;
3376641Smckusick 			} while (*p1++);
3386641Smckusick 			goto nfound;
3396641Smckusick 		}
3406641Smckusick 		/* regular algorithm */
3416641Smckusick 		do {
3426641Smckusick 			if (advance(p1, p2))
3436641Smckusick 				goto found;
3446641Smckusick 		} while (*p1++);
3456641Smckusick 	nfound:
3466641Smckusick 		if (vflag)
3476641Smckusick 			succeed(file);
3486641Smckusick 		continue;
3496641Smckusick 	found:
3506641Smckusick 		if (vflag==0)
3516641Smckusick 			succeed(file);
3526641Smckusick 	}
3536641Smckusick }
3546641Smckusick 
3556641Smckusick advance(lp, ep)
3566641Smckusick register char *lp, *ep;
3576641Smckusick {
3586641Smckusick 	register char *curlp;
3596641Smckusick 	char c;
3606641Smckusick 	char *bbeg;
3616641Smckusick 	int ct;
3626641Smckusick 
3636641Smckusick 	for (;;) switch (*ep++) {
3646641Smckusick 
3656641Smckusick 	case CCHR:
3666641Smckusick 		if (*ep++ == *lp++)
3676641Smckusick 			continue;
3686641Smckusick 		return(0);
3696641Smckusick 
3706641Smckusick 	case CDOT:
3716641Smckusick 		if (*lp++)
3726641Smckusick 			continue;
3736641Smckusick 		return(0);
3746641Smckusick 
3756641Smckusick 	case CDOL:
3766641Smckusick 		if (*lp==0)
3776641Smckusick 			continue;
3786641Smckusick 		return(0);
3796641Smckusick 
3806641Smckusick 	case CEOF:
3816641Smckusick 		return(1);
3826641Smckusick 
3836641Smckusick 	case CCL:
3846641Smckusick 		c = *lp++ & 0177;
3856641Smckusick 		if(ep[c>>3] & bittab[c & 07]) {
3866641Smckusick 			ep += 16;
3876641Smckusick 			continue;
3886641Smckusick 		}
3896641Smckusick 		return(0);
3906641Smckusick 	case CBRA:
3916641Smckusick 		braslist[*ep++] = lp;
3926641Smckusick 		continue;
3936641Smckusick 
3946641Smckusick 	case CKET:
3956641Smckusick 		braelist[*ep++] = lp;
3966641Smckusick 		continue;
3976641Smckusick 
3986641Smckusick 	case CBACK:
3996641Smckusick 		bbeg = braslist[*ep];
4006641Smckusick 		if (braelist[*ep]==0)
4016641Smckusick 			return(0);
4026641Smckusick 		ct = braelist[*ep++] - bbeg;
4036641Smckusick 		if(ecmp(bbeg, lp, ct)) {
4046641Smckusick 			lp += ct;
4056641Smckusick 			continue;
4066641Smckusick 		}
4076641Smckusick 		return(0);
4086641Smckusick 
4096641Smckusick 	case CBACK|STAR:
4106641Smckusick 		bbeg = braslist[*ep];
4116641Smckusick 		if (braelist[*ep]==0)
4126641Smckusick 			return(0);
4136641Smckusick 		ct = braelist[*ep++] - bbeg;
4146641Smckusick 		curlp = lp;
4156641Smckusick 		while(ecmp(bbeg, lp, ct))
4166641Smckusick 			lp += ct;
4176641Smckusick 		while(lp >= curlp) {
4186641Smckusick 			if(advance(lp, ep))	return(1);
4196641Smckusick 			lp -= ct;
4206641Smckusick 		}
4216641Smckusick 		return(0);
4226641Smckusick 
4236641Smckusick 
4246641Smckusick 	case CDOT|STAR:
4256641Smckusick 		curlp = lp;
4266641Smckusick 		while (*lp++);
4276641Smckusick 		goto star;
4286641Smckusick 
4296641Smckusick 	case CCHR|STAR:
4306641Smckusick 		curlp = lp;
4316641Smckusick 		while (*lp++ == *ep);
4326641Smckusick 		ep++;
4336641Smckusick 		goto star;
4346641Smckusick 
4356641Smckusick 	case CCL|STAR:
4366641Smckusick 		curlp = lp;
4376641Smckusick 		do {
4386641Smckusick 			c = *lp++ & 0177;
4396641Smckusick 		} while(ep[c>>3] & bittab[c & 07]);
4406641Smckusick 		ep += 16;
4416641Smckusick 		goto star;
4426641Smckusick 
4436641Smckusick 	star:
4446641Smckusick 		if(--lp == curlp) {
4456641Smckusick 			continue;
4466641Smckusick 		}
4476641Smckusick 
4486641Smckusick 		if(*ep == CCHR) {
4496641Smckusick 			c = ep[1];
4506641Smckusick 			do {
4516641Smckusick 				if(*lp != c)
4526641Smckusick 					continue;
4536641Smckusick 				if(advance(lp, ep))
4546641Smckusick 					return(1);
4556641Smckusick 			} while(lp-- > curlp);
4566641Smckusick 			return(0);
4576641Smckusick 		}
4586641Smckusick 
4596641Smckusick 		do {
4606641Smckusick 			if (advance(lp, ep))
4616641Smckusick 				return(1);
4626641Smckusick 		} while (lp-- > curlp);
4636641Smckusick 		return(0);
4646641Smckusick 
465*13484Ssam 	case CBRC:
466*13484Ssam 		if (lp == expbuf)
467*13484Ssam 			continue;
468*13484Ssam #define	uletter(c)	(isalpha(c) || (c) == '_')
469*13484Ssam 		if (uletter(*lp) || isdigit(*lp))
470*13484Ssam 			if (!uletter(lp[-1]) && !isdigit(lp[-1]))
471*13484Ssam 				continue;
472*13484Ssam 		return (0);
473*13484Ssam 
474*13484Ssam 	case CLET:
475*13484Ssam 		if (!uletter(*lp) && !isdigit(*lp))
476*13484Ssam 			continue;
477*13484Ssam 		return (0);
478*13484Ssam 
4796641Smckusick 	default:
4806641Smckusick 		errexit("grep RE botch\n", (char *)NULL);
4816641Smckusick 	}
4826641Smckusick }
4836641Smckusick 
4846641Smckusick succeed(f)
4856641Smckusick char *f;
4866641Smckusick {
4876641Smckusick 	nsucc = 1;
4886641Smckusick 	if (sflag)
4896641Smckusick 		return;
4906641Smckusick 	if (cflag) {
4916641Smckusick 		tln++;
4926641Smckusick 		return;
4936641Smckusick 	}
4946641Smckusick 	if (lflag) {
4956641Smckusick 		printf("%s\n", f);
4966641Smckusick 		fflush(stdout);
4976641Smckusick 		fseek(stdin, 0l, 2);
4986641Smckusick 		return;
4996641Smckusick 	}
5006641Smckusick 	if (nfile > 1 && hflag)
5016641Smckusick 		printf("%s:", f);
5026641Smckusick 	if (bflag)
5036641Smckusick 		printf("%u:", blkno);
5046641Smckusick 	if (nflag)
5056641Smckusick 		printf("%ld:", lnum);
5066641Smckusick 	printf("%s\n", linebuf);
5076641Smckusick 	fflush(stdout);
5086641Smckusick }
5096641Smckusick 
5106641Smckusick ecmp(a, b, count)
5116641Smckusick char	*a, *b;
5126641Smckusick {
5136641Smckusick 	register cc = count;
5146641Smckusick 	while(cc--)
5156641Smckusick 		if(*a++ != *b++)	return(0);
5166641Smckusick 	return(1);
5176641Smckusick }
5186641Smckusick 
5196641Smckusick errexit(s, f)
5206641Smckusick char *s, *f;
5216641Smckusick {
5226641Smckusick 	fprintf(stderr, s, f);
5236641Smckusick 	exit(2);
5246641Smckusick }
525