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