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