Research V7 development
[unix-history] / usr / src / cmd / fgrep.c
CommitLineData
fd2a4d19
AA
1/*
2 * fgrep -- print all lines containing any of a set of keywords
3 *
4 * status returns:
5 * 0 - ok, and some matches
6 * 1 - ok, but no matches
7 * 2 - some error
8 */
9
10#include <stdio.h>
11
12#define MAXSIZ 6000
13#define QSIZE 400
14struct words {
15 char inp;
16 char out;
17 struct words *nst;
18 struct words *link;
19 struct words *fail;
20} w[MAXSIZ], *smax, *q;
21
22long lnum;
23int bflag, cflag, fflag, lflag, nflag, vflag, xflag;
24int hflag = 1;
25int sflag;
26int nfile;
27long blkno;
28int nsucc;
29long tln;
30FILE *wordf;
31char *argptr;
32
33main(argc, argv)
34char **argv;
35{
36 while (--argc > 0 && (++argv)[0][0]=='-')
37 switch (argv[0][1]) {
38
39 case 's':
40 sflag++;
41 continue;
42
43 case 'h':
44 hflag = 0;
45 continue;
46
47 case 'b':
48 bflag++;
49 continue;
50
51 case 'c':
52 cflag++;
53 continue;
54
55 case 'e':
56 argc--;
57 argv++;
58 goto out;
59
60 case 'f':
61 fflag++;
62 continue;
63
64 case 'l':
65 lflag++;
66 continue;
67
68 case 'n':
69 nflag++;
70 continue;
71
72 case 'v':
73 vflag++;
74 continue;
75
76 case 'x':
77 xflag++;
78 continue;
79
80 default:
81 fprintf(stderr, "egrep: unknown flag\n");
82 continue;
83 }
84out:
85 if (argc<=0)
86 exit(2);
87 if (fflag) {
88 wordf = fopen(*argv, "r");
89 if (wordf==NULL) {
90 fprintf(stderr, "egrep: can't open %s\n", *argv);
91 exit(2);
92 }
93 }
94 else argptr = *argv;
95 argc--;
96 argv++;
97
98 cgotofn();
99 cfail();
100 nfile = argc;
101 if (argc<=0) {
102 if (lflag) exit(1);
103 execute((char *)NULL);
104 }
105 else while (--argc >= 0) {
106 execute(*argv);
107 argv++;
108 }
109 exit(nsucc == 0);
110}
111
112execute(file)
113char *file;
114{
115 register char *p;
116 register struct words *c;
117 register ccount;
118 char buf[1024];
119 int f;
120 int failed;
121 char *nlp;
122 if (file) {
123 if ((f = open(file, 0)) < 0) {
124 fprintf(stderr, "fgrep: can't open %s\n", file);
125 exit(2);
126 }
127 }
128 else f = 0;
129 ccount = 0;
130 failed = 0;
131 lnum = 1;
132 tln = 0;
133 blkno = 0;
134 p = buf;
135 nlp = p;
136 c = w;
137 for (;;) {
138 if (--ccount <= 0) {
139 if (p == &buf[1024]) p = buf;
140 if (p > &buf[512]) {
141 if ((ccount = read(f, p, &buf[1024] - p)) <= 0) break;
142 }
143 else if ((ccount = read(f, p, 512)) <= 0) break;
144 blkno += ccount;
145 }
146 nstate:
147 if (c->inp == *p) {
148 c = c->nst;
149 }
150 else if (c->link != 0) {
151 c = c->link;
152 goto nstate;
153 }
154 else {
155 c = c->fail;
156 failed = 1;
157 if (c==0) {
158 c = w;
159 istate:
160 if (c->inp == *p) {
161 c = c->nst;
162 }
163 else if (c->link != 0) {
164 c = c->link;
165 goto istate;
166 }
167 }
168 else goto nstate;
169 }
170 if (c->out) {
171 while (*p++ != '\n') {
172 if (--ccount <= 0) {
173 if (p == &buf[1024]) p = buf;
174 if (p > &buf[512]) {
175 if ((ccount = read(f, p, &buf[1024] - p)) <= 0) break;
176 }
177 else if ((ccount = read(f, p, 512)) <= 0) break;
178 blkno += ccount;
179 }
180 }
181 if ( (vflag && (failed == 0 || xflag == 0)) || (vflag == 0 && xflag && failed) )
182 goto nomatch;
183 succeed: nsucc = 1;
184 if (cflag) tln++;
185 else if (sflag)
186 ; /* ugh */
187 else if (lflag) {
188 printf("%s\n", file);
189 close(f);
190 return;
191 }
192 else {
193 if (nfile > 1 && hflag) printf("%s:", file);
194 if (bflag) printf("%ld:", (blkno-ccount-1)/512);
195 if (nflag) printf("%ld:", lnum);
196 if (p <= nlp) {
197 while (nlp < &buf[1024]) putchar(*nlp++);
198 nlp = buf;
199 }
200 while (nlp < p) putchar(*nlp++);
201 }
202 nomatch: lnum++;
203 nlp = p;
204 c = w;
205 failed = 0;
206 continue;
207 }
208 if (*p++ == '\n')
209 if (vflag) goto succeed;
210 else {
211 lnum++;
212 nlp = p;
213 c = w;
214 failed = 0;
215 }
216 }
217 close(f);
218 if (cflag) {
219 if (nfile > 1)
220 printf("%s:", file);
221 printf("%ld\n", tln);
222 }
223}
224
225getargc()
226{
227 register c;
228 if (wordf)
229 return(getc(wordf));
230 if ((c = *argptr++) == '\0')
231 return(EOF);
232 return(c);
233}
234
235cgotofn() {
236 register c;
237 register struct words *s;
238
239 s = smax = w;
240nword: for(;;) {
241 c = getargc();
242 if (c==EOF)
243 return;
244 if (c == '\n') {
245 if (xflag) {
246 for(;;) {
247 if (s->inp == c) {
248 s = s->nst;
249 break;
250 }
251 if (s->inp == 0) goto nenter;
252 if (s->link == 0) {
253 if (smax >= &w[MAXSIZ -1]) overflo();
254 s->link = ++smax;
255 s = smax;
256 goto nenter;
257 }
258 s = s->link;
259 }
260 }
261 s->out = 1;
262 s = w;
263 } else {
264 loop: if (s->inp == c) {
265 s = s->nst;
266 continue;
267 }
268 if (s->inp == 0) goto enter;
269 if (s->link == 0) {
270 if (smax >= &w[MAXSIZ - 1]) overflo();
271 s->link = ++smax;
272 s = smax;
273 goto enter;
274 }
275 s = s->link;
276 goto loop;
277 }
278 }
279
280 enter:
281 do {
282 s->inp = c;
283 if (smax >= &w[MAXSIZ - 1]) overflo();
284 s->nst = ++smax;
285 s = smax;
286 } while ((c = getargc()) != '\n' && c!=EOF);
287 if (xflag) {
288 nenter: s->inp = '\n';
289 if (smax >= &w[MAXSIZ -1]) overflo();
290 s->nst = ++smax;
291 }
292 smax->out = 1;
293 s = w;
294 if (c != EOF)
295 goto nword;
296}
297
298overflo() {
299 fprintf(stderr, "wordlist too large\n");
300 exit(2);
301}
302cfail() {
303 struct words *queue[QSIZE];
304 struct words **front, **rear;
305 struct words *state;
306 register char c;
307 register struct words *s;
308 s = w;
309 front = rear = queue;
310init: if ((s->inp) != 0) {
311 *rear++ = s->nst;
312 if (rear >= &queue[QSIZE - 1]) overflo();
313 }
314 if ((s = s->link) != 0) {
315 goto init;
316 }
317
318 while (rear!=front) {
319 s = *front;
320 if (front == &queue[QSIZE-1])
321 front = queue;
322 else front++;
323 cloop: if ((c = s->inp) != 0) {
324 *rear = (q = s->nst);
325 if (front < rear)
326 if (rear >= &queue[QSIZE-1])
327 if (front == queue) overflo();
328 else rear = queue;
329 else rear++;
330 else
331 if (++rear == front) overflo();
332 state = s->fail;
333 floop: if (state == 0) state = w;
334 if (state->inp == c) {
335 q->fail = state->nst;
336 if ((state->nst)->out == 1) q->out = 1;
337 continue;
338 }
339 else if ((state = state->link) != 0)
340 goto floop;
341 }
342 if ((s = s->link) != 0)
343 goto cloop;
344 }
345}