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