121559Sdist /*
221559Sdist  * Copyright (c) 1980 Regents of the University of California.
321559Sdist  * All rights reserved.  The Berkeley software License Agreement
421559Sdist  * specifies the terms and conditions for redistribution.
521559Sdist  */
621559Sdist 
714516Ssam #ifndef lint
821559Sdist char copyright[] =
921559Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\
1021559Sdist  All rights reserved.\n";
1121559Sdist #endif not lint
126639Smckusick 
1321559Sdist #ifndef lint
14*32365Sbostic static char sccsid[] = "@(#)old.ucb.grep.c	5.4 (Berkeley) 10/07/87";
1521559Sdist #endif not lint
1621559Sdist 
176639Smckusick #include <stdio.h>
1821391Smckusick #include <sys/types.h>
1921391Smckusick #include <sys/stat.h>
206639Smckusick /*
216639Smckusick  * grep -- print lines matching (or not matching) a pattern
226639Smckusick  */
236639Smckusick 
2421391Smckusick #define BLKSIZE 8192
256639Smckusick #define	CCHR	2
266639Smckusick #define	CDOT	4
276639Smckusick #define	CCL	6
286639Smckusick #define	NCCL	8
296639Smckusick #define	CDOL	10
306639Smckusick #define	CEOF	11
316639Smckusick 
326639Smckusick #define	CBRC	14
336639Smckusick #define	CLET	15
346639Smckusick #define	STAR	01
356639Smckusick 
366639Smckusick #define	ESIZE	256
376639Smckusick 
386639Smckusick char	expbuf[ESIZE];
396639Smckusick long	lnum;
4021391Smckusick char	linebuf[BUFSIZ+1];
416639Smckusick int	bflag;
426639Smckusick int	nflag;
436639Smckusick int	cflag;
446639Smckusick int	vflag;
456639Smckusick int	nfile;
4632363Sbostic int	hflag;
47*32365Sbostic int	oflag;
486639Smckusick int	iflag;
496639Smckusick int	lflag;
506639Smckusick int	wflag;
516639Smckusick int	sflag;
526639Smckusick int	nsucc;
536639Smckusick int	circf;
546639Smckusick int	blkno;
556639Smckusick long	tln;
5626447Slepreau int	retcode = 0;
576639Smckusick 
586639Smckusick main(argc, argv)
596639Smckusick char **argv;
606639Smckusick {
616639Smckusick 
626639Smckusick 	while (--argc > 0 && (++argv)[0][0]=='-') {
636639Smckusick 		char *cp = argv[0] + 1;
646639Smckusick 		while (*cp) switch (*cp++) {
656639Smckusick 
666639Smckusick 		case 'v':
676639Smckusick 			vflag++;
686639Smckusick 			continue;
696639Smckusick 
706639Smckusick 		case 'b':
716639Smckusick 			bflag++;
726639Smckusick 			continue;
736639Smckusick 
74*32365Sbostic 		case 'o':
75*32365Sbostic 			oflag++;
76*32365Sbostic 			continue;
77*32365Sbostic 
7832363Sbostic 		case 'h':
7932363Sbostic 			hflag++;
8032363Sbostic 			continue;
8132363Sbostic 
826639Smckusick 		case 'i':
836639Smckusick 		case 'y':	/* -y for compatibility with btl grep */
846639Smckusick 			iflag++;
856639Smckusick 			continue;
866639Smckusick 
876639Smckusick 		case 'l':
886639Smckusick 			lflag++;
896639Smckusick 		case 'c':
906639Smckusick 			cflag++;
916639Smckusick 			continue;
926639Smckusick 
936639Smckusick 		case 'w':
946639Smckusick 			wflag++;
956639Smckusick 			continue;
966639Smckusick 
976639Smckusick 		case 's':
986639Smckusick 			sflag++;
996639Smckusick 			continue;
1006639Smckusick 
1016639Smckusick 		case 'n':
1026639Smckusick 			nflag++;
1036639Smckusick 			continue;
1046639Smckusick 
1056639Smckusick 		case 'e':
1066639Smckusick 			--argc;
1076639Smckusick 			++argv;
1086639Smckusick 			goto out;
1096639Smckusick 
1106639Smckusick 		default:
11126447Slepreau 			fprintf(stderr, "grep: unknown flag\n");
1126639Smckusick 			continue;
1136639Smckusick 		}
1146639Smckusick 	}
1156639Smckusick out:
1166639Smckusick 	if (argc<=0)
1176639Smckusick 		exit(2);
1186639Smckusick 	compile(*argv);
1196639Smckusick 	nfile = --argc;
1206639Smckusick 	if (argc<=0) {
1216639Smckusick 		if (lflag)
1226639Smckusick 			exit(1);
1236639Smckusick 		execute(0);
1246639Smckusick 	}
1256639Smckusick 	else while (--argc >= 0) {
1266639Smckusick 		argv++;
1276639Smckusick 		execute(*argv);
1286639Smckusick 	}
12926447Slepreau 	exit(retcode != 0 ? retcode : nsucc == 0);
1306639Smckusick }
1316639Smckusick 
1326639Smckusick compile(astr)
1336639Smckusick char *astr;
1346639Smckusick {
1356639Smckusick 	register c;
1366639Smckusick 	register char *ep, *sp;
1376639Smckusick 	char *lastep;
1386639Smckusick 	int cclcnt;
1396639Smckusick 
1406639Smckusick 	ep = expbuf;
1416639Smckusick 	sp = astr;
1426639Smckusick 	if (*sp == '^') {
1436639Smckusick 		circf++;
1446639Smckusick 		sp++;
1456639Smckusick 	}
1466639Smckusick 	if (wflag)
1476639Smckusick 		*ep++ = CBRC;
1486639Smckusick 	for (;;) {
1496639Smckusick 		if (ep >= &expbuf[ESIZE])
1506639Smckusick 			goto cerror;
1516639Smckusick 		if ((c = *sp++) != '*')
1526639Smckusick 			lastep = ep;
1536639Smckusick 		switch (c) {
1546639Smckusick 
1556639Smckusick 		case '\0':
1566639Smckusick 			if (wflag)
1576639Smckusick 				*ep++ = CLET;
1586639Smckusick 			*ep++ = CEOF;
1596639Smckusick 			return;
1606639Smckusick 
1616639Smckusick 		case '.':
1626639Smckusick 			*ep++ = CDOT;
1636639Smckusick 			continue;
1646639Smckusick 
1656639Smckusick 		case '*':
1666639Smckusick 			if (lastep==0)
1676639Smckusick 				goto defchar;
1686639Smckusick 			*lastep |= STAR;
1696639Smckusick 			continue;
1706639Smckusick 
1716639Smckusick 		case '$':
1726639Smckusick 			if (*sp != '\0')
1736639Smckusick 				goto defchar;
1746639Smckusick 			*ep++ = CDOL;
1756639Smckusick 			continue;
1766639Smckusick 
1776639Smckusick 		case '[':
1786639Smckusick 			*ep++ = CCL;
1796639Smckusick 			*ep++ = 0;
1806639Smckusick 			cclcnt = 1;
1816639Smckusick 			if ((c = *sp++) == '^') {
1826639Smckusick 				c = *sp++;
1836639Smckusick 				ep[-2] = NCCL;
1846639Smckusick 			}
1856639Smckusick 			do {
1866639Smckusick 				*ep++ = c;
1876639Smckusick 				cclcnt++;
1886639Smckusick 				if (c=='\0' || ep >= &expbuf[ESIZE])
1896639Smckusick 					goto cerror;
1906639Smckusick 			} while ((c = *sp++) != ']');
1916639Smckusick 			lastep[1] = cclcnt;
1926639Smckusick 			continue;
1936639Smckusick 
1946639Smckusick 		case '\\':
1956639Smckusick 			if ((c = *sp++) == '\0')
1966639Smckusick 				goto cerror;
1976639Smckusick 			if (c == '<') {
1986639Smckusick 				*ep++ = CBRC;
1996639Smckusick 				continue;
2006639Smckusick 			}
2016639Smckusick 			if (c == '>') {
2026639Smckusick 				*ep++ = CLET;
2036639Smckusick 				continue;
2046639Smckusick 			}
2056639Smckusick 		defchar:
2066639Smckusick 		default:
2076639Smckusick 			*ep++ = CCHR;
2086639Smckusick 			*ep++ = c;
2096639Smckusick 		}
2106639Smckusick 	}
2116639Smckusick     cerror:
21226447Slepreau 	fprintf(stderr, "grep: RE error\n");
21326447Slepreau 	exit(2);
2146639Smckusick }
2156639Smckusick 
2166639Smckusick same(a, b)
2176639Smckusick 	register int a, b;
2186639Smckusick {
2196639Smckusick 
2206639Smckusick 	return (a == b || iflag && (a ^ b) == ' ' && letter(a) == letter(b));
2216639Smckusick }
2226639Smckusick 
2236639Smckusick letter(c)
2246639Smckusick 	register int c;
2256639Smckusick {
2266639Smckusick 
2276639Smckusick 	if (c >= 'a' && c <= 'z')
2286639Smckusick 		return (c);
2296639Smckusick 	if (c >= 'A' && c <= 'Z')
2306639Smckusick 		return (c + 'a' - 'A');
2316639Smckusick 	return (0);
2326639Smckusick }
2336639Smckusick 
2346639Smckusick execute(file)
2356639Smckusick {
2366639Smckusick 	register char *p1, *p2;
2376639Smckusick 	register c;
2386639Smckusick 	int f;
2396639Smckusick 	char *ebp, *cbp;
24021391Smckusick 	static char *buf;
24121391Smckusick 	static int blksize;
24221391Smckusick 	struct stat stb;
2436639Smckusick 
2446639Smckusick 	if (file) {
2456639Smckusick 		if ((f = open(file, 0)) < 0) {
24612090Smckusick 			perror(file);
24726447Slepreau 			retcode = 2;
2486639Smckusick 		}
2496639Smckusick 	} else
2506639Smckusick 		f = 0;
25121391Smckusick 	if (buf == NULL) {
25221391Smckusick 		if (fstat(f, &stb) > 0 && stb.st_blksize > 0)
25321391Smckusick 			blksize = stb.st_blksize;
25421391Smckusick 		else
25521391Smckusick 			blksize = BLKSIZE;
25621391Smckusick 		buf = (char *)malloc(blksize);
25721391Smckusick 		if (buf == NULL) {
25826447Slepreau 			fprintf(stderr, "grep: no memory for %s\n", file);
25926447Slepreau 			retcode = 2;
26021391Smckusick 			return;
26121391Smckusick 		}
26221391Smckusick 	}
26321391Smckusick 	ebp = buf;
26421391Smckusick 	cbp = buf;
2656639Smckusick 	lnum = 0;
2666639Smckusick 	tln = 0;
2676639Smckusick 	blkno = -1;
2686639Smckusick 	for (;;) {
2696639Smckusick 		lnum++;
2706639Smckusick 		if((lnum&0377) == 0)
2716639Smckusick 			fflush(stdout);
2726639Smckusick 		p1 = linebuf;
2736639Smckusick 		p2 = cbp;
2746639Smckusick 		for (;;) {
2756639Smckusick 			if (p2 >= ebp) {
27621391Smckusick 				if ((c = read(f, buf, blksize)) <= 0) {
2776639Smckusick 					close(f);
2786639Smckusick 					if (cflag) {
2796639Smckusick 						if (lflag) {
2806639Smckusick 							if (tln)
2816639Smckusick 							printf("%s\n", file);
2826639Smckusick 						} else {
2836639Smckusick 							if (nfile > 1)
2846639Smckusick 								printf("%s:", file);
2856639Smckusick 							printf("%ld\n", tln);
2866639Smckusick 						}
2876639Smckusick 					}
2886639Smckusick 					return;
2896639Smckusick 				}
2906639Smckusick 				blkno++;
29121391Smckusick 				p2 = buf;
29221391Smckusick 				ebp = buf+c;
2936639Smckusick 			}
2946639Smckusick 			if ((c = *p2++) == '\n')
2956639Smckusick 				break;
2966639Smckusick 			if(c)
29721391Smckusick 			if (p1 < &linebuf[BUFSIZ-1])
2986639Smckusick 				*p1++ = c;
2996639Smckusick 		}
3006639Smckusick 		*p1++ = 0;
3016639Smckusick 		cbp = p2;
3026639Smckusick 		p1 = linebuf;
3036639Smckusick 		p2 = expbuf;
3046639Smckusick 		if (circf) {
3056639Smckusick 			if (advance(p1, p2))
3066639Smckusick 				goto found;
3076639Smckusick 			goto nfound;
3086639Smckusick 		}
3096639Smckusick 		/* fast check for first character */
3106639Smckusick 		if (*p2==CCHR) {
3116639Smckusick 			c = p2[1];
3126639Smckusick 			do {
3136639Smckusick 				if (*p1!=c && (!iflag || (c ^ *p1) != ' '
3146639Smckusick 					|| letter(c) != letter(*p1)))
3156639Smckusick 					continue;
3166639Smckusick 				if (advance(p1, p2))
3176639Smckusick 					goto found;
3186639Smckusick 			} while (*p1++);
3196639Smckusick 			goto nfound;
3206639Smckusick 		}
3216639Smckusick 		/* regular algorithm */
3226639Smckusick 		do {
3236639Smckusick 			if (advance(p1, p2))
3246639Smckusick 				goto found;
3256639Smckusick 		} while (*p1++);
3266639Smckusick 	nfound:
3276639Smckusick 		if (vflag)
3286639Smckusick 			succeed(file);
3296639Smckusick 		continue;
3306639Smckusick 	found:
3316639Smckusick 		if (vflag==0)
3326639Smckusick 			succeed(file);
3336639Smckusick 	}
3346639Smckusick }
3356639Smckusick 
3366639Smckusick advance(alp, aep)
3376639Smckusick 	char *alp, *aep;
3386639Smckusick {
3396639Smckusick 	register char *lp, *ep, *curlp;
3406639Smckusick 	char *nextep;
3416639Smckusick 
3426639Smckusick 	lp = alp;
3436639Smckusick 	ep = aep;
3446639Smckusick 	for (;;) switch (*ep++) {
3456639Smckusick 
3466639Smckusick 	case CCHR:
3476639Smckusick 		if (!same(*ep, *lp))
3486639Smckusick 			return (0);
3496639Smckusick 		ep++, lp++;
3506639Smckusick 		continue;
3516639Smckusick 
3526639Smckusick 	case CDOT:
3536639Smckusick 		if (*lp++)
3546639Smckusick 			continue;
3556639Smckusick 		return(0);
3566639Smckusick 
3576639Smckusick 	case CDOL:
3586639Smckusick 		if (*lp==0)
3596639Smckusick 			continue;
3606639Smckusick 		return(0);
3616639Smckusick 
3626639Smckusick 	case CEOF:
3636639Smckusick 		return(1);
3646639Smckusick 
3656639Smckusick 	case CCL:
3666639Smckusick 		if (cclass(ep, *lp++, 1)) {
3676639Smckusick 			ep += *ep;
3686639Smckusick 			continue;
3696639Smckusick 		}
3706639Smckusick 		return(0);
3716639Smckusick 
3726639Smckusick 	case NCCL:
3736639Smckusick 		if (cclass(ep, *lp++, 0)) {
3746639Smckusick 			ep += *ep;
3756639Smckusick 			continue;
3766639Smckusick 		}
3776639Smckusick 		return(0);
3786639Smckusick 
3796639Smckusick 	case CDOT|STAR:
3806639Smckusick 		curlp = lp;
3816639Smckusick 		while (*lp++);
3826639Smckusick 		goto star;
3836639Smckusick 
3846639Smckusick 	case CCHR|STAR:
3856639Smckusick 		curlp = lp;
3866639Smckusick 		while (same(*lp, *ep))
3876639Smckusick 			lp++;
3886639Smckusick 		lp++;
3896639Smckusick 		ep++;
3906639Smckusick 		goto star;
3916639Smckusick 
3926639Smckusick 	case CCL|STAR:
3936639Smckusick 	case NCCL|STAR:
3946639Smckusick 		curlp = lp;
3956639Smckusick 		while (cclass(ep, *lp++, ep[-1]==(CCL|STAR)));
3966639Smckusick 		ep += *ep;
3976639Smckusick 		goto star;
3986639Smckusick 
3996639Smckusick 	star:
4006639Smckusick 		do {
4016639Smckusick 			lp--;
4026639Smckusick 			if (advance(lp, ep))
4036639Smckusick 				return(1);
4046639Smckusick 		} while (lp > curlp);
4056639Smckusick 		return(0);
4066639Smckusick 
4076639Smckusick 	case CBRC:
4086639Smckusick 		if (lp == expbuf)
4096639Smckusick 			continue;
4106639Smckusick #define	uletter(c)	(letter(c) || c == '_')
4116639Smckusick 		if ( ( uletter(*lp) || digit ( * lp ) )  && !uletter(lp[-1]) && !digit(lp[-1]))
4126639Smckusick 			continue;
4136639Smckusick 		return (0);
4146639Smckusick 
4156639Smckusick 	case CLET:
4166639Smckusick 		if (!uletter(*lp) && !digit(*lp))
4176639Smckusick 			continue;
4186639Smckusick 		return (0);
4196639Smckusick 
4206639Smckusick 	default:
42126447Slepreau 		fprintf(stderr, "grep: RE botch\n");
42226447Slepreau 		exit(2);
4236639Smckusick 	}
4246639Smckusick }
4256639Smckusick 
4266639Smckusick cclass(aset, ac, af)
4276639Smckusick 	char *aset;
4286639Smckusick {
4296639Smckusick 	register char *set, c;
4306639Smckusick 	register n;
4316639Smckusick 
4326639Smckusick 	set = aset;
4336639Smckusick 	if ((c = ac) == 0)
4346639Smckusick 		return(0);
4356639Smckusick 	n = *set++;
4366639Smckusick 	while (--n)
4376639Smckusick 		if (n > 2 && set[1] == '-') {
4386639Smckusick 			if (c >= (set[0] & 0177) && c <= (set[2] & 0177))
4396639Smckusick 				return (af);
4406639Smckusick 			set += 3;
4416639Smckusick 			n -= 2;
4426639Smckusick 		} else
4436639Smckusick 			if ((*set++ & 0177) == c)
4446639Smckusick 				return(af);
4456639Smckusick 	return(!af);
4466639Smckusick }
4476639Smckusick 
4486639Smckusick succeed(f)
4496639Smckusick {
4506639Smckusick 	nsucc = 1;
4516639Smckusick 	if (sflag)
4526639Smckusick 		return;
4536639Smckusick 	if (cflag) {
4546639Smckusick 		tln++;
4556639Smckusick 		return;
4566639Smckusick 	}
457*32365Sbostic 	if (oflag || !hflag && nfile > 1)
4586639Smckusick 		printf("%s:", f);
4596639Smckusick 	if (bflag)
4606639Smckusick 		printf("%d:", blkno);
4616639Smckusick 	if (nflag)
4626639Smckusick 		printf("%ld:", lnum);
4636639Smckusick 	printf("%s\n", linebuf);
4646639Smckusick }
4656639Smckusick 
4666639Smckusick digit(c)
4676639Smckusick 	char c;
4686639Smckusick {
4696639Smckusick 	return (c>='0' && c<='9');
4706639Smckusick }
471