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