1f9fce30aSbostic /*-
2*cea5154fSbostic * Copyright (c) 1991, 1993
3*cea5154fSbostic * The Regents of the University of California. All rights reserved.
4f9fce30aSbostic *
5f9fce30aSbostic * %sccs.include.proprietary.c%
6f9fce30aSbostic */
7f9fce30aSbostic
8542e7acdSsam #ifndef lint
9*cea5154fSbostic static char copyright[] =
10*cea5154fSbostic "@(#) Copyright (c) 1991, 1993\n\
11*cea5154fSbostic The Regents of the University of California. All rights reserved.\n";
12f9fce30aSbostic #endif /* not lint */
13f9fce30aSbostic
14f9fce30aSbostic #ifndef lint
15*cea5154fSbostic static char sccsid[] = "@(#)old.bin.grep.c 8.1 (Berkeley) 06/06/93";
16f9fce30aSbostic #endif /* not lint */
1762b80715Smckusick
1862b80715Smckusick /*
1962b80715Smckusick * grep -- print lines matching (or not matching) a pattern
2062b80715Smckusick *
2162b80715Smckusick * status returns:
2262b80715Smckusick * 0 - ok, and some matches
2362b80715Smckusick * 1 - ok, but no matches
2462b80715Smckusick * 2 - some error
2562b80715Smckusick */
2662b80715Smckusick
2762b80715Smckusick #include <stdio.h>
2862b80715Smckusick #include <ctype.h>
2962b80715Smckusick
3062b80715Smckusick #define CBRA 1
3162b80715Smckusick #define CCHR 2
3262b80715Smckusick #define CDOT 4
3362b80715Smckusick #define CCL 6
3462b80715Smckusick #define NCCL 8
3562b80715Smckusick #define CDOL 10
3662b80715Smckusick #define CEOF 11
3762b80715Smckusick #define CKET 12
38ac340647Ssam #define CBRC 14
39ac340647Ssam #define CLET 15
4062b80715Smckusick #define CBACK 18
4162b80715Smckusick
4262b80715Smckusick #define STAR 01
4362b80715Smckusick
4462b80715Smckusick #define LBSIZE BUFSIZ
4562b80715Smckusick #define ESIZE 256
4662b80715Smckusick #define NBRA 9
4762b80715Smckusick
4862b80715Smckusick char expbuf[ESIZE];
4962b80715Smckusick long lnum;
5062b80715Smckusick char linebuf[LBSIZE+1];
5162b80715Smckusick char ybuf[ESIZE];
5262b80715Smckusick int bflag;
5362b80715Smckusick int lflag;
5462b80715Smckusick int nflag;
5562b80715Smckusick int cflag;
5662b80715Smckusick int vflag;
5762b80715Smckusick int nfile;
5862b80715Smckusick int hflag = 1;
590e19f138Sbostic int oflag;
6062b80715Smckusick int sflag;
6162b80715Smckusick int yflag;
62ac340647Ssam int wflag;
637ae1e203Sedward int retcode = 0;
6462b80715Smckusick int circf;
6562b80715Smckusick int blkno;
6662b80715Smckusick long tln;
6762b80715Smckusick int nsucc;
6862b80715Smckusick char *braslist[NBRA];
6962b80715Smckusick char *braelist[NBRA];
7062b80715Smckusick char bittab[] = {
7162b80715Smckusick 1,
7262b80715Smckusick 2,
7362b80715Smckusick 4,
7462b80715Smckusick 8,
7562b80715Smckusick 16,
7662b80715Smckusick 32,
7762b80715Smckusick 64,
7862b80715Smckusick 128
7962b80715Smckusick };
8062b80715Smckusick
main(argc,argv)8162b80715Smckusick main(argc, argv)
827727b3a7Sbostic int argc;
8362b80715Smckusick char **argv;
8462b80715Smckusick {
857727b3a7Sbostic extern char *optarg;
867727b3a7Sbostic extern int optind;
877727b3a7Sbostic int ch;
8862b80715Smckusick
89217e64dfSbostic while ((ch = getopt(argc, argv, "iywohsvblcne:")) != EOF)
907727b3a7Sbostic switch((char)ch) {
91ac340647Ssam case 'i':
9262b80715Smckusick case 'y':
9362b80715Smckusick yflag++;
947727b3a7Sbostic break;
95ac340647Ssam case 'w':
96ac340647Ssam wflag++;
977727b3a7Sbostic break;
980e19f138Sbostic case 'o':
990e19f138Sbostic oflag++;
1007727b3a7Sbostic break;
10162b80715Smckusick case 'h':
10262b80715Smckusick hflag = 0;
1037727b3a7Sbostic break;
10462b80715Smckusick case 's':
10562b80715Smckusick sflag++;
1067727b3a7Sbostic break;
10762b80715Smckusick case 'v':
10862b80715Smckusick vflag++;
1097727b3a7Sbostic break;
11062b80715Smckusick case 'b':
11162b80715Smckusick bflag++;
1127727b3a7Sbostic break;
11362b80715Smckusick case 'l':
11462b80715Smckusick lflag++;
1157727b3a7Sbostic break;
11662b80715Smckusick case 'c':
11762b80715Smckusick cflag++;
1187727b3a7Sbostic break;
11962b80715Smckusick case 'n':
12062b80715Smckusick nflag++;
1217727b3a7Sbostic break;
12262b80715Smckusick case 'e':
123217e64dfSbostic argv += optind - 1;
124217e64dfSbostic argc -= optind - 1;
1257727b3a7Sbostic *argv = optarg;
12662b80715Smckusick goto out;
1277727b3a7Sbostic case '?':
12862b80715Smckusick default:
12962b80715Smckusick errexit("grep: unknown flag\n", (char *)NULL);
13062b80715Smckusick }
1317727b3a7Sbostic argv += optind;
1327727b3a7Sbostic argc -= optind;
1337727b3a7Sbostic
13462b80715Smckusick out:
13562b80715Smckusick if (argc<=0)
13662b80715Smckusick exit(2);
13762b80715Smckusick if (yflag) {
13862b80715Smckusick register char *p, *s;
13962b80715Smckusick for (s = ybuf, p = *argv; *p; ) {
14062b80715Smckusick if (*p == '\\') {
14162b80715Smckusick *s++ = *p++;
14262b80715Smckusick if (*p)
14362b80715Smckusick *s++ = *p++;
14462b80715Smckusick } else if (*p == '[') {
14562b80715Smckusick while (*p != '\0' && *p != ']')
14662b80715Smckusick *s++ = *p++;
14762b80715Smckusick } else if (islower(*p)) {
14862b80715Smckusick *s++ = '[';
14962b80715Smckusick *s++ = toupper(*p);
15062b80715Smckusick *s++ = *p++;
15162b80715Smckusick *s++ = ']';
15262b80715Smckusick } else
15362b80715Smckusick *s++ = *p++;
15462b80715Smckusick if (s >= ybuf+ESIZE-5)
15562b80715Smckusick errexit("grep: argument too long\n", (char *)NULL);
15662b80715Smckusick }
15762b80715Smckusick *s = '\0';
15862b80715Smckusick *argv = ybuf;
15962b80715Smckusick }
16062b80715Smckusick compile(*argv);
16162b80715Smckusick nfile = --argc;
16262b80715Smckusick if (argc<=0) {
16362b80715Smckusick if (lflag)
16462b80715Smckusick exit(1);
16562b80715Smckusick execute((char *)NULL);
16662b80715Smckusick } else while (--argc >= 0) {
16762b80715Smckusick argv++;
16862b80715Smckusick execute(*argv);
16962b80715Smckusick }
1707ae1e203Sedward exit(retcode != 0 ? retcode : nsucc == 0);
17162b80715Smckusick }
17262b80715Smckusick
compile(astr)17362b80715Smckusick compile(astr)
17462b80715Smckusick char *astr;
17562b80715Smckusick {
17662b80715Smckusick register c;
17762b80715Smckusick register char *ep, *sp;
17862b80715Smckusick char *cstart;
17962b80715Smckusick char *lastep;
18062b80715Smckusick int cclcnt;
18162b80715Smckusick char bracket[NBRA], *bracketp;
18262b80715Smckusick int closed;
18362b80715Smckusick char numbra;
18462b80715Smckusick char neg;
18562b80715Smckusick
18662b80715Smckusick ep = expbuf;
18762b80715Smckusick sp = astr;
18862b80715Smckusick lastep = 0;
18962b80715Smckusick bracketp = bracket;
19062b80715Smckusick closed = numbra = 0;
19162b80715Smckusick if (*sp == '^') {
19262b80715Smckusick circf++;
19362b80715Smckusick sp++;
19462b80715Smckusick }
195ac340647Ssam if (wflag)
196ac340647Ssam *ep++ = CBRC;
19762b80715Smckusick for (;;) {
19862b80715Smckusick if (ep >= &expbuf[ESIZE])
19962b80715Smckusick goto cerror;
20062b80715Smckusick if ((c = *sp++) != '*')
20162b80715Smckusick lastep = ep;
20262b80715Smckusick switch (c) {
20362b80715Smckusick
20462b80715Smckusick case '\0':
205ac340647Ssam if (wflag)
206ac340647Ssam *ep++ = CLET;
20762b80715Smckusick *ep++ = CEOF;
20862b80715Smckusick return;
20962b80715Smckusick
21062b80715Smckusick case '.':
21162b80715Smckusick *ep++ = CDOT;
21262b80715Smckusick continue;
21362b80715Smckusick
21462b80715Smckusick case '*':
215ac340647Ssam if (lastep==0 || *lastep==CBRA || *lastep==CKET ||
216ac340647Ssam *lastep == CBRC || *lastep == CLET)
21762b80715Smckusick goto defchar;
21862b80715Smckusick *lastep |= STAR;
21962b80715Smckusick continue;
22062b80715Smckusick
22162b80715Smckusick case '$':
22262b80715Smckusick if (*sp != '\0')
22362b80715Smckusick goto defchar;
22462b80715Smckusick *ep++ = CDOL;
22562b80715Smckusick continue;
22662b80715Smckusick
22762b80715Smckusick case '[':
22862b80715Smckusick if(&ep[17] >= &expbuf[ESIZE])
22962b80715Smckusick goto cerror;
23062b80715Smckusick *ep++ = CCL;
23162b80715Smckusick neg = 0;
23262b80715Smckusick if((c = *sp++) == '^') {
23362b80715Smckusick neg = 1;
23462b80715Smckusick c = *sp++;
23562b80715Smckusick }
23662b80715Smckusick cstart = sp;
23762b80715Smckusick do {
23862b80715Smckusick if (c=='\0')
23962b80715Smckusick goto cerror;
24062b80715Smckusick if (c=='-' && sp>cstart && *sp!=']') {
24162b80715Smckusick for (c = sp[-2]; c<*sp; c++)
24262b80715Smckusick ep[c>>3] |= bittab[c&07];
24362b80715Smckusick sp++;
24462b80715Smckusick }
24562b80715Smckusick ep[c>>3] |= bittab[c&07];
24662b80715Smckusick } while((c = *sp++) != ']');
24762b80715Smckusick if(neg) {
24862b80715Smckusick for(cclcnt = 0; cclcnt < 16; cclcnt++)
24962b80715Smckusick ep[cclcnt] ^= -1;
25062b80715Smckusick ep[0] &= 0376;
25162b80715Smckusick }
25262b80715Smckusick
25362b80715Smckusick ep += 16;
25462b80715Smckusick
25562b80715Smckusick continue;
25662b80715Smckusick
25762b80715Smckusick case '\\':
258ac340647Ssam if((c = *sp++) == 0)
259ac340647Ssam goto cerror;
260ac340647Ssam if(c == '<') {
261ac340647Ssam *ep++ = CBRC;
262ac340647Ssam continue;
263ac340647Ssam }
264ac340647Ssam if(c == '>') {
265ac340647Ssam *ep++ = CLET;
266ac340647Ssam continue;
267ac340647Ssam }
268ac340647Ssam if(c == '(') {
26962b80715Smckusick if(numbra >= NBRA) {
27062b80715Smckusick goto cerror;
27162b80715Smckusick }
27262b80715Smckusick *bracketp++ = numbra;
27362b80715Smckusick *ep++ = CBRA;
27462b80715Smckusick *ep++ = numbra++;
27562b80715Smckusick continue;
27662b80715Smckusick }
27762b80715Smckusick if(c == ')') {
27862b80715Smckusick if(bracketp <= bracket) {
27962b80715Smckusick goto cerror;
28062b80715Smckusick }
28162b80715Smckusick *ep++ = CKET;
28262b80715Smckusick *ep++ = *--bracketp;
28362b80715Smckusick closed++;
28462b80715Smckusick continue;
28562b80715Smckusick }
28662b80715Smckusick
28762b80715Smckusick if(c >= '1' && c <= '9') {
28862b80715Smckusick if((c -= '1') >= closed)
28962b80715Smckusick goto cerror;
29062b80715Smckusick *ep++ = CBACK;
29162b80715Smckusick *ep++ = c;
29262b80715Smckusick continue;
29362b80715Smckusick }
29462b80715Smckusick
29562b80715Smckusick defchar:
29662b80715Smckusick default:
29762b80715Smckusick *ep++ = CCHR;
29862b80715Smckusick *ep++ = c;
29962b80715Smckusick }
30062b80715Smckusick }
30162b80715Smckusick cerror:
30262b80715Smckusick errexit("grep: RE error\n", (char *)NULL);
30362b80715Smckusick }
30462b80715Smckusick
execute(file)30562b80715Smckusick execute(file)
30662b80715Smckusick char *file;
30762b80715Smckusick {
30862b80715Smckusick register char *p1, *p2;
30962b80715Smckusick register c;
31062b80715Smckusick
31162b80715Smckusick if (file) {
3127ae1e203Sedward if (freopen(file, "r", stdin) == NULL) {
31352d9e935Smckusick perror(file);
3147ae1e203Sedward retcode = 2;
3157ae1e203Sedward }
31662b80715Smckusick }
31762b80715Smckusick lnum = 0;
31862b80715Smckusick tln = 0;
31962b80715Smckusick for (;;) {
32062b80715Smckusick lnum++;
32162b80715Smckusick p1 = linebuf;
32262b80715Smckusick while ((c = getchar()) != '\n') {
32362b80715Smckusick if (c == EOF) {
32462b80715Smckusick if (cflag) {
32562b80715Smckusick if (nfile>1)
32662b80715Smckusick printf("%s:", file);
32762b80715Smckusick printf("%D\n", tln);
32862b80715Smckusick fflush(stdout);
32962b80715Smckusick }
33062b80715Smckusick return;
33162b80715Smckusick }
33262b80715Smckusick *p1++ = c;
33362b80715Smckusick if (p1 >= &linebuf[LBSIZE-1])
33462b80715Smckusick break;
33562b80715Smckusick }
33662b80715Smckusick *p1++ = '\0';
33762b80715Smckusick p1 = linebuf;
33862b80715Smckusick p2 = expbuf;
33962b80715Smckusick if (circf) {
34062b80715Smckusick if (advance(p1, p2))
34162b80715Smckusick goto found;
34262b80715Smckusick goto nfound;
34362b80715Smckusick }
34462b80715Smckusick /* fast check for first character */
34562b80715Smckusick if (*p2==CCHR) {
34662b80715Smckusick c = p2[1];
34762b80715Smckusick do {
34862b80715Smckusick if (*p1!=c)
34962b80715Smckusick continue;
35062b80715Smckusick if (advance(p1, p2))
35162b80715Smckusick goto found;
35262b80715Smckusick } while (*p1++);
35362b80715Smckusick goto nfound;
35462b80715Smckusick }
35562b80715Smckusick /* regular algorithm */
35662b80715Smckusick do {
35762b80715Smckusick if (advance(p1, p2))
35862b80715Smckusick goto found;
35962b80715Smckusick } while (*p1++);
36062b80715Smckusick nfound:
36162b80715Smckusick if (vflag)
36262b80715Smckusick succeed(file);
36362b80715Smckusick continue;
36462b80715Smckusick found:
36562b80715Smckusick if (vflag==0)
36662b80715Smckusick succeed(file);
36762b80715Smckusick }
36862b80715Smckusick }
36962b80715Smckusick
advance(lp,ep)37062b80715Smckusick advance(lp, ep)
37162b80715Smckusick register char *lp, *ep;
37262b80715Smckusick {
37362b80715Smckusick register char *curlp;
37462b80715Smckusick char c;
37562b80715Smckusick char *bbeg;
37662b80715Smckusick int ct;
37762b80715Smckusick
37862b80715Smckusick for (;;) switch (*ep++) {
37962b80715Smckusick
38062b80715Smckusick case CCHR:
38162b80715Smckusick if (*ep++ == *lp++)
38262b80715Smckusick continue;
38362b80715Smckusick return(0);
38462b80715Smckusick
38562b80715Smckusick case CDOT:
38662b80715Smckusick if (*lp++)
38762b80715Smckusick continue;
38862b80715Smckusick return(0);
38962b80715Smckusick
39062b80715Smckusick case CDOL:
39162b80715Smckusick if (*lp==0)
39262b80715Smckusick continue;
39362b80715Smckusick return(0);
39462b80715Smckusick
39562b80715Smckusick case CEOF:
39662b80715Smckusick return(1);
39762b80715Smckusick
39862b80715Smckusick case CCL:
39962b80715Smckusick c = *lp++ & 0177;
40062b80715Smckusick if(ep[c>>3] & bittab[c & 07]) {
40162b80715Smckusick ep += 16;
40262b80715Smckusick continue;
40362b80715Smckusick }
40462b80715Smckusick return(0);
40562b80715Smckusick case CBRA:
40662b80715Smckusick braslist[*ep++] = lp;
40762b80715Smckusick continue;
40862b80715Smckusick
40962b80715Smckusick case CKET:
41062b80715Smckusick braelist[*ep++] = lp;
41162b80715Smckusick continue;
41262b80715Smckusick
41362b80715Smckusick case CBACK:
41462b80715Smckusick bbeg = braslist[*ep];
41562b80715Smckusick if (braelist[*ep]==0)
41662b80715Smckusick return(0);
41762b80715Smckusick ct = braelist[*ep++] - bbeg;
41862b80715Smckusick if(ecmp(bbeg, lp, ct)) {
41962b80715Smckusick lp += ct;
42062b80715Smckusick continue;
42162b80715Smckusick }
42262b80715Smckusick return(0);
42362b80715Smckusick
42462b80715Smckusick case CBACK|STAR:
42562b80715Smckusick bbeg = braslist[*ep];
42662b80715Smckusick if (braelist[*ep]==0)
42762b80715Smckusick return(0);
42862b80715Smckusick ct = braelist[*ep++] - bbeg;
42962b80715Smckusick curlp = lp;
43062b80715Smckusick while(ecmp(bbeg, lp, ct))
43162b80715Smckusick lp += ct;
43262b80715Smckusick while(lp >= curlp) {
43362b80715Smckusick if(advance(lp, ep)) return(1);
43462b80715Smckusick lp -= ct;
43562b80715Smckusick }
43662b80715Smckusick return(0);
43762b80715Smckusick
43862b80715Smckusick
43962b80715Smckusick case CDOT|STAR:
44062b80715Smckusick curlp = lp;
44162b80715Smckusick while (*lp++);
44262b80715Smckusick goto star;
44362b80715Smckusick
44462b80715Smckusick case CCHR|STAR:
44562b80715Smckusick curlp = lp;
44662b80715Smckusick while (*lp++ == *ep);
44762b80715Smckusick ep++;
44862b80715Smckusick goto star;
44962b80715Smckusick
45062b80715Smckusick case CCL|STAR:
45162b80715Smckusick curlp = lp;
45262b80715Smckusick do {
45362b80715Smckusick c = *lp++ & 0177;
45462b80715Smckusick } while(ep[c>>3] & bittab[c & 07]);
45562b80715Smckusick ep += 16;
45662b80715Smckusick goto star;
45762b80715Smckusick
45862b80715Smckusick star:
45962b80715Smckusick if(--lp == curlp) {
46062b80715Smckusick continue;
46162b80715Smckusick }
46262b80715Smckusick
46362b80715Smckusick if(*ep == CCHR) {
46462b80715Smckusick c = ep[1];
46562b80715Smckusick do {
46662b80715Smckusick if(*lp != c)
46762b80715Smckusick continue;
46862b80715Smckusick if(advance(lp, ep))
46962b80715Smckusick return(1);
47062b80715Smckusick } while(lp-- > curlp);
47162b80715Smckusick return(0);
47262b80715Smckusick }
47362b80715Smckusick
47462b80715Smckusick do {
47562b80715Smckusick if (advance(lp, ep))
47662b80715Smckusick return(1);
47762b80715Smckusick } while (lp-- > curlp);
47862b80715Smckusick return(0);
47962b80715Smckusick
480ac340647Ssam case CBRC:
481ac340647Ssam if (lp == expbuf)
482ac340647Ssam continue;
483ac340647Ssam #define uletter(c) (isalpha(c) || (c) == '_')
484ac340647Ssam if (uletter(*lp) || isdigit(*lp))
485ac340647Ssam if (!uletter(lp[-1]) && !isdigit(lp[-1]))
486ac340647Ssam continue;
487ac340647Ssam return (0);
488ac340647Ssam
489ac340647Ssam case CLET:
490ac340647Ssam if (!uletter(*lp) && !isdigit(*lp))
491ac340647Ssam continue;
492ac340647Ssam return (0);
493ac340647Ssam
49462b80715Smckusick default:
49562b80715Smckusick errexit("grep RE botch\n", (char *)NULL);
49662b80715Smckusick }
49762b80715Smckusick }
49862b80715Smckusick
succeed(f)49962b80715Smckusick succeed(f)
50062b80715Smckusick char *f;
50162b80715Smckusick {
50262b80715Smckusick nsucc = 1;
50362b80715Smckusick if (sflag)
50462b80715Smckusick return;
50562b80715Smckusick if (cflag) {
50662b80715Smckusick tln++;
50762b80715Smckusick return;
50862b80715Smckusick }
50962b80715Smckusick if (lflag) {
51062b80715Smckusick printf("%s\n", f);
51162b80715Smckusick fflush(stdout);
51262b80715Smckusick fseek(stdin, 0l, 2);
51362b80715Smckusick return;
51462b80715Smckusick }
5150e19f138Sbostic if (nfile > 1 && hflag || oflag)
51662b80715Smckusick printf("%s:", f);
51762b80715Smckusick if (bflag)
51862b80715Smckusick printf("%u:", blkno);
51962b80715Smckusick if (nflag)
52062b80715Smckusick printf("%ld:", lnum);
52162b80715Smckusick printf("%s\n", linebuf);
52262b80715Smckusick fflush(stdout);
52362b80715Smckusick }
52462b80715Smckusick
ecmp(a,b,count)52562b80715Smckusick ecmp(a, b, count)
52662b80715Smckusick char *a, *b;
52762b80715Smckusick {
52862b80715Smckusick register cc = count;
52962b80715Smckusick while(cc--)
53062b80715Smckusick if(*a++ != *b++) return(0);
53162b80715Smckusick return(1);
53262b80715Smckusick }
53362b80715Smckusick
errexit(s,f)53462b80715Smckusick errexit(s, f)
53562b80715Smckusick char *s, *f;
53662b80715Smckusick {
53762b80715Smckusick fprintf(stderr, s, f);
53862b80715Smckusick exit(2);
53962b80715Smckusick }
540