+/*
+ * 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 <stdio.h>
+
+#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;
+ }
+}