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