|
|
1.1 root 1: static char *sccsid = "@(#)fgrep.c 4.1 (Berkeley) 10/1/80";
2: /*
3: * fgrep -- print all lines containing any of a set of keywords
4: *
5: * status returns:
6: * 0 - ok, and some matches
7: * 1 - ok, but no matches
8: * 2 - some error
9: */
10: /*#define DOSTATS /* define this to gather stats */
11: #ifdef DOSTATS
12: char *statsexpr, *statspat;
13: long nlines, nbytes, nfail, ntrans0;
14: char statsflags[1024], *statsfptr = statsflags;
15: dostats();
16: #endif
17:
18: #include "stdio.h"
19: # include "ctype.h"
20:
21: #define MAXSIZ 6000
22: #define QSIZE 400
23: struct words {
24: char inp;
25: char out;
26: struct words *nst;
27: struct words *link;
28: struct words *fail;
29: } w[MAXSIZ], *smax, *q;
30:
31: long lnum;
32: int bflag, cflag, fflag, lflag, nflag, vflag, xflag, iflag;
33: int hflag = 1;
34: int sflag;
35: int retcode = 0;
36: int nfile;
37: long blkno;
38: int nsucc;
39: long tln;
40: FILE *wordf;
41: char *argptr;
42:
43: /*
44: * preserve the interactive feel with stdio
45: */
46: #define Read(f, b, s) (fflush(stdout), read(f, b, s))
47:
48: main(argc, argv)
49: char **argv;
50: {
51: while (--argc > 0 && (++argv)[0][0]=='-'){
52: #ifdef DOSTATS
53: *statsfptr++ = argv[0][1];
54: #endif
55: switch (argv[0][1]) {
56:
57: case 's':
58: sflag++;
59: continue;
60:
61: case 'h':
62: hflag = 0;
63: continue;
64:
65: case 'b':
66: bflag++;
67: continue;
68:
69: case 'c':
70: cflag++;
71: continue;
72:
73: case 'e':
74: argc--;
75: argv++;
76: goto out;
77:
78: case 'f':
79: fflag++;
80: continue;
81:
82: case 'l':
83: lflag++;
84: continue;
85:
86: case 'n':
87: nflag++;
88: continue;
89:
90: case 'v':
91: vflag++;
92: continue;
93:
94: case 'x':
95: xflag++;
96: continue;
97:
98: case 'i':
99: iflag++;
100: continue;
101: default:
102: fprintf(stderr, "fgrep: unknown flag\n");
103: continue;
104: }
105: }
106: out:
107: if (argc<=0)
108: exit(2);
109: if (fflag) {
110: wordf = fopen(*argv, "r");
111: if (wordf==NULL) {
112: fprintf(stderr, "fgrep: can't open %s\n", *argv);
113: exit(2);
114: }
115: }
116: else argptr = *argv;
117: argc--;
118: argv++;
119:
120: #ifdef DOSTATS
121: statsexpr = statspat = (char *)malloc(MAXSIZ);
122: onexit(dostats);
123: #endif
124: cgotofn();
125: cfail();
126: nfile = argc;
127: if (argc<=0) {
128: if (lflag) exit(1);
129: execute((char *)NULL);
130: }
131: else while (--argc >= 0) {
132: execute(*argv);
133: argv++;
134: }
135: exit(retcode != 0 ? retcode : nsucc == 0);
136: }
137:
138: # define ccomp(a,b) (iflag ? lca(a)==lca(b) : a==b)
139: # define lca(x) (isupper(x) ? ((x)+'a'-'A') : x)
140: execute(file)
141: char *file;
142: {
143: register struct words *c;
144: register ccount;
145: register char ch;
146: register char *p;
147: char buf[2*BUFSIZ];
148: int f;
149: int failed;
150: char *nlp;
151: if (file) {
152: if ((f = open(file, 0)) < 0) {
153: fprintf(stderr, "fgrep: can't open %s\n", file);
154: retcode = 2;
155: return;
156: }
157: }
158: else f = 0;
159: ccount = 0;
160: failed = 0;
161: lnum = 1;
162: tln = 0;
163: blkno = 0;
164: p = buf;
165: nlp = p;
166: c = w;
167: for (;;) {
168: if (--ccount <= 0) {
169: if (p == &buf[2*BUFSIZ]) p = buf;
170: if (p > &buf[BUFSIZ]) {
171: if ((ccount = Read(f, p, &buf[2*BUFSIZ] - p)) <= 0) break;
172: }
173: else if ((ccount = Read(f, p, BUFSIZ)) <= 0) break;
174: blkno += ccount;
175: }
176: nstate:
177: if (ccomp(c->inp, *p)) {
178: #ifdef DOSTATS
179: if(c == w) ntrans0++;
180: #endif
181: c = c->nst;
182: }
183: else if (c->link != 0) {
184: c = c->link;
185: goto nstate;
186: }
187: else {
188: #ifdef DOSTATS
189: nfail++;
190: #endif
191: c = c->fail;
192: failed = 1;
193: if (c==0) {
194: c = w;
195: istate:
196: if (ccomp(c->inp , *p)) {
197: c = c->nst;
198: }
199: else if (c->link != 0) {
200: c = c->link;
201: goto istate;
202: }
203: }
204: else goto nstate;
205: }
206: if (c->out) {
207: while (*p++ != '\n') {
208: if (--ccount <= 0) {
209: if (p == &buf[2*BUFSIZ]) p = buf;
210: if (p > &buf[BUFSIZ]) {
211: if ((ccount = Read(f, p, &buf[2*BUFSIZ] - p)) <= 0) break;
212: }
213: else if ((ccount = Read(f, p, BUFSIZ)) <= 0) break;
214: blkno += ccount;
215: }
216: }
217: if ( (vflag && (failed == 0 || xflag == 0)) || (vflag == 0 && xflag && failed) )
218: goto nomatch;
219: succeed: nsucc = 1;
220: if (cflag) tln++;
221: else if (sflag)
222: ; /* ugh */
223: else if (lflag) {
224: printf("%s\n", file);
225: close(f);
226: return;
227: }
228: else {
229: if (nfile > 1 && hflag) printf("%s:", file);
230: if (bflag) printf("%ld:", (blkno-ccount-1)/1024);
231: if (nflag) printf("%ld:", lnum);
232: if (p <= nlp) {
233: while (nlp < &buf[2*BUFSIZ]) putchar(*nlp++);
234: nlp = buf;
235: }
236: while (nlp < p) putchar(*nlp++);
237: }
238: nomatch: lnum++;
239: nlp = p;
240: c = w;
241: failed = 0;
242: continue;
243: }
244: if (*p++ == '\n')
245: if (vflag) goto succeed;
246: else {
247: lnum++;
248: nlp = p;
249: c = w;
250: failed = 0;
251: }
252: }
253: close(f);
254: if (cflag) {
255: if (nfile > 1)
256: printf("%s:", file);
257: printf("%ld\n", tln);
258: }
259: #ifdef DOSTATS
260: nbytes += blkno;
261: nlines += lnum-1;
262: #endif
263: }
264:
265: static int mailfd = -1;
266:
267: getargc()
268: {
269: register c;
270: if (wordf)
271: c = getc(wordf);
272: else if ((c = *argptr++) == '\0')
273: c = EOF;
274: #ifdef DOSTATS
275: if(c != EOF) *statsexpr++ = c;
276: #endif
277: return(c);
278: }
279:
280: cgotofn() {
281: register c;
282: register struct words *s;
283:
284: s = smax = w;
285: nword: for(;;) {
286: c = getargc();
287: if (c==EOF)
288: return;
289: if (c == '\n') {
290: if (xflag) {
291: for(;;) {
292: if (s->inp == c) {
293: s = s->nst;
294: break;
295: }
296: if (s->inp == 0) goto nenter;
297: if (s->link == 0) {
298: if (smax >= &w[MAXSIZ -1]) overflo();
299: s->link = ++smax;
300: s = smax;
301: goto nenter;
302: }
303: s = s->link;
304: }
305: }
306: s->out = 1;
307: s = w;
308: } else {
309: loop: if (s->inp == c) {
310: s = s->nst;
311: continue;
312: }
313: if (s->inp == 0) goto enter;
314: if (s->link == 0) {
315: if (smax >= &w[MAXSIZ - 1]) overflo();
316: s->link = ++smax;
317: s = smax;
318: goto enter;
319: }
320: s = s->link;
321: goto loop;
322: }
323: }
324:
325: enter:
326: do {
327: s->inp = c;
328: if (smax >= &w[MAXSIZ - 1]) overflo();
329: s->nst = ++smax;
330: s = smax;
331: } while ((c = getargc()) != '\n' && c!=EOF);
332: if (xflag) {
333: nenter: s->inp = '\n';
334: if (smax >= &w[MAXSIZ -1]) overflo();
335: s->nst = ++smax;
336: }
337: smax->out = 1;
338: s = w;
339: if (c != EOF)
340: goto nword;
341: }
342:
343: overflo() {
344: fprintf(stderr, "wordlist too large\n");
345: exit(2);
346: }
347: cfail() {
348: struct words *queue[QSIZE];
349: struct words **front, **rear;
350: struct words *state;
351: register char c;
352: register struct words *s;
353: s = w;
354: front = rear = queue;
355: init: if ((s->inp) != 0) {
356: *rear++ = s->nst;
357: if (rear >= &queue[QSIZE - 1]) overflo();
358: }
359: if ((s = s->link) != 0) {
360: goto init;
361: }
362:
363: while (rear!=front) {
364: s = *front; /* s is next state in queue */
365: if (front == &queue[QSIZE-1])
366: front = queue;
367: else front++;
368: cloop: if ((c = s->inp) != 0) { /* g(s,c) != 0 */
369: *rear = (q = s->nst); /* add q = g(s,c) to queue */
370: if (front < rear)
371: if (rear >= &queue[QSIZE-1])
372: if (front == queue) overflo();
373: else rear = queue;
374: else rear++;
375: else
376: if (++rear == front) overflo();
377: state = s->fail; /* state = f(s) */
378: floop: if (state == 0)
379: state = w;
380: if (state->inp == c)
381: do { /* f(q) = g(state,c) for all q links */
382: q->fail = state->nst;
383: if ((state->nst)->out == 1) q->out = 1;
384: } while ((q = q->link) != 0);
385: else if (state->link != 0) {
386: state = state->link;
387: goto floop;
388: }
389: else if ((state = state->fail) != 0)
390: goto floop; /* state = f(state) */
391: }
392: if ((s = s->link) != 0)
393: goto cloop;
394: }
395: }
396:
397: #ifdef DOSTATS
398: #include <errno.h>
399: #define NAME "/tmp/grepdata"
400: dostats()
401: {
402: umask(0);
403: mailfd = open(NAME, 1);
404: if((mailfd < 0) && (errno != ECONC)){
405: umask(0);
406: mailfd = creat(NAME, 03666);
407: }
408: if(mailfd >= 0){
409: Finit(mailfd, (char *)0);
410: Fseek(mailfd, 0L, 2);
411: *statsexpr = 0;
412: *statsfptr = 0;
413: Fprint(mailfd, "\321fgrep:%s:%d:%d:%d:%d: %s\n", statsflags, nlines, nbytes, ntrans0, nfail, statspat);
414: }
415: Fflush(mailfd);
416: }
417: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.