1 /*-
2 * Copyright (c) 1980, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.proprietary.c%
6 */
7
8 #ifndef lint
9 static char copyright[] =
10 "@(#) Copyright (c) 1980, 1993\n\
11 The Regents of the University of California. All rights reserved.\n";
12 #endif /* not lint */
13
14 #ifndef lint
15 static char sccsid[] = "@(#)old.ucb.grep.c 8.1 (Berkeley) 06/06/93";
16 #endif /* not lint */
17
18 #include <stdio.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 /*
22 * grep -- print lines matching (or not matching) a pattern
23 */
24
25 #define BLKSIZE 8192
26 #define CCHR 2
27 #define CDOT 4
28 #define CCL 6
29 #define NCCL 8
30 #define CDOL 10
31 #define CEOF 11
32
33 #define CBRC 14
34 #define CLET 15
35 #define STAR 01
36
37 #define ESIZE 256
38
39 char expbuf[ESIZE];
40 long lnum;
41 char linebuf[BUFSIZ+1];
42 int bflag;
43 int nflag;
44 int cflag;
45 int vflag;
46 int nfile;
47 int hflag;
48 int oflag;
49 int iflag;
50 int lflag;
51 int wflag;
52 int sflag;
53 int nsucc;
54 int circf;
55 int blkno;
56 long tln;
57 int retcode = 0;
58
main(argc,argv)59 main(argc, argv)
60 char **argv;
61 {
62
63 while (--argc > 0 && (++argv)[0][0]=='-') {
64 char *cp = argv[0] + 1;
65 while (*cp) switch (*cp++) {
66
67 case 'v':
68 vflag++;
69 continue;
70
71 case 'b':
72 bflag++;
73 continue;
74
75 case 'o':
76 oflag++;
77 continue;
78
79 case 'h':
80 hflag++;
81 continue;
82
83 case 'i':
84 case 'y': /* -y for compatibility with btl grep */
85 iflag++;
86 continue;
87
88 case 'l':
89 lflag++;
90 case 'c':
91 cflag++;
92 continue;
93
94 case 'w':
95 wflag++;
96 continue;
97
98 case 's':
99 sflag++;
100 continue;
101
102 case 'n':
103 nflag++;
104 continue;
105
106 case 'e':
107 --argc;
108 ++argv;
109 goto out;
110
111 default:
112 fprintf(stderr, "grep: unknown flag\n");
113 continue;
114 }
115 }
116 out:
117 if (argc<=0)
118 exit(2);
119 compile(*argv);
120 nfile = --argc;
121 if (argc<=0) {
122 if (lflag)
123 exit(1);
124 execute(0);
125 }
126 else while (--argc >= 0) {
127 argv++;
128 execute(*argv);
129 }
130 exit(retcode != 0 ? retcode : nsucc == 0);
131 }
132
compile(astr)133 compile(astr)
134 char *astr;
135 {
136 register c;
137 register char *ep, *sp;
138 char *lastep;
139 int cclcnt;
140
141 ep = expbuf;
142 sp = astr;
143 if (*sp == '^') {
144 circf++;
145 sp++;
146 }
147 if (wflag)
148 *ep++ = CBRC;
149 for (;;) {
150 if (ep >= &expbuf[ESIZE])
151 goto cerror;
152 if ((c = *sp++) != '*')
153 lastep = ep;
154 switch (c) {
155
156 case '\0':
157 if (wflag)
158 *ep++ = CLET;
159 *ep++ = CEOF;
160 return;
161
162 case '.':
163 *ep++ = CDOT;
164 continue;
165
166 case '*':
167 if (lastep==0)
168 goto defchar;
169 *lastep |= STAR;
170 continue;
171
172 case '$':
173 if (*sp != '\0')
174 goto defchar;
175 *ep++ = CDOL;
176 continue;
177
178 case '[':
179 *ep++ = CCL;
180 *ep++ = 0;
181 cclcnt = 1;
182 if ((c = *sp++) == '^') {
183 c = *sp++;
184 ep[-2] = NCCL;
185 }
186 do {
187 *ep++ = c;
188 cclcnt++;
189 if (c=='\0' || ep >= &expbuf[ESIZE])
190 goto cerror;
191 } while ((c = *sp++) != ']');
192 lastep[1] = cclcnt;
193 continue;
194
195 case '\\':
196 if ((c = *sp++) == '\0')
197 goto cerror;
198 if (c == '<') {
199 *ep++ = CBRC;
200 continue;
201 }
202 if (c == '>') {
203 *ep++ = CLET;
204 continue;
205 }
206 defchar:
207 default:
208 *ep++ = CCHR;
209 *ep++ = c;
210 }
211 }
212 cerror:
213 fprintf(stderr, "grep: RE error\n");
214 exit(2);
215 }
216
same(a,b)217 same(a, b)
218 register int a, b;
219 {
220
221 return (a == b || iflag && (a ^ b) == ' ' && letter(a) == letter(b));
222 }
223
letter(c)224 letter(c)
225 register int c;
226 {
227
228 if (c >= 'a' && c <= 'z')
229 return (c);
230 if (c >= 'A' && c <= 'Z')
231 return (c + 'a' - 'A');
232 return (0);
233 }
234
execute(file)235 execute(file)
236 char *file;
237 {
238 register char *p1, *p2;
239 register c;
240 int f;
241 char *ebp, *cbp;
242 static char *buf;
243 static int blksize;
244 struct stat stb;
245
246 if (file) {
247 if ((f = open(file, 0)) < 0) {
248 perror(file);
249 retcode = 2;
250 }
251 } else
252 f = 0;
253 if (buf == NULL) {
254 if (fstat(f, &stb) > 0 && stb.st_blksize > 0)
255 blksize = stb.st_blksize;
256 else
257 blksize = BLKSIZE;
258 buf = (char *)malloc(blksize);
259 if (buf == NULL) {
260 fprintf(stderr, "grep: no memory for %s\n", file);
261 retcode = 2;
262 return;
263 }
264 }
265 ebp = buf;
266 cbp = buf;
267 lnum = 0;
268 tln = 0;
269 blkno = -1;
270 for (;;) {
271 lnum++;
272 if((lnum&0377) == 0)
273 fflush(stdout);
274 p1 = linebuf;
275 p2 = cbp;
276 for (;;) {
277 if (p2 >= ebp) {
278 if ((c = read(f, buf, blksize)) <= 0) {
279 close(f);
280 if (cflag) {
281 if (lflag) {
282 if (tln)
283 printf("%s\n", file);
284 } else {
285 if (nfile > 1)
286 printf("%s:", file);
287 printf("%ld\n", tln);
288 }
289 }
290 return;
291 }
292 blkno++;
293 p2 = buf;
294 ebp = buf+c;
295 }
296 if ((c = *p2++) == '\n')
297 break;
298 if(c)
299 if (p1 < &linebuf[BUFSIZ-1])
300 *p1++ = c;
301 }
302 *p1++ = 0;
303 cbp = p2;
304 p1 = linebuf;
305 p2 = expbuf;
306 if (circf) {
307 if (advance(p1, p2))
308 goto found;
309 goto nfound;
310 }
311 /* fast check for first character */
312 if (*p2==CCHR) {
313 c = p2[1];
314 do {
315 if (*p1!=c && (!iflag || (c ^ *p1) != ' '
316 || letter(c) != letter(*p1)))
317 continue;
318 if (advance(p1, p2))
319 goto found;
320 } while (*p1++);
321 goto nfound;
322 }
323 /* regular algorithm */
324 do {
325 if (advance(p1, p2))
326 goto found;
327 } while (*p1++);
328 nfound:
329 if (vflag)
330 succeed(file);
331 continue;
332 found:
333 if (vflag==0)
334 succeed(file);
335 }
336 }
337
advance(alp,aep)338 advance(alp, aep)
339 char *alp, *aep;
340 {
341 register char *lp, *ep, *curlp;
342 char *nextep;
343
344 lp = alp;
345 ep = aep;
346 for (;;) switch (*ep++) {
347
348 case CCHR:
349 if (!same(*ep, *lp))
350 return (0);
351 ep++, lp++;
352 continue;
353
354 case CDOT:
355 if (*lp++)
356 continue;
357 return(0);
358
359 case CDOL:
360 if (*lp==0)
361 continue;
362 return(0);
363
364 case CEOF:
365 return(1);
366
367 case CCL:
368 if (cclass(ep, *lp++, 1)) {
369 ep += *ep;
370 continue;
371 }
372 return(0);
373
374 case NCCL:
375 if (cclass(ep, *lp++, 0)) {
376 ep += *ep;
377 continue;
378 }
379 return(0);
380
381 case CDOT|STAR:
382 curlp = lp;
383 while (*lp++);
384 goto star;
385
386 case CCHR|STAR:
387 curlp = lp;
388 while (same(*lp, *ep))
389 lp++;
390 lp++;
391 ep++;
392 goto star;
393
394 case CCL|STAR:
395 case NCCL|STAR:
396 curlp = lp;
397 while (cclass(ep, *lp++, ep[-1]==(CCL|STAR)));
398 ep += *ep;
399 goto star;
400
401 star:
402 do {
403 lp--;
404 if (advance(lp, ep))
405 return(1);
406 } while (lp > curlp);
407 return(0);
408
409 case CBRC:
410 if (lp == expbuf)
411 continue;
412 #define uletter(c) (letter(c) || c == '_')
413 if ( ( uletter(*lp) || digit ( * lp ) ) && !uletter(lp[-1]) && !digit(lp[-1]))
414 continue;
415 return (0);
416
417 case CLET:
418 if (!uletter(*lp) && !digit(*lp))
419 continue;
420 return (0);
421
422 default:
423 fprintf(stderr, "grep: RE botch\n");
424 exit(2);
425 }
426 }
427
cclass(aset,ac,af)428 cclass(aset, ac, af)
429 char *aset;
430 {
431 register char *set, c;
432 register n;
433
434 set = aset;
435 if ((c = ac) == 0)
436 return(0);
437 n = *set++;
438 while (--n)
439 if (n > 2 && set[1] == '-') {
440 if (c >= (set[0] & 0177) && c <= (set[2] & 0177))
441 return (af);
442 set += 3;
443 n -= 2;
444 } else
445 if ((*set++ & 0177) == c)
446 return(af);
447 return(!af);
448 }
449
succeed(f)450 succeed(f)
451 {
452 nsucc = 1;
453 if (sflag)
454 return;
455 if (cflag) {
456 tln++;
457 return;
458 }
459 if (oflag || !hflag && nfile > 1)
460 printf("%s:", f);
461 if (bflag)
462 printf("%d:", blkno);
463 if (nflag)
464 printf("%ld:", lnum);
465 printf("%s\n", linebuf);
466 }
467
digit(c)468 digit(c)
469 char c;
470 {
471 return (c>='0' && c<='9');
472 }
473