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