|
|
1.1 root 1: /*
2: * egrep -- print lines containing (or not containing) a regular expression
3: *
4: * status returns:
5: * 0 - ok, and some matches
6: * 1 - ok, but no matches
7: * 2 - some error; matches irrelevant
8: */
9: %token CHAR DOT CCL NCCL OR CAT STAR PLUS QUEST
10: %left OR
11: %left CHAR DOT CCL NCCL '('
12: %left CAT
13: %left STAR PLUS QUEST
14:
15: %{
16: #include <stdio.h>
17: #include <ctype.h>
18:
19: #define BLKSIZE 512 /* size of reported disk blocks */
20: #define MAXLIN 1000
21: #define MAXPOS 10000
22: #define NCHARS 128
23: #define NSTATES 128
24: #define FINAL -1
25: #define LEFT '\177' /* serves as ^ */
26: #define RIGHT '\n' /* serves as record separator and as $ */
27: char gotofn[NSTATES][NCHARS];
28: int state[NSTATES];
29: char out[NSTATES];
30: int line = 1;
31: int name[MAXLIN];
32: int left[MAXLIN];
33: int right[MAXLIN];
34: int parent[MAXLIN];
35: int foll[MAXLIN];
36: int positions[MAXPOS];
37: char chars[MAXLIN];
38: int nxtpos = 0;
39: int inxtpos;
40: int nxtchar = 0;
41: int tmpstat[MAXLIN];
42: int initstat[MAXLIN];
43: int istat;
44: int nstate = 1;
45: int xstate;
46: int count;
47: int icount;
48: char *input;
49:
50: char reinit = 0;
51:
52: long lnum;
53: int bflag;
54: int cflag;
55: int fflag;
56: int lflag;
57: int nflag;
58: int hflag = 1;
59: int iflag;
60: int sflag;
61: int vflag;
62: int nfile;
63: long blkno;
64: long tln;
65: int nsucc;
66: int badbotch;
67:
68: int f;
69: FILE *expfile;
70: %}
71:
72: %%
73: s: t
74: ={ unary(FINAL, $1);
75: line--;
76: }
77: ;
78: t: b r
79: ={ $$ = node(CAT, $1, $2); }
80: | OR b r OR
81: ={ $$ = node(CAT, $2, $3); }
82: | OR b r
83: ={ $$ = node(CAT, $2, $3); }
84: | b r OR
85: ={ $$ = node(CAT, $1, $2); }
86: ;
87: b:
88: ={ $$ = enter(DOT);
89: $$ = unary(STAR, $$); }
90: ;
91: r: CHAR
92: ={ $$ = enter($1); }
93: | DOT
94: ={ $$ = enter(DOT); }
95: | CCL
96: ={ $$ = cclenter(CCL); }
97: | NCCL
98: ={ $$ = cclenter(NCCL); }
99: ;
100:
101: r: r OR r
102: ={ $$ = node(OR, $1, $3); }
103: | r r %prec CAT
104: ={ $$ = node(CAT, $1, $2); }
105: | r STAR
106: ={ $$ = unary(STAR, $1); }
107: | r PLUS
108: ={ $$ = unary(PLUS, $1); }
109: | r QUEST
110: ={ $$ = unary(QUEST, $1); }
111: | '(' r ')'
112: ={ $$ = $2; }
113: | error
114: ;
115:
116: %%
117: yyerror(s) {
118: fprintf(stderr, "egrep: %s\n", s);
119: exit(2);
120: }
121:
122: yylex() {
123: extern int yylval;
124: int cclcnt, x;
125: register char c, d;
126: switch(c = nextch()) {
127: case '^': c = LEFT;
128: goto defchar;
129: case '$': c = RIGHT;
130: goto defchar;
131: case '|': return (OR);
132: case '*': return (STAR);
133: case '+': return (PLUS);
134: case '?': return (QUEST);
135: case '(': return (c);
136: case ')': return (c);
137: case '.': return (DOT);
138: case '\0': return (0);
139: case RIGHT: return (OR);
140: case '[':
141: x = CCL;
142: cclcnt = 0;
143: count = nxtchar++;
144: if ((c = nextch()) == '^') {
145: x = NCCL;
146: c = nextch();
147: }
148: do {
149: if (c == '\0') synerror();
150: if (c == '-' && cclcnt > 0 && chars[nxtchar-1] != 0) {
151: if ((d = nextch()) != 0) {
152: c = chars[nxtchar-1];
153: while (c < d) {
154: if (nxtchar >= MAXLIN) overflo();
155: chars[nxtchar++] = ++c;
156: cclcnt++;
157: }
158: continue;
159: }
160: }
161: if (nxtchar >= MAXLIN) overflo();
162: chars[nxtchar++] = c;
163: cclcnt++;
164: } while ((c = nextch()) != ']');
165: chars[count] = cclcnt;
166: return (x);
167: case '\\':
168: if ((c = nextch()) == '\0') synerror();
169: defchar:
170: default: yylval = c; return (CHAR);
171: }
172: }
173: nextch() {
174: register char c;
175: if (fflag) {
176: if ((c = getc(expfile)) == EOF) return(0);
177: }
178: else c = *input++;
179: return(iflag? tolower(c): c);
180: }
181:
182: synerror() {
183: fprintf(stderr, "egrep: syntax error\n");
184: exit(2);
185: }
186:
187: enter(x) int x; {
188: if(line >= MAXLIN) overflo();
189: name[line] = x;
190: left[line] = 0;
191: right[line] = 0;
192: return(line++);
193: }
194:
195: cclenter(x) int x; {
196: register linno;
197: linno = enter(x);
198: right[linno] = count;
199: return (linno);
200: }
201:
202: node(x, l, r) {
203: if(line >= MAXLIN) overflo();
204: name[line] = x;
205: left[line] = l;
206: right[line] = r;
207: parent[l] = line;
208: parent[r] = line;
209: return(line++);
210: }
211:
212: unary(x, d) {
213: if(line >= MAXLIN) overflo();
214: name[line] = x;
215: left[line] = d;
216: right[line] = 0;
217: parent[d] = line;
218: return(line++);
219: }
220: overflo() {
221: fprintf(stderr, "egrep: regular expression too long\n");
222: exit(2);
223: }
224:
225: cfoll(v) {
226: register i;
227: if (left[v] == 0) {
228: count = 0;
229: for (i=1; i<=line; i++) tmpstat[i] = 0;
230: follow(v);
231: add(foll, v);
232: }
233: else if (right[v] == 0) cfoll(left[v]);
234: else {
235: cfoll(left[v]);
236: cfoll(right[v]);
237: }
238: }
239: cgotofn() {
240: register i;
241: count = 0;
242: inxtpos = nxtpos;
243: for (i=3; i<=line; i++) tmpstat[i] = 0;
244: if (cstate(line-1)==0) {
245: tmpstat[line] = 1;
246: count++;
247: out[1] = 1;
248: }
249: for (i=3; i<=line; i++) initstat[i] = tmpstat[i];
250: count--; /*leave out position 1 */
251: icount = count;
252: tmpstat[1] = 0;
253: add(state, 1);
254: istat = nxtst(1,LEFT);
255: }
256:
257: nxtst(s,c)
258: char c;
259: {
260: register i, num, k;
261: int pos, curpos, number, newpos;
262: num = positions[state[s]];
263: count = icount;
264: for (i=3; i<=line; i++) tmpstat[i] = initstat[i];
265: pos = state[s] + 1;
266: for (i=0; i<num; i++) {
267: curpos = positions[pos];
268: if ((k = name[curpos]) >= 0)
269: if (
270: (k == c)
271: | (k == DOT && c != LEFT && c != RIGHT)
272: | (k == CCL && member(c, right[curpos], 1))
273: | (k == NCCL && member(c, right[curpos], 0) && c != LEFT && c != RIGHT)
274: ) {
275: number = positions[foll[curpos]];
276: newpos = foll[curpos] + 1;
277: for (k=0; k<number; k++) {
278: if (tmpstat[positions[newpos]] != 1) {
279: tmpstat[positions[newpos]] = 1;
280: count++;
281: }
282: newpos++;
283: }
284: }
285: pos++;
286: }
287: if (notin(nstate)) {
288: if (++nstate >= NSTATES) {
289: for (i=1; i<NSTATES; i++)
290: out[i] = 0;
291: for (i=1; i<NSTATES; i++)
292: for (k=0; k<NCHARS; k++)
293: gotofn[i][k] = 0;
294: nstate = 1;
295: nxtpos = inxtpos;
296: reinit = 1;
297: add(state, nstate);
298: if (tmpstat[line] == 1) out[nstate] = 1;
299: return nstate;
300: }
301: add(state, nstate);
302: if (tmpstat[line] == 1) out[nstate] = 1;
303: gotofn[s][c] = nstate;
304: return nstate;
305: }
306: else {
307: gotofn[s][c] = xstate;
308: return xstate;
309: }
310: }
311:
312:
313: cstate(v) {
314: register b;
315: if (left[v] == 0) {
316: if (tmpstat[v] != 1) {
317: tmpstat[v] = 1;
318: count++;
319: }
320: return(1);
321: }
322: else if (right[v] == 0) {
323: if (cstate(left[v]) == 0) return (0);
324: else if (name[v] == PLUS) return (1);
325: else return (0);
326: }
327: else if (name[v] == CAT) {
328: if (cstate(left[v]) == 0 && cstate(right[v]) == 0) return (0);
329: else return (1);
330: }
331: else { /* name[v] == OR */
332: b = cstate(right[v]);
333: if (cstate(left[v]) == 0 || b == 0) return (0);
334: else return (1);
335: }
336: }
337:
338:
339: member(symb, set, torf) {
340: register i, num, pos;
341: num = chars[set];
342: pos = set + 1;
343: for (i=0; i<num; i++)
344: if (symb == chars[pos++]) return (torf);
345: return (!torf);
346: }
347:
348: notin(n) {
349: register i, j, pos;
350: for (i=1; i<=n; i++) {
351: if (positions[state[i]] == count) {
352: pos = state[i] + 1;
353: for (j=0; j < count; j++)
354: if (tmpstat[positions[pos++]] != 1) goto nxt;
355: xstate = i;
356: return (0);
357: }
358: nxt: ;
359: }
360: return (1);
361: }
362:
363: add(array, n) int *array; {
364: register i;
365: if (nxtpos + count >= MAXPOS) overflo();
366: array[n] = nxtpos;
367: positions[nxtpos++] = count;
368: for (i=3; i <= line; i++) {
369: if (tmpstat[i] == 1) {
370: positions[nxtpos++] = i;
371: }
372: }
373: }
374:
375: follow(v) int v; {
376: int p;
377: if (v == line) return;
378: p = parent[v];
379: switch(name[p]) {
380: case STAR:
381: case PLUS: cstate(v);
382: follow(p);
383: return;
384:
385: case OR:
386: case QUEST: follow(p);
387: return;
388:
389: case CAT: if (v == left[p]) {
390: if (cstate(right[p]) == 0) {
391: follow(p);
392: return;
393: }
394: }
395: else follow(p);
396: return;
397: case FINAL: if (tmpstat[line] != 1) {
398: tmpstat[line] = 1;
399: count++;
400: }
401: return;
402: }
403: }
404:
405:
406: main(argc, argv)
407: char **argv;
408: {
409: while (--argc > 0 && (++argv)[0][0]=='-')
410: switch (argv[0][1]) {
411:
412: case 's':
413: sflag++;
414: continue;
415:
416: case 'h':
417: hflag = 0;
418: continue;
419:
420: case 'i':
421: iflag++;
422: continue;
423:
424: case 'b':
425: bflag++;
426: continue;
427:
428: case 'c':
429: cflag++;
430: continue;
431:
432: case 'e':
433: argc--;
434: argv++;
435: goto cut;
436:
437: case 'f':
438: fflag++;
439: continue;
440:
441: case 'l':
442: lflag++;
443: continue;
444:
445: case 'n':
446: nflag++;
447: continue;
448:
449: case 'v':
450: vflag++;
451: continue;
452:
453: default:
454: fprintf(stderr, "egrep: unknown flag\n");
455: continue;
456: }
457: cut:
458: if (argc<=0)
459: exit(2);
460: if (fflag) {
461: if ((expfile = fopen(*argv, "r")) == NULL) {
462: fprintf(stderr, "egrep: can't open %s\n", *argv);
463: exit(2);
464: }
465: }
466: else input = *argv;
467: argc--;
468: argv++;
469:
470: yyparse();
471:
472: cfoll(line-1);
473: cgotofn();
474: nfile = argc;
475: if (argc<=0) {
476: if (lflag) exit(1);
477: execute(0);
478: }
479: else while (--argc >= 0) {
480: execute(*argv);
481: argv++;
482: }
483: exit(badbotch ? 2 : nsucc==0);
484: }
485:
486: execute(file)
487: char *file;
488: {
489: register char *p;
490: register cstat;
491: register c;
492: register t;
493: int ccount;
494: char buf[2*BUFSIZ];
495: char *nlp;
496: if (file) {
497: if ((f = open(file, 0)) < 0) {
498: fprintf(stderr, "egrep: can't open %s\n", file);
499: badbotch=1;
500: return;
501: }
502: }
503: else f = 0;
504: ccount = 0;
505: lnum = 1;
506: tln = 0;
507: p = buf;
508: nlp = p;
509: if ((ccount = read(f,p,BUFSIZ))<=0) goto done;
510: blkno = ccount;
511: cstat = istat;
512: if (out[cstat]) goto found;
513: for (;;) {
514: c = *p&0377;
515: if(iflag && c>='A' && c<='Z')
516: c += 'a'-'A';
517: if ((t = gotofn[cstat][c]) == 0)
518: cstat = nxtst(cstat,c);
519: else
520: cstat = t;
521: if (out[cstat]) {
522: found: for(;;) {
523: if (*p++ == RIGHT) {
524: if (vflag == 0) {
525: succeed: nsucc = 1;
526: if (cflag) tln++;
527: else if (sflag)
528: ; /* ugh */
529: else if (lflag) {
530: printf("%s\n", file);
531: close(f);
532: return;
533: }
534: else {
535: if (nfile > 1 && hflag) printf("%s:", file);
536: if (bflag) printf("%ld:", (blkno-ccount-1)/BLKSIZE);
537: if (nflag) printf("%ld:", lnum);
538: if (p <= nlp) {
539: while (nlp < &buf[2*BUFSIZ]) putchar(*nlp++);
540: nlp = buf;
541: }
542: while (nlp < p) putchar(*nlp++);
543: }
544: }
545: lnum++;
546: nlp = p;
547: if (reinit == 1) {
548: clearg();
549: }
550: if ((out[(cstat=istat)]) == 0) goto brk2;
551: }
552: cfound:
553: if (--ccount <= 0) {
554: if (p <= &buf[BUFSIZ]) {
555: if ((ccount = read(f, p, BUFSIZ)) <= 0) goto done;
556: }
557: else if (p == &buf[2*BUFSIZ]) {
558: p = buf;
559: if ((ccount = read(f, p, BUFSIZ)) <= 0) goto done;
560: }
561: else {
562: if ((ccount = read(f, p, &buf[2*BUFSIZ]-p)) <= 0) goto done;
563: }
564: if(nlp>p && nlp<=p+ccount)
565: nlp = p+ccount;
566: blkno += ccount;
567: }
568: }
569: }
570: if (*p++ == RIGHT) {
571: if (vflag) goto succeed;
572: else {
573: lnum++;
574: nlp = p;
575: if (reinit == 1) {
576: clearg();
577: }
578: if (out[(cstat=istat)]) goto cfound;
579: }
580: }
581: brk2:
582: if (--ccount <= 0) {
583: if (p <= &buf[BUFSIZ]) {
584: if ((ccount = read(f, p, BUFSIZ)) <= 0) break;
585: }
586: else if (p == &buf[2*BUFSIZ]) {
587: p = buf;
588: if ((ccount = read(f, p, BUFSIZ)) <= 0) break;
589: }
590: else {
591: if ((ccount = read(f, p, &buf[2*BUFSIZ] - p)) <= 0) break;
592: }
593: if(nlp>p && nlp<=p+ccount)
594: nlp = p+ccount;
595: blkno += ccount;
596: }
597: }
598: done: close(f);
599: if (cflag) {
600: if (nfile > 1)
601: printf("%s:", file);
602: printf("%ld\n", tln);
603: }
604: }
605:
606: clearg() {
607: register i, k;
608: for (i=1; i<NSTATES; i++)
609: out[i] = 0;
610: for (i=1; i<NSTATES; i++)
611: for (k=0; k<NCHARS; k++)
612: gotofn[i][k] = 0;
613: nstate = 1;
614: nxtpos = inxtpos;
615: reinit = 1;
616: count = 0;
617: for (i=3; i<=line; i++) tmpstat[i] = 0;
618: if (cstate(line-1)==0) {
619: tmpstat[line] = 1;
620: count++;
621: out[1] = 1;
622: }
623: for (i=3; i<=line; i++) initstat[i] = tmpstat[i];
624: count--; /*leave out position 1 */
625: icount = count;
626: tmpstat[1] = 0;
627: add(state, 1);
628: istat = nxtst(1,LEFT);
629: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.