1*6639Smckusick /*	old.ucb.grep.c	4.1	82/05/07	*/
2*6639Smckusick 
3*6639Smckusick #include <stdio.h>
4*6639Smckusick /*
5*6639Smckusick  * grep -- print lines matching (or not matching) a pattern
6*6639Smckusick  */
7*6639Smckusick 
8*6639Smckusick #define	CCHR	2
9*6639Smckusick #define	CDOT	4
10*6639Smckusick #define	CCL	6
11*6639Smckusick #define	NCCL	8
12*6639Smckusick #define	CDOL	10
13*6639Smckusick #define	CEOF	11
14*6639Smckusick 
15*6639Smckusick #define	CBRC	14
16*6639Smckusick #define	CLET	15
17*6639Smckusick #define	STAR	01
18*6639Smckusick 
19*6639Smckusick #define	LBSIZE	BUFSIZ
20*6639Smckusick #define	ESIZE	256
21*6639Smckusick 
22*6639Smckusick char	expbuf[ESIZE];
23*6639Smckusick long	lnum;
24*6639Smckusick char	linebuf[LBSIZE+1];
25*6639Smckusick int	bflag;
26*6639Smckusick int	nflag;
27*6639Smckusick int	cflag;
28*6639Smckusick int	vflag;
29*6639Smckusick int	nfile;
30*6639Smckusick int	iflag;
31*6639Smckusick int	lflag;
32*6639Smckusick int	wflag;
33*6639Smckusick int	sflag;
34*6639Smckusick int	nsucc;
35*6639Smckusick int	circf;
36*6639Smckusick int	blkno;
37*6639Smckusick char	ibuf[BUFSIZ];
38*6639Smckusick long	tln;
39*6639Smckusick 
40*6639Smckusick main(argc, argv)
41*6639Smckusick char **argv;
42*6639Smckusick {
43*6639Smckusick 	char obuf[BUFSIZ];
44*6639Smckusick 
45*6639Smckusick 	setbuf(stdout, obuf);
46*6639Smckusick 	while (--argc > 0 && (++argv)[0][0]=='-') {
47*6639Smckusick 		char *cp = argv[0] + 1;
48*6639Smckusick 		while (*cp) switch (*cp++) {
49*6639Smckusick 
50*6639Smckusick 		case 'v':
51*6639Smckusick 			vflag++;
52*6639Smckusick 			continue;
53*6639Smckusick 
54*6639Smckusick 		case 'b':
55*6639Smckusick 			bflag++;
56*6639Smckusick 			continue;
57*6639Smckusick 
58*6639Smckusick 		case 'i':
59*6639Smckusick 		case 'y':	/* -y for compatibility with btl grep */
60*6639Smckusick 			iflag++;
61*6639Smckusick 			continue;
62*6639Smckusick 
63*6639Smckusick 		case 'l':
64*6639Smckusick 			lflag++;
65*6639Smckusick 		case 'c':
66*6639Smckusick 			cflag++;
67*6639Smckusick 			continue;
68*6639Smckusick 
69*6639Smckusick 		case 'w':
70*6639Smckusick 			wflag++;
71*6639Smckusick 			continue;
72*6639Smckusick 
73*6639Smckusick 		case 's':
74*6639Smckusick 			sflag++;
75*6639Smckusick 			continue;
76*6639Smckusick 
77*6639Smckusick 		case 'n':
78*6639Smckusick 			nflag++;
79*6639Smckusick 			continue;
80*6639Smckusick 
81*6639Smckusick 		case 'e':
82*6639Smckusick 			--argc;
83*6639Smckusick 			++argv;
84*6639Smckusick 			goto out;
85*6639Smckusick 
86*6639Smckusick 		default:
87*6639Smckusick 			fprintf(stderr, "Unknown flag\n");
88*6639Smckusick 			continue;
89*6639Smckusick 		}
90*6639Smckusick 	}
91*6639Smckusick out:
92*6639Smckusick 	if (argc<=0)
93*6639Smckusick 		exit(2);
94*6639Smckusick 	compile(*argv);
95*6639Smckusick 	nfile = --argc;
96*6639Smckusick 	if (argc<=0) {
97*6639Smckusick 		if (lflag)
98*6639Smckusick 			exit(1);
99*6639Smckusick 		execute(0);
100*6639Smckusick 	}
101*6639Smckusick 	else while (--argc >= 0) {
102*6639Smckusick 		argv++;
103*6639Smckusick 		execute(*argv);
104*6639Smckusick 	}
105*6639Smckusick 	exit(nsucc == 0);
106*6639Smckusick }
107*6639Smckusick 
108*6639Smckusick compile(astr)
109*6639Smckusick char *astr;
110*6639Smckusick {
111*6639Smckusick 	register c;
112*6639Smckusick 	register char *ep, *sp;
113*6639Smckusick 	char *lastep;
114*6639Smckusick 	int cclcnt;
115*6639Smckusick 
116*6639Smckusick 	ep = expbuf;
117*6639Smckusick 	sp = astr;
118*6639Smckusick 	if (*sp == '^') {
119*6639Smckusick 		circf++;
120*6639Smckusick 		sp++;
121*6639Smckusick 	}
122*6639Smckusick 	if (wflag)
123*6639Smckusick 		*ep++ = CBRC;
124*6639Smckusick 	for (;;) {
125*6639Smckusick 		if (ep >= &expbuf[ESIZE])
126*6639Smckusick 			goto cerror;
127*6639Smckusick 		if ((c = *sp++) != '*')
128*6639Smckusick 			lastep = ep;
129*6639Smckusick 		switch (c) {
130*6639Smckusick 
131*6639Smckusick 		case '\0':
132*6639Smckusick 			if (wflag)
133*6639Smckusick 				*ep++ = CLET;
134*6639Smckusick 			*ep++ = CEOF;
135*6639Smckusick 			return;
136*6639Smckusick 
137*6639Smckusick 		case '.':
138*6639Smckusick 			*ep++ = CDOT;
139*6639Smckusick 			continue;
140*6639Smckusick 
141*6639Smckusick 		case '*':
142*6639Smckusick 			if (lastep==0)
143*6639Smckusick 				goto defchar;
144*6639Smckusick 			*lastep |= STAR;
145*6639Smckusick 			continue;
146*6639Smckusick 
147*6639Smckusick 		case '$':
148*6639Smckusick 			if (*sp != '\0')
149*6639Smckusick 				goto defchar;
150*6639Smckusick 			*ep++ = CDOL;
151*6639Smckusick 			continue;
152*6639Smckusick 
153*6639Smckusick 		case '[':
154*6639Smckusick 			*ep++ = CCL;
155*6639Smckusick 			*ep++ = 0;
156*6639Smckusick 			cclcnt = 1;
157*6639Smckusick 			if ((c = *sp++) == '^') {
158*6639Smckusick 				c = *sp++;
159*6639Smckusick 				ep[-2] = NCCL;
160*6639Smckusick 			}
161*6639Smckusick 			do {
162*6639Smckusick 				*ep++ = c;
163*6639Smckusick 				cclcnt++;
164*6639Smckusick 				if (c=='\0' || ep >= &expbuf[ESIZE])
165*6639Smckusick 					goto cerror;
166*6639Smckusick 			} while ((c = *sp++) != ']');
167*6639Smckusick 			lastep[1] = cclcnt;
168*6639Smckusick 			continue;
169*6639Smckusick 
170*6639Smckusick 		case '\\':
171*6639Smckusick 			if ((c = *sp++) == '\0')
172*6639Smckusick 				goto cerror;
173*6639Smckusick 			if (c == '<') {
174*6639Smckusick 				*ep++ = CBRC;
175*6639Smckusick 				continue;
176*6639Smckusick 			}
177*6639Smckusick 			if (c == '>') {
178*6639Smckusick 				*ep++ = CLET;
179*6639Smckusick 				continue;
180*6639Smckusick 			}
181*6639Smckusick 		defchar:
182*6639Smckusick 		default:
183*6639Smckusick 			*ep++ = CCHR;
184*6639Smckusick 			*ep++ = c;
185*6639Smckusick 		}
186*6639Smckusick 	}
187*6639Smckusick     cerror:
188*6639Smckusick 	fprintf(stderr, "RE error\n");
189*6639Smckusick }
190*6639Smckusick 
191*6639Smckusick same(a, b)
192*6639Smckusick 	register int a, b;
193*6639Smckusick {
194*6639Smckusick 
195*6639Smckusick 	return (a == b || iflag && (a ^ b) == ' ' && letter(a) == letter(b));
196*6639Smckusick }
197*6639Smckusick 
198*6639Smckusick letter(c)
199*6639Smckusick 	register int c;
200*6639Smckusick {
201*6639Smckusick 
202*6639Smckusick 	if (c >= 'a' && c <= 'z')
203*6639Smckusick 		return (c);
204*6639Smckusick 	if (c >= 'A' && c <= 'Z')
205*6639Smckusick 		return (c + 'a' - 'A');
206*6639Smckusick 	return (0);
207*6639Smckusick }
208*6639Smckusick 
209*6639Smckusick execute(file)
210*6639Smckusick {
211*6639Smckusick 	register char *p1, *p2;
212*6639Smckusick 	register c;
213*6639Smckusick 	int f;
214*6639Smckusick 	char *ebp, *cbp;
215*6639Smckusick 
216*6639Smckusick 	if (file) {
217*6639Smckusick 		if ((f = open(file, 0)) < 0) {
218*6639Smckusick 			fprintf(stderr, "Can't open %s\n", file);
219*6639Smckusick 		}
220*6639Smckusick 	} else
221*6639Smckusick 		f = 0;
222*6639Smckusick 	ebp = ibuf;
223*6639Smckusick 	cbp = ibuf;
224*6639Smckusick 	lnum = 0;
225*6639Smckusick 	tln = 0;
226*6639Smckusick 	blkno = -1;
227*6639Smckusick 	for (;;) {
228*6639Smckusick 		lnum++;
229*6639Smckusick 		if((lnum&0377) == 0)
230*6639Smckusick 			fflush(stdout);
231*6639Smckusick 		p1 = linebuf;
232*6639Smckusick 		p2 = cbp;
233*6639Smckusick 		for (;;) {
234*6639Smckusick 			if (p2 >= ebp) {
235*6639Smckusick 				if ((c = read(f, ibuf, BUFSIZ)) <= 0) {
236*6639Smckusick 					close(f);
237*6639Smckusick 					if (cflag) {
238*6639Smckusick 						if (lflag) {
239*6639Smckusick 							if (tln)
240*6639Smckusick 							printf("%s\n", file);
241*6639Smckusick 						} else {
242*6639Smckusick 							if (nfile > 1)
243*6639Smckusick 								printf("%s:", file);
244*6639Smckusick 							printf("%ld\n", tln);
245*6639Smckusick 						}
246*6639Smckusick 					}
247*6639Smckusick 					return;
248*6639Smckusick 				}
249*6639Smckusick 				blkno++;
250*6639Smckusick 				p2 = ibuf;
251*6639Smckusick 				ebp = ibuf+c;
252*6639Smckusick 			}
253*6639Smckusick 			if ((c = *p2++) == '\n')
254*6639Smckusick 				break;
255*6639Smckusick 			if(c)
256*6639Smckusick 			if (p1 < &linebuf[LBSIZE-1])
257*6639Smckusick 				*p1++ = c;
258*6639Smckusick 		}
259*6639Smckusick 		*p1++ = 0;
260*6639Smckusick 		cbp = p2;
261*6639Smckusick 		p1 = linebuf;
262*6639Smckusick 		p2 = expbuf;
263*6639Smckusick 		if (circf) {
264*6639Smckusick 			if (advance(p1, p2))
265*6639Smckusick 				goto found;
266*6639Smckusick 			goto nfound;
267*6639Smckusick 		}
268*6639Smckusick 		/* fast check for first character */
269*6639Smckusick 		if (*p2==CCHR) {
270*6639Smckusick 			c = p2[1];
271*6639Smckusick 			do {
272*6639Smckusick 				if (*p1!=c && (!iflag || (c ^ *p1) != ' '
273*6639Smckusick 					|| letter(c) != letter(*p1)))
274*6639Smckusick 					continue;
275*6639Smckusick 				if (advance(p1, p2))
276*6639Smckusick 					goto found;
277*6639Smckusick 			} while (*p1++);
278*6639Smckusick 			goto nfound;
279*6639Smckusick 		}
280*6639Smckusick 		/* regular algorithm */
281*6639Smckusick 		do {
282*6639Smckusick 			if (advance(p1, p2))
283*6639Smckusick 				goto found;
284*6639Smckusick 		} while (*p1++);
285*6639Smckusick 	nfound:
286*6639Smckusick 		if (vflag)
287*6639Smckusick 			succeed(file);
288*6639Smckusick 		continue;
289*6639Smckusick 	found:
290*6639Smckusick 		if (vflag==0)
291*6639Smckusick 			succeed(file);
292*6639Smckusick 	}
293*6639Smckusick }
294*6639Smckusick 
295*6639Smckusick advance(alp, aep)
296*6639Smckusick 	char *alp, *aep;
297*6639Smckusick {
298*6639Smckusick 	register char *lp, *ep, *curlp;
299*6639Smckusick 	char *nextep;
300*6639Smckusick 
301*6639Smckusick 	lp = alp;
302*6639Smckusick 	ep = aep;
303*6639Smckusick 	for (;;) switch (*ep++) {
304*6639Smckusick 
305*6639Smckusick 	case CCHR:
306*6639Smckusick 		if (!same(*ep, *lp))
307*6639Smckusick 			return (0);
308*6639Smckusick 		ep++, lp++;
309*6639Smckusick 		continue;
310*6639Smckusick 
311*6639Smckusick 	case CDOT:
312*6639Smckusick 		if (*lp++)
313*6639Smckusick 			continue;
314*6639Smckusick 		return(0);
315*6639Smckusick 
316*6639Smckusick 	case CDOL:
317*6639Smckusick 		if (*lp==0)
318*6639Smckusick 			continue;
319*6639Smckusick 		return(0);
320*6639Smckusick 
321*6639Smckusick 	case CEOF:
322*6639Smckusick 		return(1);
323*6639Smckusick 
324*6639Smckusick 	case CCL:
325*6639Smckusick 		if (cclass(ep, *lp++, 1)) {
326*6639Smckusick 			ep += *ep;
327*6639Smckusick 			continue;
328*6639Smckusick 		}
329*6639Smckusick 		return(0);
330*6639Smckusick 
331*6639Smckusick 	case NCCL:
332*6639Smckusick 		if (cclass(ep, *lp++, 0)) {
333*6639Smckusick 			ep += *ep;
334*6639Smckusick 			continue;
335*6639Smckusick 		}
336*6639Smckusick 		return(0);
337*6639Smckusick 
338*6639Smckusick 	case CDOT|STAR:
339*6639Smckusick 		curlp = lp;
340*6639Smckusick 		while (*lp++);
341*6639Smckusick 		goto star;
342*6639Smckusick 
343*6639Smckusick 	case CCHR|STAR:
344*6639Smckusick 		curlp = lp;
345*6639Smckusick 		while (same(*lp, *ep))
346*6639Smckusick 			lp++;
347*6639Smckusick 		lp++;
348*6639Smckusick 		ep++;
349*6639Smckusick 		goto star;
350*6639Smckusick 
351*6639Smckusick 	case CCL|STAR:
352*6639Smckusick 	case NCCL|STAR:
353*6639Smckusick 		curlp = lp;
354*6639Smckusick 		while (cclass(ep, *lp++, ep[-1]==(CCL|STAR)));
355*6639Smckusick 		ep += *ep;
356*6639Smckusick 		goto star;
357*6639Smckusick 
358*6639Smckusick 	star:
359*6639Smckusick 		do {
360*6639Smckusick 			lp--;
361*6639Smckusick 			if (advance(lp, ep))
362*6639Smckusick 				return(1);
363*6639Smckusick 		} while (lp > curlp);
364*6639Smckusick 		return(0);
365*6639Smckusick 
366*6639Smckusick 	case CBRC:
367*6639Smckusick 		if (lp == expbuf)
368*6639Smckusick 			continue;
369*6639Smckusick #define	uletter(c)	(letter(c) || c == '_')
370*6639Smckusick 		if ( ( uletter(*lp) || digit ( * lp ) )  && !uletter(lp[-1]) && !digit(lp[-1]))
371*6639Smckusick 			continue;
372*6639Smckusick 		return (0);
373*6639Smckusick 
374*6639Smckusick 	case CLET:
375*6639Smckusick 		if (!uletter(*lp) && !digit(*lp))
376*6639Smckusick 			continue;
377*6639Smckusick 		return (0);
378*6639Smckusick 
379*6639Smckusick 	default:
380*6639Smckusick 		fprintf(stderr, "RE botch\n");
381*6639Smckusick 	}
382*6639Smckusick }
383*6639Smckusick 
384*6639Smckusick cclass(aset, ac, af)
385*6639Smckusick 	char *aset;
386*6639Smckusick {
387*6639Smckusick 	register char *set, c;
388*6639Smckusick 	register n;
389*6639Smckusick 
390*6639Smckusick 	set = aset;
391*6639Smckusick 	if ((c = ac) == 0)
392*6639Smckusick 		return(0);
393*6639Smckusick 	n = *set++;
394*6639Smckusick 	while (--n)
395*6639Smckusick 		if (n > 2 && set[1] == '-') {
396*6639Smckusick 			if (c >= (set[0] & 0177) && c <= (set[2] & 0177))
397*6639Smckusick 				return (af);
398*6639Smckusick 			set += 3;
399*6639Smckusick 			n -= 2;
400*6639Smckusick 		} else
401*6639Smckusick 			if ((*set++ & 0177) == c)
402*6639Smckusick 				return(af);
403*6639Smckusick 	return(!af);
404*6639Smckusick }
405*6639Smckusick 
406*6639Smckusick succeed(f)
407*6639Smckusick {
408*6639Smckusick 	nsucc = 1;
409*6639Smckusick 	if (sflag)
410*6639Smckusick 		return;
411*6639Smckusick 	if (cflag) {
412*6639Smckusick 		tln++;
413*6639Smckusick 		return;
414*6639Smckusick 	}
415*6639Smckusick 	if (nfile > 1)
416*6639Smckusick 		printf("%s:", f);
417*6639Smckusick 	if (bflag)
418*6639Smckusick 		printf("%d:", blkno);
419*6639Smckusick 	if (nflag)
420*6639Smckusick 		printf("%ld:", lnum);
421*6639Smckusick 	printf("%s\n", linebuf);
422*6639Smckusick }
423*6639Smckusick 
424*6639Smckusick digit(c)
425*6639Smckusick 	char c;
426*6639Smckusick {
427*6639Smckusick 	return (c>='0' && c<='9');
428*6639Smckusick }
429