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