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