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