/* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #pragma ident "%Z%%M% %I% %E% SMI" #include #include /* * 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 */ #define MAXSIZ 700 #define QSIZE 400 struct words { char inp; char out; struct words *nst; struct words *link; struct words *fail; } *www, *smax, *q; char buf[2*BUFSIZ]; int nsucc; int need; char *instr; int inct; int rflag; int xargc; char **xargv; int numwords; int nfound; static int flag = 0; extern void err(); extern void *zalloc(); static void cfail(void); static void cgotofn(void); static void execute(void); static char gch(void); static int new(struct words *x); static void overflo(void); int fgrep(int argc, char **argv) { nsucc = need = inct = rflag = numwords = nfound = 0; instr = 0; flag = 0; if (www == 0) www = (struct words *)zalloc(MAXSIZ, sizeof (*www)); if (www == NULL) err(gettext("Can't get space for machines"), 0); for (q = www; q < www+MAXSIZ; q++) { q->inp = 0; q->out = 0; q->nst = 0; q->link = 0; q->fail = 0; } xargc = argc-1; xargv = argv+1; while (xargc > 0 && xargv[0][0] == '-') { switch (xargv[0][1]) { case 'r': /* return value only */ rflag++; break; case 'n': /* number of answers needed */ need = (int)xargv[1]; xargv++; xargc--; break; case 'i': instr = xargv[1]; inct = (int)xargv[2]+2; #if D2 fprintf(stderr, "inct %d xargv.2. %o %d\n", inct, xargv[2], xargv[2]); #endif xargv += 2; xargc -= 2; break; } xargv++; xargc--; } if (xargc <= 0) { write(2, "bad fgrep call\n", 15); exit(2); } #if D1 fprintf(stderr, "before cgoto\n"); #endif cgotofn(); #if D1 fprintf(stderr, "before cfail\n"); #endif cfail(); #if D1 fprintf(stderr, "before execute instr %.20s\n", instr? instr: ""); fprintf(stderr, "end of string %d %c %c %c\n", inct, instr ? instr[inct-3] : '\0', instr ? instr[inct-2] : '\0', instr ? instr[inct-1] : '\0'); #endif execute(); #if D1 fprintf(stderr, "returning nsucc %d\n", nsucc); fprintf(stderr, "fgrep done www %o\n", www); #endif return (nsucc == 0); } static void execute(void) { char *p; struct words *c; char ch; int ccount; int f; char *nlp; f = 0; ccount = instr ? inct : 0; nfound = 0; p = instr ? instr : buf; if (need == 0) need = numwords; nlp = p; c = www; #if D2 fprintf(stderr, "in execute ccount %d inct %d\n", ccount, inct); #endif for (;;) { #if D3 fprintf(stderr, "down ccount\n"); #endif if (--ccount <= 0) { #if D2 fprintf(stderr, "ex loop ccount %d instr %o\n", ccount, instr); #endif if (instr) break; if (p == &buf[2*BUFSIZ]) p = buf; if (p > &buf[BUFSIZ]) { if ((ccount = read(f, p, &buf[2*BUFSIZ] - p)) <= 0) break; } else if ((ccount = read(f, p, BUFSIZ)) <= 0) break; #if D2 fprintf(stderr, " normal read %d bytres\n", ccount); { char xx[20]; sprintf(xx, "they are %%.%ds\n", ccount); fprintf(stderr, xx, p); } #endif } nstate: ch = *p; #if D2 fprintf(stderr, "roaming along in ex ch %c c %o\n", ch, c); #endif if (isupper(ch)) ch |= 040; if (c->inp == ch) { c = c->nst; } else if (c->link != 0) { c = c->link; goto nstate; } else { c = c->fail; if (c == 0) { c = www; istate: if (c->inp == ch) { c = c->nst; } else if (c->link != 0) { c = c->link; goto istate; } } else goto nstate; } if (c->out && new(c)) { #if D2 fprintf(stderr, " found: nfound %d need %d\n", nfound, need); #endif if (++nfound >= need) { #if D1 fprintf(stderr, "found, p %o nlp %o ccount %d buf %o buf[2*BUFSIZ] %o\n", p, nlp, ccount, buf, buf+2*BUFSIZ); #endif if (instr == 0) while (*p++ != '\n') { #if D3 fprintf(stderr, "down ccount2\n"); #endif if (--ccount <= 0) { if (p == &buf[2*BUFSIZ]) p = buf; if (p > &buf[BUFSIZ]) { if ((ccount = read(f, p, &buf[2*BUFSIZ] - p)) <= 0) break; } else if ((ccount = read(f, p, BUFSIZ)) <= 0) break; #if D2 fprintf(stderr, " read %d bytes\n", ccount); { char xx[20]; sprintf(xx, "they are %%.%ds\n", ccount); fprintf(stderr, xx, p); } #endif } } nsucc = 1; if (rflag == 0) { #if D2 fprintf(stderr, "p %o nlp %o buf %o\n", p, nlp, buf); if (p > nlp) {write(2, "XX\n", 3); write(2, nlp, p-nlp); write(2, "XX\n", 3); } #endif if (p > nlp) write(1, nlp, p-nlp); else { write(1, nlp, &buf[2*BUFSIZ] - nlp); write(1, buf, p-&buf[0]); } if (p[-1] != '\n') write(1, "\n", 1); } if (instr == 0) { nlp = p; c = www; nfound = 0; } } else ccount++; continue; } #if D2 fprintf(stderr, "nr end loop p %o\n", p); #endif if (instr) p++; else if (*p++ == '\n') { nlp = p; c = www; nfound = 0; } } if (instr == 0) close(f); } static void cgotofn(void) { char c; struct words *s; s = smax = www; nword: for (;;) { #if D1 fprintf(stderr, " in for loop c now %o %c\n", c, c > ' ' ? c : ' '); #endif if ((c = gch()) == 0) return; else if (c == '\n') { s->out = 1; s = www; } else { loop: if (s->inp == c) { s = s->nst; continue; } if (s->inp == 0) goto enter; if (s->link == 0) { if (smax >= &www[MAXSIZ - 1]) overflo(); s->link = ++smax; s = smax; goto enter; } s = s->link; goto loop; } } enter: do { s->inp = c; if (smax >= &www[MAXSIZ - 1]) overflo(); s->nst = ++smax; s = smax; } while ((c = gch()) != '\n') ; smax->out = 1; s = www; numwords++; goto nword; } static char gch(void) { static char *s; if (flag == 0) { flag = 1; s = *xargv++; #if D1 fprintf(stderr, "next arg is %s xargc %d\n", xargc > 0 ? s : "", xargc); #endif if (xargc-- <= 0) return (0); } if (*s) return (*s++); for (flag = 0; flag < 2*BUFSIZ; flag++) buf[flag] = 0; flag = 0; return ('\n'); } static void overflo(void) { write(2, "wordlist too large\n", 19); exit(2); } static void cfail(void) { struct words *queue[QSIZE]; struct words **front, **rear; struct words *state; char c; struct words *s; s = www; 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 = www; 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; } } static struct words *seen[50]; static int new(struct words *x) { int i; for (i = 0; i < nfound; i++) if (seen[i] == x) return (0); seen[i] = x; return (1); }