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