1*12096Smckusick /*	old.bin.grep.c	4.3	83/04/29	*/
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
236641Smckusick #define	CBACK	18
246641Smckusick 
256641Smckusick #define	STAR	01
266641Smckusick 
276641Smckusick #define	LBSIZE	BUFSIZ
286641Smckusick #define	ESIZE	256
296641Smckusick #define	NBRA	9
306641Smckusick 
316641Smckusick char	expbuf[ESIZE];
326641Smckusick long	lnum;
336641Smckusick char	linebuf[LBSIZE+1];
346641Smckusick char	ybuf[ESIZE];
356641Smckusick int	bflag;
366641Smckusick int	lflag;
376641Smckusick int	nflag;
386641Smckusick int	cflag;
396641Smckusick int	vflag;
406641Smckusick int	nfile;
416641Smckusick int	hflag	= 1;
426641Smckusick int	sflag;
436641Smckusick int	yflag;
4411579Sedward int	retcode = 0;
456641Smckusick int	circf;
466641Smckusick int	blkno;
476641Smckusick long	tln;
486641Smckusick int	nsucc;
496641Smckusick char	*braslist[NBRA];
506641Smckusick char	*braelist[NBRA];
516641Smckusick char	bittab[] = {
526641Smckusick 	1,
536641Smckusick 	2,
546641Smckusick 	4,
556641Smckusick 	8,
566641Smckusick 	16,
576641Smckusick 	32,
586641Smckusick 	64,
596641Smckusick 	128
606641Smckusick };
616641Smckusick 
626641Smckusick main(argc, argv)
636641Smckusick char **argv;
646641Smckusick {
656641Smckusick 	extern char _sobuf[];
666641Smckusick 	setbuf(stdout, _sobuf);
676641Smckusick 	while (--argc > 0 && (++argv)[0][0]=='-')
686641Smckusick 		switch (argv[0][1]) {
696641Smckusick 
706641Smckusick 		case 'y':
716641Smckusick 			yflag++;
726641Smckusick 			continue;
736641Smckusick 
746641Smckusick 		case 'h':
756641Smckusick 			hflag = 0;
766641Smckusick 			continue;
776641Smckusick 
786641Smckusick 		case 's':
796641Smckusick 			sflag++;
806641Smckusick 			continue;
816641Smckusick 
826641Smckusick 		case 'v':
836641Smckusick 			vflag++;
846641Smckusick 			continue;
856641Smckusick 
866641Smckusick 		case 'b':
876641Smckusick 			bflag++;
886641Smckusick 			continue;
896641Smckusick 
906641Smckusick 		case 'l':
916641Smckusick 			lflag++;
926641Smckusick 			continue;
936641Smckusick 
946641Smckusick 		case 'c':
956641Smckusick 			cflag++;
966641Smckusick 			continue;
976641Smckusick 
986641Smckusick 		case 'n':
996641Smckusick 			nflag++;
1006641Smckusick 			continue;
1016641Smckusick 
1026641Smckusick 		case 'e':
1036641Smckusick 			--argc;
1046641Smckusick 			++argv;
1056641Smckusick 			goto out;
1066641Smckusick 
1076641Smckusick 		default:
1086641Smckusick 			errexit("grep: unknown flag\n", (char *)NULL);
1096641Smckusick 			continue;
1106641Smckusick 		}
1116641Smckusick out:
1126641Smckusick 	if (argc<=0)
1136641Smckusick 		exit(2);
1146641Smckusick 	if (yflag) {
1156641Smckusick 		register char *p, *s;
1166641Smckusick 		for (s = ybuf, p = *argv; *p; ) {
1176641Smckusick 			if (*p == '\\') {
1186641Smckusick 				*s++ = *p++;
1196641Smckusick 				if (*p)
1206641Smckusick 					*s++ = *p++;
1216641Smckusick 			} else if (*p == '[') {
1226641Smckusick 				while (*p != '\0' && *p != ']')
1236641Smckusick 					*s++ = *p++;
1246641Smckusick 			} else if (islower(*p)) {
1256641Smckusick 				*s++ = '[';
1266641Smckusick 				*s++ = toupper(*p);
1276641Smckusick 				*s++ = *p++;
1286641Smckusick 				*s++ = ']';
1296641Smckusick 			} else
1306641Smckusick 				*s++ = *p++;
1316641Smckusick 			if (s >= ybuf+ESIZE-5)
1326641Smckusick 				errexit("grep: argument too long\n", (char *)NULL);
1336641Smckusick 		}
1346641Smckusick 		*s = '\0';
1356641Smckusick 		*argv = ybuf;
1366641Smckusick 	}
1376641Smckusick 	compile(*argv);
1386641Smckusick 	nfile = --argc;
1396641Smckusick 	if (argc<=0) {
1406641Smckusick 		if (lflag)
1416641Smckusick 			exit(1);
1426641Smckusick 		execute((char *)NULL);
1436641Smckusick 	} else while (--argc >= 0) {
1446641Smckusick 		argv++;
1456641Smckusick 		execute(*argv);
1466641Smckusick 	}
14711579Sedward 	exit(retcode != 0 ? retcode : nsucc == 0);
1486641Smckusick }
1496641Smckusick 
1506641Smckusick compile(astr)
1516641Smckusick char *astr;
1526641Smckusick {
1536641Smckusick 	register c;
1546641Smckusick 	register char *ep, *sp;
1556641Smckusick 	char *cstart;
1566641Smckusick 	char *lastep;
1576641Smckusick 	int cclcnt;
1586641Smckusick 	char bracket[NBRA], *bracketp;
1596641Smckusick 	int closed;
1606641Smckusick 	char numbra;
1616641Smckusick 	char neg;
1626641Smckusick 
1636641Smckusick 	ep = expbuf;
1646641Smckusick 	sp = astr;
1656641Smckusick 	lastep = 0;
1666641Smckusick 	bracketp = bracket;
1676641Smckusick 	closed = numbra = 0;
1686641Smckusick 	if (*sp == '^') {
1696641Smckusick 		circf++;
1706641Smckusick 		sp++;
1716641Smckusick 	}
1726641Smckusick 	for (;;) {
1736641Smckusick 		if (ep >= &expbuf[ESIZE])
1746641Smckusick 			goto cerror;
1756641Smckusick 		if ((c = *sp++) != '*')
1766641Smckusick 			lastep = ep;
1776641Smckusick 		switch (c) {
1786641Smckusick 
1796641Smckusick 		case '\0':
1806641Smckusick 			*ep++ = CEOF;
1816641Smckusick 			return;
1826641Smckusick 
1836641Smckusick 		case '.':
1846641Smckusick 			*ep++ = CDOT;
1856641Smckusick 			continue;
1866641Smckusick 
1876641Smckusick 		case '*':
1886641Smckusick 			if (lastep==0 || *lastep==CBRA || *lastep==CKET)
1896641Smckusick 				goto defchar;
1906641Smckusick 			*lastep |= STAR;
1916641Smckusick 			continue;
1926641Smckusick 
1936641Smckusick 		case '$':
1946641Smckusick 			if (*sp != '\0')
1956641Smckusick 				goto defchar;
1966641Smckusick 			*ep++ = CDOL;
1976641Smckusick 			continue;
1986641Smckusick 
1996641Smckusick 		case '[':
2006641Smckusick 			if(&ep[17] >= &expbuf[ESIZE])
2016641Smckusick 				goto cerror;
2026641Smckusick 			*ep++ = CCL;
2036641Smckusick 			neg = 0;
2046641Smckusick 			if((c = *sp++) == '^') {
2056641Smckusick 				neg = 1;
2066641Smckusick 				c = *sp++;
2076641Smckusick 			}
2086641Smckusick 			cstart = sp;
2096641Smckusick 			do {
2106641Smckusick 				if (c=='\0')
2116641Smckusick 					goto cerror;
2126641Smckusick 				if (c=='-' && sp>cstart && *sp!=']') {
2136641Smckusick 					for (c = sp[-2]; c<*sp; c++)
2146641Smckusick 						ep[c>>3] |= bittab[c&07];
2156641Smckusick 					sp++;
2166641Smckusick 				}
2176641Smckusick 				ep[c>>3] |= bittab[c&07];
2186641Smckusick 			} while((c = *sp++) != ']');
2196641Smckusick 			if(neg) {
2206641Smckusick 				for(cclcnt = 0; cclcnt < 16; cclcnt++)
2216641Smckusick 					ep[cclcnt] ^= -1;
2226641Smckusick 				ep[0] &= 0376;
2236641Smckusick 			}
2246641Smckusick 
2256641Smckusick 			ep += 16;
2266641Smckusick 
2276641Smckusick 			continue;
2286641Smckusick 
2296641Smckusick 		case '\\':
2306641Smckusick 			if((c = *sp++) == '(') {
2316641Smckusick 				if(numbra >= NBRA) {
2326641Smckusick 					goto cerror;
2336641Smckusick 				}
2346641Smckusick 				*bracketp++ = numbra;
2356641Smckusick 				*ep++ = CBRA;
2366641Smckusick 				*ep++ = numbra++;
2376641Smckusick 				continue;
2386641Smckusick 			}
2396641Smckusick 			if(c == ')') {
2406641Smckusick 				if(bracketp <= bracket) {
2416641Smckusick 					goto cerror;
2426641Smckusick 				}
2436641Smckusick 				*ep++ = CKET;
2446641Smckusick 				*ep++ = *--bracketp;
2456641Smckusick 				closed++;
2466641Smckusick 				continue;
2476641Smckusick 			}
2486641Smckusick 
2496641Smckusick 			if(c >= '1' && c <= '9') {
2506641Smckusick 				if((c -= '1') >= closed)
2516641Smckusick 					goto cerror;
2526641Smckusick 				*ep++ = CBACK;
2536641Smckusick 				*ep++ = c;
2546641Smckusick 				continue;
2556641Smckusick 			}
2566641Smckusick 
2576641Smckusick 		defchar:
2586641Smckusick 		default:
2596641Smckusick 			*ep++ = CCHR;
2606641Smckusick 			*ep++ = c;
2616641Smckusick 		}
2626641Smckusick 	}
2636641Smckusick     cerror:
2646641Smckusick 	errexit("grep: RE error\n", (char *)NULL);
2656641Smckusick }
2666641Smckusick 
2676641Smckusick execute(file)
2686641Smckusick char *file;
2696641Smckusick {
2706641Smckusick 	register char *p1, *p2;
2716641Smckusick 	register c;
2726641Smckusick 
2736641Smckusick 	if (file) {
27411579Sedward 		if (freopen(file, "r", stdin) == NULL) {
275*12096Smckusick 			perror(file);
27611579Sedward 			retcode = 2;
27711579Sedward 		}
2786641Smckusick 	}
2796641Smckusick 	lnum = 0;
2806641Smckusick 	tln = 0;
2816641Smckusick 	for (;;) {
2826641Smckusick 		lnum++;
2836641Smckusick 		p1 = linebuf;
2846641Smckusick 		while ((c = getchar()) != '\n') {
2856641Smckusick 			if (c == EOF) {
2866641Smckusick 				if (cflag) {
2876641Smckusick 					if (nfile>1)
2886641Smckusick 						printf("%s:", file);
2896641Smckusick 					printf("%D\n", tln);
2906641Smckusick 					fflush(stdout);
2916641Smckusick 				}
2926641Smckusick 				return;
2936641Smckusick 			}
2946641Smckusick 			*p1++ = c;
2956641Smckusick 			if (p1 >= &linebuf[LBSIZE-1])
2966641Smckusick 				break;
2976641Smckusick 		}
2986641Smckusick 		*p1++ = '\0';
2996641Smckusick 		p1 = linebuf;
3006641Smckusick 		p2 = expbuf;
3016641Smckusick 		if (circf) {
3026641Smckusick 			if (advance(p1, p2))
3036641Smckusick 				goto found;
3046641Smckusick 			goto nfound;
3056641Smckusick 		}
3066641Smckusick 		/* fast check for first character */
3076641Smckusick 		if (*p2==CCHR) {
3086641Smckusick 			c = p2[1];
3096641Smckusick 			do {
3106641Smckusick 				if (*p1!=c)
3116641Smckusick 					continue;
3126641Smckusick 				if (advance(p1, p2))
3136641Smckusick 					goto found;
3146641Smckusick 			} while (*p1++);
3156641Smckusick 			goto nfound;
3166641Smckusick 		}
3176641Smckusick 		/* regular algorithm */
3186641Smckusick 		do {
3196641Smckusick 			if (advance(p1, p2))
3206641Smckusick 				goto found;
3216641Smckusick 		} while (*p1++);
3226641Smckusick 	nfound:
3236641Smckusick 		if (vflag)
3246641Smckusick 			succeed(file);
3256641Smckusick 		continue;
3266641Smckusick 	found:
3276641Smckusick 		if (vflag==0)
3286641Smckusick 			succeed(file);
3296641Smckusick 	}
3306641Smckusick }
3316641Smckusick 
3326641Smckusick advance(lp, ep)
3336641Smckusick register char *lp, *ep;
3346641Smckusick {
3356641Smckusick 	register char *curlp;
3366641Smckusick 	char c;
3376641Smckusick 	char *bbeg;
3386641Smckusick 	int ct;
3396641Smckusick 
3406641Smckusick 	for (;;) switch (*ep++) {
3416641Smckusick 
3426641Smckusick 	case CCHR:
3436641Smckusick 		if (*ep++ == *lp++)
3446641Smckusick 			continue;
3456641Smckusick 		return(0);
3466641Smckusick 
3476641Smckusick 	case CDOT:
3486641Smckusick 		if (*lp++)
3496641Smckusick 			continue;
3506641Smckusick 		return(0);
3516641Smckusick 
3526641Smckusick 	case CDOL:
3536641Smckusick 		if (*lp==0)
3546641Smckusick 			continue;
3556641Smckusick 		return(0);
3566641Smckusick 
3576641Smckusick 	case CEOF:
3586641Smckusick 		return(1);
3596641Smckusick 
3606641Smckusick 	case CCL:
3616641Smckusick 		c = *lp++ & 0177;
3626641Smckusick 		if(ep[c>>3] & bittab[c & 07]) {
3636641Smckusick 			ep += 16;
3646641Smckusick 			continue;
3656641Smckusick 		}
3666641Smckusick 		return(0);
3676641Smckusick 	case CBRA:
3686641Smckusick 		braslist[*ep++] = lp;
3696641Smckusick 		continue;
3706641Smckusick 
3716641Smckusick 	case CKET:
3726641Smckusick 		braelist[*ep++] = lp;
3736641Smckusick 		continue;
3746641Smckusick 
3756641Smckusick 	case CBACK:
3766641Smckusick 		bbeg = braslist[*ep];
3776641Smckusick 		if (braelist[*ep]==0)
3786641Smckusick 			return(0);
3796641Smckusick 		ct = braelist[*ep++] - bbeg;
3806641Smckusick 		if(ecmp(bbeg, lp, ct)) {
3816641Smckusick 			lp += ct;
3826641Smckusick 			continue;
3836641Smckusick 		}
3846641Smckusick 		return(0);
3856641Smckusick 
3866641Smckusick 	case CBACK|STAR:
3876641Smckusick 		bbeg = braslist[*ep];
3886641Smckusick 		if (braelist[*ep]==0)
3896641Smckusick 			return(0);
3906641Smckusick 		ct = braelist[*ep++] - bbeg;
3916641Smckusick 		curlp = lp;
3926641Smckusick 		while(ecmp(bbeg, lp, ct))
3936641Smckusick 			lp += ct;
3946641Smckusick 		while(lp >= curlp) {
3956641Smckusick 			if(advance(lp, ep))	return(1);
3966641Smckusick 			lp -= ct;
3976641Smckusick 		}
3986641Smckusick 		return(0);
3996641Smckusick 
4006641Smckusick 
4016641Smckusick 	case CDOT|STAR:
4026641Smckusick 		curlp = lp;
4036641Smckusick 		while (*lp++);
4046641Smckusick 		goto star;
4056641Smckusick 
4066641Smckusick 	case CCHR|STAR:
4076641Smckusick 		curlp = lp;
4086641Smckusick 		while (*lp++ == *ep);
4096641Smckusick 		ep++;
4106641Smckusick 		goto star;
4116641Smckusick 
4126641Smckusick 	case CCL|STAR:
4136641Smckusick 		curlp = lp;
4146641Smckusick 		do {
4156641Smckusick 			c = *lp++ & 0177;
4166641Smckusick 		} while(ep[c>>3] & bittab[c & 07]);
4176641Smckusick 		ep += 16;
4186641Smckusick 		goto star;
4196641Smckusick 
4206641Smckusick 	star:
4216641Smckusick 		if(--lp == curlp) {
4226641Smckusick 			continue;
4236641Smckusick 		}
4246641Smckusick 
4256641Smckusick 		if(*ep == CCHR) {
4266641Smckusick 			c = ep[1];
4276641Smckusick 			do {
4286641Smckusick 				if(*lp != c)
4296641Smckusick 					continue;
4306641Smckusick 				if(advance(lp, ep))
4316641Smckusick 					return(1);
4326641Smckusick 			} while(lp-- > curlp);
4336641Smckusick 			return(0);
4346641Smckusick 		}
4356641Smckusick 
4366641Smckusick 		do {
4376641Smckusick 			if (advance(lp, ep))
4386641Smckusick 				return(1);
4396641Smckusick 		} while (lp-- > curlp);
4406641Smckusick 		return(0);
4416641Smckusick 
4426641Smckusick 	default:
4436641Smckusick 		errexit("grep RE botch\n", (char *)NULL);
4446641Smckusick 	}
4456641Smckusick }
4466641Smckusick 
4476641Smckusick succeed(f)
4486641Smckusick char *f;
4496641Smckusick {
4506641Smckusick 	nsucc = 1;
4516641Smckusick 	if (sflag)
4526641Smckusick 		return;
4536641Smckusick 	if (cflag) {
4546641Smckusick 		tln++;
4556641Smckusick 		return;
4566641Smckusick 	}
4576641Smckusick 	if (lflag) {
4586641Smckusick 		printf("%s\n", f);
4596641Smckusick 		fflush(stdout);
4606641Smckusick 		fseek(stdin, 0l, 2);
4616641Smckusick 		return;
4626641Smckusick 	}
4636641Smckusick 	if (nfile > 1 && hflag)
4646641Smckusick 		printf("%s:", f);
4656641Smckusick 	if (bflag)
4666641Smckusick 		printf("%u:", blkno);
4676641Smckusick 	if (nflag)
4686641Smckusick 		printf("%ld:", lnum);
4696641Smckusick 	printf("%s\n", linebuf);
4706641Smckusick 	fflush(stdout);
4716641Smckusick }
4726641Smckusick 
4736641Smckusick ecmp(a, b, count)
4746641Smckusick char	*a, *b;
4756641Smckusick {
4766641Smckusick 	register cc = count;
4776641Smckusick 	while(cc--)
4786641Smckusick 		if(*a++ != *b++)	return(0);
4796641Smckusick 	return(1);
4806641Smckusick }
4816641Smckusick 
4826641Smckusick errexit(s, f)
4836641Smckusick char *s, *f;
4846641Smckusick {
4856641Smckusick 	fprintf(stderr, s, f);
4866641Smckusick 	exit(2);
4876641Smckusick }
488