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