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