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