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