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