Commit | Line | Data |
---|---|---|
2b1a705e TL |
1 | # include "stdio.h" |
2 | # include "ctype.h" | |
3 | /* | |
4 | * fgrep -- print all lines containing any of a set of keywords | |
5 | * | |
6 | * status returns: | |
7 | * 0 - ok, and some matches | |
8 | * 1 - ok, but no matches | |
9 | * 2 - some error | |
10 | */ | |
11 | #define MAXSIZ 700 | |
12 | #define QSIZE 400 | |
13 | struct words { | |
14 | char inp; | |
15 | char out; | |
16 | struct words *nst; | |
17 | struct words *link; | |
18 | struct words *fail; | |
19 | } | |
20 | *www, *smax, *q; | |
21 | ||
22 | char buf[1024]; | |
23 | int nsucc; | |
24 | int need; | |
25 | char *instr; | |
26 | int inct; | |
27 | int rflag; | |
28 | int xargc; | |
29 | char **xargv; | |
30 | int numwords; | |
31 | int nfound; | |
32 | static int flag = 0; | |
33 | ||
34 | ||
35 | fgrep(argc, argv) | |
36 | char **argv; | |
37 | { | |
38 | instr = nsucc = need = inct = rflag = numwords = nfound = 0; | |
39 | flag = 0; | |
40 | if (www==0) | |
41 | www = zalloc(MAXSIZ, sizeof (*www)); | |
42 | if (www==NULL) | |
43 | err("Can't get space for machines", 0); | |
44 | for (q=www; q<www+MAXSIZ; q++) { | |
45 | q->inp =0; q->out =0; q->nst =0; q->link =0; q->fail =0; | |
46 | } | |
47 | xargc = argc-1; | |
48 | xargv = argv+1; | |
49 | while (xargc>0 && xargv[0][0]=='-') | |
50 | { | |
51 | switch(xargv[0][1]) | |
52 | { | |
53 | case 'r': /* return value only */ | |
54 | rflag++; | |
55 | break; | |
56 | case 'n': /* number of answers needed */ | |
57 | need = xargv[1]; | |
58 | xargv++; xargc--; | |
59 | break; | |
60 | case 'i': | |
61 | instr = xargv[1]; | |
62 | inct = xargv[2]+2; | |
63 | # if D2 | |
64 | fprintf(stderr,"inct %d xargv.2. %o %d\n",inct, xargv[2],xargv[2]); | |
65 | # endif | |
66 | xargv += 2; xargc -= 2; | |
67 | break; | |
68 | } | |
69 | xargv++; xargc--; | |
70 | } | |
71 | if (xargc<=0) | |
72 | { | |
73 | write (2, "bad fgrep call\n", 15); | |
74 | exit(2); | |
75 | } | |
76 | # if D1 | |
77 | fprintf(stderr, "before cgoto\n"); | |
78 | # endif | |
79 | cgotofn(); | |
80 | # if D1 | |
81 | fprintf(stderr, "before cfail\n"); | |
82 | # endif | |
83 | cfail(); | |
84 | # if D1 | |
85 | fprintf(stderr, "before execute instr %.20s\n", instr? instr: ""); | |
86 | fprintf(stderr, "end of string %d %c %c %c\n", inct, instr[inct-3], | |
87 | instr[inct-2], instr[inct-1]); | |
88 | # endif | |
89 | execute(); | |
90 | # if D1 | |
91 | fprintf(stderr, "returning nsucc %d\n", nsucc); | |
92 | fprintf(stderr, "fgrep done www %o\n",www); | |
93 | # endif | |
94 | return(nsucc == 0); | |
95 | } | |
96 | ||
97 | execute() | |
98 | { | |
99 | register char *p; | |
100 | register struct words *c; | |
101 | register ch; | |
102 | register ccount; | |
103 | int f; | |
104 | char *nlp; | |
105 | f=0; | |
106 | ccount = instr ? inct : 0; | |
107 | nfound=0; | |
108 | p = instr ? instr : buf; | |
109 | if (need == 0) need = numwords; | |
110 | nlp = p; | |
111 | c = www; | |
112 | # if D2 | |
113 | fprintf(stderr, "in execute ccount %d inct %d\n",ccount, inct ); | |
114 | # endif | |
115 | for (;;) { | |
116 | # if D3 | |
117 | fprintf(stderr, "down ccount\n"); | |
118 | # endif | |
119 | if (--ccount <= 0) { | |
120 | # if D2 | |
121 | fprintf(stderr, "ex loop ccount %d instr %o\n",ccount, instr); | |
122 | # endif | |
123 | if (instr) break; | |
124 | if (p == &buf[1024]) p = buf; | |
125 | if (p > &buf[512]) { | |
126 | if ((ccount = read(f, p, &buf[1024] - p)) <= 0) break; | |
127 | } | |
128 | else if ((ccount = read(f, p, 512)) <= 0) break; | |
129 | # if D2 | |
130 | fprintf(stderr, " normal read %d bytres\n", ccount); | |
131 | {char xx[20]; sprintf(xx, "they are %%.%ds\n", ccount); | |
132 | fprintf(stderr, xx, p); | |
133 | } | |
134 | # endif | |
135 | } | |
136 | nstate: | |
137 | ch = *p; | |
138 | # if D2 | |
139 | fprintf(stderr, "roaming along in ex ch %c c %o\n",ch,c); | |
140 | # endif | |
141 | if (isupper(ch)) ch |= 040; | |
142 | if (c->inp == ch) { | |
143 | c = c->nst; | |
144 | } | |
145 | else if (c->link != 0) { | |
146 | c = c->link; | |
147 | goto nstate; | |
148 | } | |
149 | else { | |
150 | c = c->fail; | |
151 | if (c==0) { | |
152 | c = www; | |
153 | istate: | |
154 | if (c->inp == ch) { | |
155 | c = c->nst; | |
156 | } | |
157 | else if (c->link != 0) { | |
158 | c = c->link; | |
159 | goto istate; | |
160 | } | |
161 | } | |
162 | else goto nstate; | |
163 | } | |
164 | if (c->out && new (c)) { | |
165 | # if D2 | |
166 | fprintf(stderr, " found: nfound %d need %d\n",nfound,need); | |
167 | # endif | |
168 | if (++nfound >= need) | |
169 | { | |
170 | # if D1 | |
171 | fprintf(stderr, "found, p %o nlp %o ccount %d buf %o buf[1024] %o\n",p,nlp,ccount,buf,buf+1024); | |
172 | # endif | |
173 | if (instr==0) | |
174 | while (*p++ != '\n') { | |
175 | # if D3 | |
176 | fprintf(stderr, "down ccount2\n"); | |
177 | # endif | |
178 | if (--ccount <= 0) { | |
179 | if (p == &buf[1024]) p = buf; | |
180 | if (p > &buf[512]) { | |
181 | if ((ccount = read(f, p, &buf[1024] - p)) <= 0) break; | |
182 | } | |
183 | else if ((ccount = read(f, p, 512)) <= 0) break; | |
184 | # if D2 | |
185 | fprintf(stderr, " read %d bytes\n",ccount); | |
186 | { char xx[20]; sprintf(xx, "they are %%.%ds\n", ccount); | |
187 | fprintf(stderr, xx, p); | |
188 | } | |
189 | # endif | |
190 | } | |
191 | } | |
192 | nsucc = 1; | |
193 | if (rflag==0) | |
194 | { | |
195 | # if D2 | |
196 | fprintf(stderr, "p %o nlp %o buf %o\n",p,nlp,buf); | |
197 | if (p>nlp) | |
198 | {write (2, "XX\n", 3); write (2, nlp, p-nlp); write (2, "XX\n", 3);} | |
199 | # endif | |
200 | if (p > nlp) write(1, nlp, p-nlp); | |
201 | else { | |
202 | write(1, nlp, &buf[1024] - nlp); | |
203 | write(1, buf, p-&buf[0]); | |
204 | } | |
205 | if (p[-1]!= '\n') write (1, "\n", 1); | |
206 | } | |
207 | if (instr==0) | |
208 | { | |
209 | nlp = p; | |
210 | c = www; | |
211 | nfound=0; | |
212 | } | |
213 | } | |
214 | else | |
215 | ccount++; | |
216 | continue; | |
217 | } | |
218 | # if D2 | |
219 | fprintf(stderr, "nr end loop p %o\n",p); | |
220 | # endif | |
221 | if (instr) | |
222 | p++; | |
223 | else | |
224 | if (*p++ == '\n') | |
225 | { | |
226 | nlp = p; | |
227 | c = www; | |
228 | nfound=0; | |
229 | } | |
230 | } | |
231 | if (instr==0) | |
232 | close(f); | |
233 | } | |
234 | ||
235 | cgotofn() { | |
236 | register c; | |
237 | register struct words *s; | |
238 | s = smax = www; | |
239 | nword: | |
240 | for(;;) { | |
241 | # if D1 | |
242 | fprintf(stderr, " in for loop c now %o %c\n",c, c>' ' ? c : ' '); | |
243 | # endif | |
244 | if ((c = gch())==0) return; | |
245 | else if (c == '\n') { | |
246 | s->out = 1; | |
247 | s = www; | |
248 | } | |
249 | else { | |
250 | loop: | |
251 | if (s->inp == c) { | |
252 | s = s->nst; | |
253 | continue; | |
254 | } | |
255 | if (s->inp == 0) goto enter; | |
256 | if (s->link == 0) { | |
257 | if (smax >= &www[MAXSIZ - 1]) overflo(); | |
258 | s->link = ++smax; | |
259 | s = smax; | |
260 | goto enter; | |
261 | } | |
262 | s = s->link; | |
263 | goto loop; | |
264 | } | |
265 | } | |
266 | ||
267 | enter: | |
268 | do { | |
269 | s->inp = c; | |
270 | if (smax >= &www[MAXSIZ - 1]) overflo(); | |
271 | s->nst = ++smax; | |
272 | s = smax; | |
273 | } | |
274 | while ((c = gch()) != '\n'); | |
275 | smax->out = 1; | |
276 | s = www; | |
277 | numwords++; | |
278 | goto nword; | |
279 | ||
280 | } | |
281 | ||
282 | gch() | |
283 | { | |
284 | static char *s; | |
285 | if (flag==0) | |
286 | { | |
287 | flag=1; | |
288 | s = *xargv++; | |
289 | # if D1 | |
290 | fprintf(stderr, "next arg is %s xargc %d\n",s,xargc); | |
291 | # endif | |
292 | if (xargc-- <=0) return(0); | |
293 | } | |
294 | if (*s) return(*s++); | |
295 | for(flag=0; flag<1024; flag++) | |
296 | buf[flag]=0; | |
297 | flag=0; | |
298 | return('\n'); | |
299 | } | |
300 | ||
301 | overflo() { | |
302 | write(2,"wordlist too large\n", 19); | |
303 | exit(2); | |
304 | } | |
305 | cfail() { | |
306 | struct words *queue[QSIZE]; | |
307 | struct words **front, **rear; | |
308 | struct words *state; | |
309 | register char c; | |
310 | register struct words *s; | |
311 | s = www; | |
312 | front = rear = queue; | |
313 | init: | |
314 | if ((s->inp) != 0) { | |
315 | *rear++ = s->nst; | |
316 | if (rear >= &queue[QSIZE - 1]) overflo(); | |
317 | } | |
318 | if ((s = s->link) != 0) { | |
319 | goto init; | |
320 | } | |
321 | ||
322 | while (rear!=front) { | |
323 | s = *front; | |
324 | if (front == &queue[QSIZE-1]) | |
325 | front = queue; | |
326 | else front++; | |
327 | cloop: | |
328 | if ((c = s->inp) != 0) { | |
329 | *rear = (q = s->nst); | |
330 | if (front < rear) | |
331 | if (rear >= &queue[QSIZE-1]) | |
332 | if (front == queue) overflo(); | |
333 | else rear = queue; | |
334 | else rear++; | |
335 | else | |
336 | if (++rear == front) overflo(); | |
337 | state = s->fail; | |
338 | floop: | |
339 | if (state == 0) state = www; | |
340 | if (state->inp == c) { | |
341 | q->fail = state->nst; | |
342 | if ((state->nst)->out == 1) q->out = 1; | |
343 | continue; | |
344 | } | |
345 | else if ((state = state->link) != 0) | |
346 | goto floop; | |
347 | } | |
348 | if ((s = s->link) != 0) | |
349 | goto cloop; | |
350 | } | |
351 | } | |
352 | static int seen[50]; | |
353 | new (x) | |
354 | { | |
355 | int i; | |
356 | for(i=0; i<nfound; i++) | |
357 | if (seen[i]==x) | |
358 | return(0); | |
359 | seen[i]=x; | |
360 | return(1); | |
361 | } |