/* * fgrep -- print all lines containing any of a set of keywords * * status returns: * 0 - ok, and some matches * 1 - ok, but no matches * 2 - some error */ #include #define MAXSIZ 6000 #define QSIZE 400 struct words { char inp; char out; struct words *nst; struct words *link; struct words *fail; } w[MAXSIZ], *smax, *q; long lnum; int bflag, cflag, fflag, lflag, nflag, vflag, xflag; int hflag = 1; int sflag; int nfile; long blkno; int nsucc; long tln; FILE *wordf; char *argptr; main(argc, argv) char **argv; { while (--argc > 0 && (++argv)[0][0]=='-') switch (argv[0][1]) { case 's': sflag++; continue; case 'h': hflag = 0; continue; case 'b': bflag++; continue; case 'c': cflag++; continue; case 'e': argc--; argv++; goto out; case 'f': fflag++; continue; case 'l': lflag++; continue; case 'n': nflag++; continue; case 'v': vflag++; continue; case 'x': xflag++; continue; default: fprintf(stderr, "egrep: unknown flag\n"); continue; } out: if (argc<=0) exit(2); if (fflag) { wordf = fopen(*argv, "r"); if (wordf==NULL) { fprintf(stderr, "egrep: can't open %s\n", *argv); exit(2); } } else argptr = *argv; argc--; argv++; cgotofn(); cfail(); nfile = argc; if (argc<=0) { if (lflag) exit(1); execute((char *)NULL); } else while (--argc >= 0) { execute(*argv); argv++; } exit(nsucc == 0); } execute(file) char *file; { register char *p; register struct words *c; register ccount; char buf[1024]; int f; int failed; char *nlp; if (file) { if ((f = open(file, 0)) < 0) { fprintf(stderr, "fgrep: can't open %s\n", file); exit(2); } } else f = 0; ccount = 0; failed = 0; lnum = 1; tln = 0; blkno = 0; p = buf; nlp = p; c = w; for (;;) { if (--ccount <= 0) { if (p == &buf[1024]) p = buf; if (p > &buf[512]) { if ((ccount = read(f, p, &buf[1024] - p)) <= 0) break; } else if ((ccount = read(f, p, 512)) <= 0) break; blkno += ccount; } nstate: if (c->inp == *p) { c = c->nst; } else if (c->link != 0) { c = c->link; goto nstate; } else { c = c->fail; failed = 1; if (c==0) { c = w; istate: if (c->inp == *p) { c = c->nst; } else if (c->link != 0) { c = c->link; goto istate; } } else goto nstate; } if (c->out) { while (*p++ != '\n') { if (--ccount <= 0) { if (p == &buf[1024]) p = buf; if (p > &buf[512]) { if ((ccount = read(f, p, &buf[1024] - p)) <= 0) break; } else if ((ccount = read(f, p, 512)) <= 0) break; blkno += ccount; } } if ( (vflag && (failed == 0 || xflag == 0)) || (vflag == 0 && xflag && failed) ) goto nomatch; succeed: nsucc = 1; if (cflag) tln++; else if (sflag) ; /* ugh */ else if (lflag) { printf("%s\n", file); close(f); return; } else { if (nfile > 1 && hflag) printf("%s:", file); if (bflag) printf("%ld:", (blkno-ccount-1)/512); if (nflag) printf("%ld:", lnum); if (p <= nlp) { while (nlp < &buf[1024]) putchar(*nlp++); nlp = buf; } while (nlp < p) putchar(*nlp++); } nomatch: lnum++; nlp = p; c = w; failed = 0; continue; } if (*p++ == '\n') if (vflag) goto succeed; else { lnum++; nlp = p; c = w; failed = 0; } } close(f); if (cflag) { if (nfile > 1) printf("%s:", file); printf("%ld\n", tln); } } getargc() { register c; if (wordf) return(getc(wordf)); if ((c = *argptr++) == '\0') return(EOF); return(c); } cgotofn() { register c; register struct words *s; s = smax = w; nword: for(;;) { c = getargc(); if (c==EOF) return; if (c == '\n') { if (xflag) { for(;;) { if (s->inp == c) { s = s->nst; break; } if (s->inp == 0) goto nenter; if (s->link == 0) { if (smax >= &w[MAXSIZ -1]) overflo(); s->link = ++smax; s = smax; goto nenter; } s = s->link; } } s->out = 1; s = w; } else { loop: if (s->inp == c) { s = s->nst; continue; } if (s->inp == 0) goto enter; if (s->link == 0) { if (smax >= &w[MAXSIZ - 1]) overflo(); s->link = ++smax; s = smax; goto enter; } s = s->link; goto loop; } } enter: do { s->inp = c; if (smax >= &w[MAXSIZ - 1]) overflo(); s->nst = ++smax; s = smax; } while ((c = getargc()) != '\n' && c!=EOF); if (xflag) { nenter: s->inp = '\n'; if (smax >= &w[MAXSIZ -1]) overflo(); s->nst = ++smax; } smax->out = 1; s = w; if (c != EOF) goto nword; } overflo() { fprintf(stderr, "wordlist too large\n"); exit(2); } cfail() { struct words *queue[QSIZE]; struct words **front, **rear; struct words *state; register char c; register struct words *s; s = w; front = rear = queue; init: if ((s->inp) != 0) { *rear++ = s->nst; if (rear >= &queue[QSIZE - 1]) overflo(); } if ((s = s->link) != 0) { goto init; } while (rear!=front) { s = *front; if (front == &queue[QSIZE-1]) front = queue; else front++; cloop: if ((c = s->inp) != 0) { *rear = (q = s->nst); if (front < rear) if (rear >= &queue[QSIZE-1]) if (front == queue) overflo(); else rear = queue; else rear++; else if (++rear == front) overflo(); state = s->fail; floop: if (state == 0) state = w; if (state->inp == c) { q->fail = state->nst; if ((state->nst)->out == 1) q->out = 1; continue; } else if ((state = state->link) != 0) goto floop; } if ((s = s->link) != 0) goto cloop; } }