1*6641Smckusick /*	old.bin.grep.c	4.1	82/05/07	*/
2*6641Smckusick 
3*6641Smckusick /*
4*6641Smckusick  * grep -- print lines matching (or not matching) a pattern
5*6641Smckusick  *
6*6641Smckusick  *	status returns:
7*6641Smckusick  *		0 - ok, and some matches
8*6641Smckusick  *		1 - ok, but no matches
9*6641Smckusick  *		2 - some error
10*6641Smckusick  */
11*6641Smckusick 
12*6641Smckusick #include <stdio.h>
13*6641Smckusick #include <ctype.h>
14*6641Smckusick 
15*6641Smckusick #define	CBRA	1
16*6641Smckusick #define	CCHR	2
17*6641Smckusick #define	CDOT	4
18*6641Smckusick #define	CCL	6
19*6641Smckusick #define	NCCL	8
20*6641Smckusick #define	CDOL	10
21*6641Smckusick #define	CEOF	11
22*6641Smckusick #define	CKET	12
23*6641Smckusick #define	CBACK	18
24*6641Smckusick 
25*6641Smckusick #define	STAR	01
26*6641Smckusick 
27*6641Smckusick #define	LBSIZE	BUFSIZ
28*6641Smckusick #define	ESIZE	256
29*6641Smckusick #define	NBRA	9
30*6641Smckusick 
31*6641Smckusick char	expbuf[ESIZE];
32*6641Smckusick long	lnum;
33*6641Smckusick char	linebuf[LBSIZE+1];
34*6641Smckusick char	ybuf[ESIZE];
35*6641Smckusick int	bflag;
36*6641Smckusick int	lflag;
37*6641Smckusick int	nflag;
38*6641Smckusick int	cflag;
39*6641Smckusick int	vflag;
40*6641Smckusick int	nfile;
41*6641Smckusick int	hflag	= 1;
42*6641Smckusick int	sflag;
43*6641Smckusick int	yflag;
44*6641Smckusick int	circf;
45*6641Smckusick int	blkno;
46*6641Smckusick long	tln;
47*6641Smckusick int	nsucc;
48*6641Smckusick char	*braslist[NBRA];
49*6641Smckusick char	*braelist[NBRA];
50*6641Smckusick char	bittab[] = {
51*6641Smckusick 	1,
52*6641Smckusick 	2,
53*6641Smckusick 	4,
54*6641Smckusick 	8,
55*6641Smckusick 	16,
56*6641Smckusick 	32,
57*6641Smckusick 	64,
58*6641Smckusick 	128
59*6641Smckusick };
60*6641Smckusick 
61*6641Smckusick main(argc, argv)
62*6641Smckusick char **argv;
63*6641Smckusick {
64*6641Smckusick 	extern char _sobuf[];
65*6641Smckusick 	setbuf(stdout, _sobuf);
66*6641Smckusick 	while (--argc > 0 && (++argv)[0][0]=='-')
67*6641Smckusick 		switch (argv[0][1]) {
68*6641Smckusick 
69*6641Smckusick 		case 'y':
70*6641Smckusick 			yflag++;
71*6641Smckusick 			continue;
72*6641Smckusick 
73*6641Smckusick 		case 'h':
74*6641Smckusick 			hflag = 0;
75*6641Smckusick 			continue;
76*6641Smckusick 
77*6641Smckusick 		case 's':
78*6641Smckusick 			sflag++;
79*6641Smckusick 			continue;
80*6641Smckusick 
81*6641Smckusick 		case 'v':
82*6641Smckusick 			vflag++;
83*6641Smckusick 			continue;
84*6641Smckusick 
85*6641Smckusick 		case 'b':
86*6641Smckusick 			bflag++;
87*6641Smckusick 			continue;
88*6641Smckusick 
89*6641Smckusick 		case 'l':
90*6641Smckusick 			lflag++;
91*6641Smckusick 			continue;
92*6641Smckusick 
93*6641Smckusick 		case 'c':
94*6641Smckusick 			cflag++;
95*6641Smckusick 			continue;
96*6641Smckusick 
97*6641Smckusick 		case 'n':
98*6641Smckusick 			nflag++;
99*6641Smckusick 			continue;
100*6641Smckusick 
101*6641Smckusick 		case 'e':
102*6641Smckusick 			--argc;
103*6641Smckusick 			++argv;
104*6641Smckusick 			goto out;
105*6641Smckusick 
106*6641Smckusick 		default:
107*6641Smckusick 			errexit("grep: unknown flag\n", (char *)NULL);
108*6641Smckusick 			continue;
109*6641Smckusick 		}
110*6641Smckusick out:
111*6641Smckusick 	if (argc<=0)
112*6641Smckusick 		exit(2);
113*6641Smckusick 	if (yflag) {
114*6641Smckusick 		register char *p, *s;
115*6641Smckusick 		for (s = ybuf, p = *argv; *p; ) {
116*6641Smckusick 			if (*p == '\\') {
117*6641Smckusick 				*s++ = *p++;
118*6641Smckusick 				if (*p)
119*6641Smckusick 					*s++ = *p++;
120*6641Smckusick 			} else if (*p == '[') {
121*6641Smckusick 				while (*p != '\0' && *p != ']')
122*6641Smckusick 					*s++ = *p++;
123*6641Smckusick 			} else if (islower(*p)) {
124*6641Smckusick 				*s++ = '[';
125*6641Smckusick 				*s++ = toupper(*p);
126*6641Smckusick 				*s++ = *p++;
127*6641Smckusick 				*s++ = ']';
128*6641Smckusick 			} else
129*6641Smckusick 				*s++ = *p++;
130*6641Smckusick 			if (s >= ybuf+ESIZE-5)
131*6641Smckusick 				errexit("grep: argument too long\n", (char *)NULL);
132*6641Smckusick 		}
133*6641Smckusick 		*s = '\0';
134*6641Smckusick 		*argv = ybuf;
135*6641Smckusick 	}
136*6641Smckusick 	compile(*argv);
137*6641Smckusick 	nfile = --argc;
138*6641Smckusick 	if (argc<=0) {
139*6641Smckusick 		if (lflag)
140*6641Smckusick 			exit(1);
141*6641Smckusick 		execute((char *)NULL);
142*6641Smckusick 	} else while (--argc >= 0) {
143*6641Smckusick 		argv++;
144*6641Smckusick 		execute(*argv);
145*6641Smckusick 	}
146*6641Smckusick 	exit(nsucc == 0);
147*6641Smckusick }
148*6641Smckusick 
149*6641Smckusick compile(astr)
150*6641Smckusick char *astr;
151*6641Smckusick {
152*6641Smckusick 	register c;
153*6641Smckusick 	register char *ep, *sp;
154*6641Smckusick 	char *cstart;
155*6641Smckusick 	char *lastep;
156*6641Smckusick 	int cclcnt;
157*6641Smckusick 	char bracket[NBRA], *bracketp;
158*6641Smckusick 	int closed;
159*6641Smckusick 	char numbra;
160*6641Smckusick 	char neg;
161*6641Smckusick 
162*6641Smckusick 	ep = expbuf;
163*6641Smckusick 	sp = astr;
164*6641Smckusick 	lastep = 0;
165*6641Smckusick 	bracketp = bracket;
166*6641Smckusick 	closed = numbra = 0;
167*6641Smckusick 	if (*sp == '^') {
168*6641Smckusick 		circf++;
169*6641Smckusick 		sp++;
170*6641Smckusick 	}
171*6641Smckusick 	for (;;) {
172*6641Smckusick 		if (ep >= &expbuf[ESIZE])
173*6641Smckusick 			goto cerror;
174*6641Smckusick 		if ((c = *sp++) != '*')
175*6641Smckusick 			lastep = ep;
176*6641Smckusick 		switch (c) {
177*6641Smckusick 
178*6641Smckusick 		case '\0':
179*6641Smckusick 			*ep++ = CEOF;
180*6641Smckusick 			return;
181*6641Smckusick 
182*6641Smckusick 		case '.':
183*6641Smckusick 			*ep++ = CDOT;
184*6641Smckusick 			continue;
185*6641Smckusick 
186*6641Smckusick 		case '*':
187*6641Smckusick 			if (lastep==0 || *lastep==CBRA || *lastep==CKET)
188*6641Smckusick 				goto defchar;
189*6641Smckusick 			*lastep |= STAR;
190*6641Smckusick 			continue;
191*6641Smckusick 
192*6641Smckusick 		case '$':
193*6641Smckusick 			if (*sp != '\0')
194*6641Smckusick 				goto defchar;
195*6641Smckusick 			*ep++ = CDOL;
196*6641Smckusick 			continue;
197*6641Smckusick 
198*6641Smckusick 		case '[':
199*6641Smckusick 			if(&ep[17] >= &expbuf[ESIZE])
200*6641Smckusick 				goto cerror;
201*6641Smckusick 			*ep++ = CCL;
202*6641Smckusick 			neg = 0;
203*6641Smckusick 			if((c = *sp++) == '^') {
204*6641Smckusick 				neg = 1;
205*6641Smckusick 				c = *sp++;
206*6641Smckusick 			}
207*6641Smckusick 			cstart = sp;
208*6641Smckusick 			do {
209*6641Smckusick 				if (c=='\0')
210*6641Smckusick 					goto cerror;
211*6641Smckusick 				if (c=='-' && sp>cstart && *sp!=']') {
212*6641Smckusick 					for (c = sp[-2]; c<*sp; c++)
213*6641Smckusick 						ep[c>>3] |= bittab[c&07];
214*6641Smckusick 					sp++;
215*6641Smckusick 				}
216*6641Smckusick 				ep[c>>3] |= bittab[c&07];
217*6641Smckusick 			} while((c = *sp++) != ']');
218*6641Smckusick 			if(neg) {
219*6641Smckusick 				for(cclcnt = 0; cclcnt < 16; cclcnt++)
220*6641Smckusick 					ep[cclcnt] ^= -1;
221*6641Smckusick 				ep[0] &= 0376;
222*6641Smckusick 			}
223*6641Smckusick 
224*6641Smckusick 			ep += 16;
225*6641Smckusick 
226*6641Smckusick 			continue;
227*6641Smckusick 
228*6641Smckusick 		case '\\':
229*6641Smckusick 			if((c = *sp++) == '(') {
230*6641Smckusick 				if(numbra >= NBRA) {
231*6641Smckusick 					goto cerror;
232*6641Smckusick 				}
233*6641Smckusick 				*bracketp++ = numbra;
234*6641Smckusick 				*ep++ = CBRA;
235*6641Smckusick 				*ep++ = numbra++;
236*6641Smckusick 				continue;
237*6641Smckusick 			}
238*6641Smckusick 			if(c == ')') {
239*6641Smckusick 				if(bracketp <= bracket) {
240*6641Smckusick 					goto cerror;
241*6641Smckusick 				}
242*6641Smckusick 				*ep++ = CKET;
243*6641Smckusick 				*ep++ = *--bracketp;
244*6641Smckusick 				closed++;
245*6641Smckusick 				continue;
246*6641Smckusick 			}
247*6641Smckusick 
248*6641Smckusick 			if(c >= '1' && c <= '9') {
249*6641Smckusick 				if((c -= '1') >= closed)
250*6641Smckusick 					goto cerror;
251*6641Smckusick 				*ep++ = CBACK;
252*6641Smckusick 				*ep++ = c;
253*6641Smckusick 				continue;
254*6641Smckusick 			}
255*6641Smckusick 
256*6641Smckusick 		defchar:
257*6641Smckusick 		default:
258*6641Smckusick 			*ep++ = CCHR;
259*6641Smckusick 			*ep++ = c;
260*6641Smckusick 		}
261*6641Smckusick 	}
262*6641Smckusick     cerror:
263*6641Smckusick 	errexit("grep: RE error\n", (char *)NULL);
264*6641Smckusick }
265*6641Smckusick 
266*6641Smckusick execute(file)
267*6641Smckusick char *file;
268*6641Smckusick {
269*6641Smckusick 	register char *p1, *p2;
270*6641Smckusick 	register c;
271*6641Smckusick 
272*6641Smckusick 	if (file) {
273*6641Smckusick 		if (freopen(file, "r", stdin) == NULL)
274*6641Smckusick 			errexit("grep: can't open %s\n", file);
275*6641Smckusick 	}
276*6641Smckusick 	lnum = 0;
277*6641Smckusick 	tln = 0;
278*6641Smckusick 	for (;;) {
279*6641Smckusick 		lnum++;
280*6641Smckusick 		p1 = linebuf;
281*6641Smckusick 		while ((c = getchar()) != '\n') {
282*6641Smckusick 			if (c == EOF) {
283*6641Smckusick 				if (cflag) {
284*6641Smckusick 					if (nfile>1)
285*6641Smckusick 						printf("%s:", file);
286*6641Smckusick 					printf("%D\n", tln);
287*6641Smckusick 					fflush(stdout);
288*6641Smckusick 				}
289*6641Smckusick 				return;
290*6641Smckusick 			}
291*6641Smckusick 			*p1++ = c;
292*6641Smckusick 			if (p1 >= &linebuf[LBSIZE-1])
293*6641Smckusick 				break;
294*6641Smckusick 		}
295*6641Smckusick 		*p1++ = '\0';
296*6641Smckusick 		p1 = linebuf;
297*6641Smckusick 		p2 = expbuf;
298*6641Smckusick 		if (circf) {
299*6641Smckusick 			if (advance(p1, p2))
300*6641Smckusick 				goto found;
301*6641Smckusick 			goto nfound;
302*6641Smckusick 		}
303*6641Smckusick 		/* fast check for first character */
304*6641Smckusick 		if (*p2==CCHR) {
305*6641Smckusick 			c = p2[1];
306*6641Smckusick 			do {
307*6641Smckusick 				if (*p1!=c)
308*6641Smckusick 					continue;
309*6641Smckusick 				if (advance(p1, p2))
310*6641Smckusick 					goto found;
311*6641Smckusick 			} while (*p1++);
312*6641Smckusick 			goto nfound;
313*6641Smckusick 		}
314*6641Smckusick 		/* regular algorithm */
315*6641Smckusick 		do {
316*6641Smckusick 			if (advance(p1, p2))
317*6641Smckusick 				goto found;
318*6641Smckusick 		} while (*p1++);
319*6641Smckusick 	nfound:
320*6641Smckusick 		if (vflag)
321*6641Smckusick 			succeed(file);
322*6641Smckusick 		continue;
323*6641Smckusick 	found:
324*6641Smckusick 		if (vflag==0)
325*6641Smckusick 			succeed(file);
326*6641Smckusick 	}
327*6641Smckusick }
328*6641Smckusick 
329*6641Smckusick advance(lp, ep)
330*6641Smckusick register char *lp, *ep;
331*6641Smckusick {
332*6641Smckusick 	register char *curlp;
333*6641Smckusick 	char c;
334*6641Smckusick 	char *bbeg;
335*6641Smckusick 	int ct;
336*6641Smckusick 
337*6641Smckusick 	for (;;) switch (*ep++) {
338*6641Smckusick 
339*6641Smckusick 	case CCHR:
340*6641Smckusick 		if (*ep++ == *lp++)
341*6641Smckusick 			continue;
342*6641Smckusick 		return(0);
343*6641Smckusick 
344*6641Smckusick 	case CDOT:
345*6641Smckusick 		if (*lp++)
346*6641Smckusick 			continue;
347*6641Smckusick 		return(0);
348*6641Smckusick 
349*6641Smckusick 	case CDOL:
350*6641Smckusick 		if (*lp==0)
351*6641Smckusick 			continue;
352*6641Smckusick 		return(0);
353*6641Smckusick 
354*6641Smckusick 	case CEOF:
355*6641Smckusick 		return(1);
356*6641Smckusick 
357*6641Smckusick 	case CCL:
358*6641Smckusick 		c = *lp++ & 0177;
359*6641Smckusick 		if(ep[c>>3] & bittab[c & 07]) {
360*6641Smckusick 			ep += 16;
361*6641Smckusick 			continue;
362*6641Smckusick 		}
363*6641Smckusick 		return(0);
364*6641Smckusick 	case CBRA:
365*6641Smckusick 		braslist[*ep++] = lp;
366*6641Smckusick 		continue;
367*6641Smckusick 
368*6641Smckusick 	case CKET:
369*6641Smckusick 		braelist[*ep++] = lp;
370*6641Smckusick 		continue;
371*6641Smckusick 
372*6641Smckusick 	case CBACK:
373*6641Smckusick 		bbeg = braslist[*ep];
374*6641Smckusick 		if (braelist[*ep]==0)
375*6641Smckusick 			return(0);
376*6641Smckusick 		ct = braelist[*ep++] - bbeg;
377*6641Smckusick 		if(ecmp(bbeg, lp, ct)) {
378*6641Smckusick 			lp += ct;
379*6641Smckusick 			continue;
380*6641Smckusick 		}
381*6641Smckusick 		return(0);
382*6641Smckusick 
383*6641Smckusick 	case CBACK|STAR:
384*6641Smckusick 		bbeg = braslist[*ep];
385*6641Smckusick 		if (braelist[*ep]==0)
386*6641Smckusick 			return(0);
387*6641Smckusick 		ct = braelist[*ep++] - bbeg;
388*6641Smckusick 		curlp = lp;
389*6641Smckusick 		while(ecmp(bbeg, lp, ct))
390*6641Smckusick 			lp += ct;
391*6641Smckusick 		while(lp >= curlp) {
392*6641Smckusick 			if(advance(lp, ep))	return(1);
393*6641Smckusick 			lp -= ct;
394*6641Smckusick 		}
395*6641Smckusick 		return(0);
396*6641Smckusick 
397*6641Smckusick 
398*6641Smckusick 	case CDOT|STAR:
399*6641Smckusick 		curlp = lp;
400*6641Smckusick 		while (*lp++);
401*6641Smckusick 		goto star;
402*6641Smckusick 
403*6641Smckusick 	case CCHR|STAR:
404*6641Smckusick 		curlp = lp;
405*6641Smckusick 		while (*lp++ == *ep);
406*6641Smckusick 		ep++;
407*6641Smckusick 		goto star;
408*6641Smckusick 
409*6641Smckusick 	case CCL|STAR:
410*6641Smckusick 		curlp = lp;
411*6641Smckusick 		do {
412*6641Smckusick 			c = *lp++ & 0177;
413*6641Smckusick 		} while(ep[c>>3] & bittab[c & 07]);
414*6641Smckusick 		ep += 16;
415*6641Smckusick 		goto star;
416*6641Smckusick 
417*6641Smckusick 	star:
418*6641Smckusick 		if(--lp == curlp) {
419*6641Smckusick 			continue;
420*6641Smckusick 		}
421*6641Smckusick 
422*6641Smckusick 		if(*ep == CCHR) {
423*6641Smckusick 			c = ep[1];
424*6641Smckusick 			do {
425*6641Smckusick 				if(*lp != c)
426*6641Smckusick 					continue;
427*6641Smckusick 				if(advance(lp, ep))
428*6641Smckusick 					return(1);
429*6641Smckusick 			} while(lp-- > curlp);
430*6641Smckusick 			return(0);
431*6641Smckusick 		}
432*6641Smckusick 
433*6641Smckusick 		do {
434*6641Smckusick 			if (advance(lp, ep))
435*6641Smckusick 				return(1);
436*6641Smckusick 		} while (lp-- > curlp);
437*6641Smckusick 		return(0);
438*6641Smckusick 
439*6641Smckusick 	default:
440*6641Smckusick 		errexit("grep RE botch\n", (char *)NULL);
441*6641Smckusick 	}
442*6641Smckusick }
443*6641Smckusick 
444*6641Smckusick succeed(f)
445*6641Smckusick char *f;
446*6641Smckusick {
447*6641Smckusick 	nsucc = 1;
448*6641Smckusick 	if (sflag)
449*6641Smckusick 		return;
450*6641Smckusick 	if (cflag) {
451*6641Smckusick 		tln++;
452*6641Smckusick 		return;
453*6641Smckusick 	}
454*6641Smckusick 	if (lflag) {
455*6641Smckusick 		printf("%s\n", f);
456*6641Smckusick 		fflush(stdout);
457*6641Smckusick 		fseek(stdin, 0l, 2);
458*6641Smckusick 		return;
459*6641Smckusick 	}
460*6641Smckusick 	if (nfile > 1 && hflag)
461*6641Smckusick 		printf("%s:", f);
462*6641Smckusick 	if (bflag)
463*6641Smckusick 		printf("%u:", blkno);
464*6641Smckusick 	if (nflag)
465*6641Smckusick 		printf("%ld:", lnum);
466*6641Smckusick 	printf("%s\n", linebuf);
467*6641Smckusick 	fflush(stdout);
468*6641Smckusick }
469*6641Smckusick 
470*6641Smckusick ecmp(a, b, count)
471*6641Smckusick char	*a, *b;
472*6641Smckusick {
473*6641Smckusick 	register cc = count;
474*6641Smckusick 	while(cc--)
475*6641Smckusick 		if(*a++ != *b++)	return(0);
476*6641Smckusick 	return(1);
477*6641Smckusick }
478*6641Smckusick 
479*6641Smckusick errexit(s, f)
480*6641Smckusick char *s, *f;
481*6641Smckusick {
482*6641Smckusick 	fprintf(stderr, s, f);
483*6641Smckusick 	exit(2);
484*6641Smckusick }
485