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