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