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