148267Sbostic /*-
2*62029Sbostic * Copyright (c) 1980, 1993
3*62029Sbostic * The Regents of the University of California. All rights reserved.
448267Sbostic *
548267Sbostic * %sccs.include.proprietary.c%
621559Sdist */
721559Sdist
814516Ssam #ifndef lint
9*62029Sbostic static char copyright[] =
10*62029Sbostic "@(#) Copyright (c) 1980, 1993\n\
11*62029Sbostic The Regents of the University of California. All rights reserved.\n";
1248267Sbostic #endif /* not lint */
136639Smckusick
1421559Sdist #ifndef lint
15*62029Sbostic static char sccsid[] = "@(#)old.ucb.grep.c 8.1 (Berkeley) 06/06/93";
1648267Sbostic #endif /* not lint */
1721559Sdist
186639Smckusick #include <stdio.h>
1921391Smckusick #include <sys/types.h>
2021391Smckusick #include <sys/stat.h>
216639Smckusick /*
226639Smckusick * grep -- print lines matching (or not matching) a pattern
236639Smckusick */
246639Smckusick
2521391Smckusick #define BLKSIZE 8192
266639Smckusick #define CCHR 2
276639Smckusick #define CDOT 4
286639Smckusick #define CCL 6
296639Smckusick #define NCCL 8
306639Smckusick #define CDOL 10
316639Smckusick #define CEOF 11
326639Smckusick
336639Smckusick #define CBRC 14
346639Smckusick #define CLET 15
356639Smckusick #define STAR 01
366639Smckusick
376639Smckusick #define ESIZE 256
386639Smckusick
396639Smckusick char expbuf[ESIZE];
406639Smckusick long lnum;
4121391Smckusick char linebuf[BUFSIZ+1];
426639Smckusick int bflag;
436639Smckusick int nflag;
446639Smckusick int cflag;
456639Smckusick int vflag;
466639Smckusick int nfile;
4732363Sbostic int hflag;
4832365Sbostic int oflag;
496639Smckusick int iflag;
506639Smckusick int lflag;
516639Smckusick int wflag;
526639Smckusick int sflag;
536639Smckusick int nsucc;
546639Smckusick int circf;
556639Smckusick int blkno;
566639Smckusick long tln;
5726447Slepreau int retcode = 0;
586639Smckusick
main(argc,argv)596639Smckusick main(argc, argv)
606639Smckusick char **argv;
616639Smckusick {
626639Smckusick
636639Smckusick while (--argc > 0 && (++argv)[0][0]=='-') {
646639Smckusick char *cp = argv[0] + 1;
656639Smckusick while (*cp) switch (*cp++) {
666639Smckusick
676639Smckusick case 'v':
686639Smckusick vflag++;
696639Smckusick continue;
706639Smckusick
716639Smckusick case 'b':
726639Smckusick bflag++;
736639Smckusick continue;
746639Smckusick
7532365Sbostic case 'o':
7632365Sbostic oflag++;
7732365Sbostic continue;
7832365Sbostic
7932363Sbostic case 'h':
8032363Sbostic hflag++;
8132363Sbostic continue;
8232363Sbostic
836639Smckusick case 'i':
846639Smckusick case 'y': /* -y for compatibility with btl grep */
856639Smckusick iflag++;
866639Smckusick continue;
876639Smckusick
886639Smckusick case 'l':
896639Smckusick lflag++;
906639Smckusick case 'c':
916639Smckusick cflag++;
926639Smckusick continue;
936639Smckusick
946639Smckusick case 'w':
956639Smckusick wflag++;
966639Smckusick continue;
976639Smckusick
986639Smckusick case 's':
996639Smckusick sflag++;
1006639Smckusick continue;
1016639Smckusick
1026639Smckusick case 'n':
1036639Smckusick nflag++;
1046639Smckusick continue;
1056639Smckusick
1066639Smckusick case 'e':
1076639Smckusick --argc;
1086639Smckusick ++argv;
1096639Smckusick goto out;
1106639Smckusick
1116639Smckusick default:
11226447Slepreau fprintf(stderr, "grep: unknown flag\n");
1136639Smckusick continue;
1146639Smckusick }
1156639Smckusick }
1166639Smckusick out:
1176639Smckusick if (argc<=0)
1186639Smckusick exit(2);
1196639Smckusick compile(*argv);
1206639Smckusick nfile = --argc;
1216639Smckusick if (argc<=0) {
1226639Smckusick if (lflag)
1236639Smckusick exit(1);
1246639Smckusick execute(0);
1256639Smckusick }
1266639Smckusick else while (--argc >= 0) {
1276639Smckusick argv++;
1286639Smckusick execute(*argv);
1296639Smckusick }
13026447Slepreau exit(retcode != 0 ? retcode : nsucc == 0);
1316639Smckusick }
1326639Smckusick
compile(astr)1336639Smckusick compile(astr)
1346639Smckusick char *astr;
1356639Smckusick {
1366639Smckusick register c;
1376639Smckusick register char *ep, *sp;
1386639Smckusick char *lastep;
1396639Smckusick int cclcnt;
1406639Smckusick
1416639Smckusick ep = expbuf;
1426639Smckusick sp = astr;
1436639Smckusick if (*sp == '^') {
1446639Smckusick circf++;
1456639Smckusick sp++;
1466639Smckusick }
1476639Smckusick if (wflag)
1486639Smckusick *ep++ = CBRC;
1496639Smckusick for (;;) {
1506639Smckusick if (ep >= &expbuf[ESIZE])
1516639Smckusick goto cerror;
1526639Smckusick if ((c = *sp++) != '*')
1536639Smckusick lastep = ep;
1546639Smckusick switch (c) {
1556639Smckusick
1566639Smckusick case '\0':
1576639Smckusick if (wflag)
1586639Smckusick *ep++ = CLET;
1596639Smckusick *ep++ = CEOF;
1606639Smckusick return;
1616639Smckusick
1626639Smckusick case '.':
1636639Smckusick *ep++ = CDOT;
1646639Smckusick continue;
1656639Smckusick
1666639Smckusick case '*':
1676639Smckusick if (lastep==0)
1686639Smckusick goto defchar;
1696639Smckusick *lastep |= STAR;
1706639Smckusick continue;
1716639Smckusick
1726639Smckusick case '$':
1736639Smckusick if (*sp != '\0')
1746639Smckusick goto defchar;
1756639Smckusick *ep++ = CDOL;
1766639Smckusick continue;
1776639Smckusick
1786639Smckusick case '[':
1796639Smckusick *ep++ = CCL;
1806639Smckusick *ep++ = 0;
1816639Smckusick cclcnt = 1;
1826639Smckusick if ((c = *sp++) == '^') {
1836639Smckusick c = *sp++;
1846639Smckusick ep[-2] = NCCL;
1856639Smckusick }
1866639Smckusick do {
1876639Smckusick *ep++ = c;
1886639Smckusick cclcnt++;
1896639Smckusick if (c=='\0' || ep >= &expbuf[ESIZE])
1906639Smckusick goto cerror;
1916639Smckusick } while ((c = *sp++) != ']');
1926639Smckusick lastep[1] = cclcnt;
1936639Smckusick continue;
1946639Smckusick
1956639Smckusick case '\\':
1966639Smckusick if ((c = *sp++) == '\0')
1976639Smckusick goto cerror;
1986639Smckusick if (c == '<') {
1996639Smckusick *ep++ = CBRC;
2006639Smckusick continue;
2016639Smckusick }
2026639Smckusick if (c == '>') {
2036639Smckusick *ep++ = CLET;
2046639Smckusick continue;
2056639Smckusick }
2066639Smckusick defchar:
2076639Smckusick default:
2086639Smckusick *ep++ = CCHR;
2096639Smckusick *ep++ = c;
2106639Smckusick }
2116639Smckusick }
2126639Smckusick cerror:
21326447Slepreau fprintf(stderr, "grep: RE error\n");
21426447Slepreau exit(2);
2156639Smckusick }
2166639Smckusick
same(a,b)2176639Smckusick same(a, b)
2186639Smckusick register int a, b;
2196639Smckusick {
2206639Smckusick
2216639Smckusick return (a == b || iflag && (a ^ b) == ' ' && letter(a) == letter(b));
2226639Smckusick }
2236639Smckusick
letter(c)2246639Smckusick letter(c)
2256639Smckusick register int c;
2266639Smckusick {
2276639Smckusick
2286639Smckusick if (c >= 'a' && c <= 'z')
2296639Smckusick return (c);
2306639Smckusick if (c >= 'A' && c <= 'Z')
2316639Smckusick return (c + 'a' - 'A');
2326639Smckusick return (0);
2336639Smckusick }
2346639Smckusick
execute(file)2356639Smckusick execute(file)
23646829Sbostic char *file;
2376639Smckusick {
2386639Smckusick register char *p1, *p2;
2396639Smckusick register c;
2406639Smckusick int f;
2416639Smckusick char *ebp, *cbp;
24221391Smckusick static char *buf;
24321391Smckusick static int blksize;
24421391Smckusick struct stat stb;
2456639Smckusick
2466639Smckusick if (file) {
2476639Smckusick if ((f = open(file, 0)) < 0) {
24812090Smckusick perror(file);
24926447Slepreau retcode = 2;
2506639Smckusick }
2516639Smckusick } else
2526639Smckusick f = 0;
25321391Smckusick if (buf == NULL) {
25421391Smckusick if (fstat(f, &stb) > 0 && stb.st_blksize > 0)
25521391Smckusick blksize = stb.st_blksize;
25621391Smckusick else
25721391Smckusick blksize = BLKSIZE;
25821391Smckusick buf = (char *)malloc(blksize);
25921391Smckusick if (buf == NULL) {
26026447Slepreau fprintf(stderr, "grep: no memory for %s\n", file);
26126447Slepreau retcode = 2;
26221391Smckusick return;
26321391Smckusick }
26421391Smckusick }
26521391Smckusick ebp = buf;
26621391Smckusick cbp = buf;
2676639Smckusick lnum = 0;
2686639Smckusick tln = 0;
2696639Smckusick blkno = -1;
2706639Smckusick for (;;) {
2716639Smckusick lnum++;
2726639Smckusick if((lnum&0377) == 0)
2736639Smckusick fflush(stdout);
2746639Smckusick p1 = linebuf;
2756639Smckusick p2 = cbp;
2766639Smckusick for (;;) {
2776639Smckusick if (p2 >= ebp) {
27821391Smckusick if ((c = read(f, buf, blksize)) <= 0) {
2796639Smckusick close(f);
2806639Smckusick if (cflag) {
2816639Smckusick if (lflag) {
2826639Smckusick if (tln)
2836639Smckusick printf("%s\n", file);
2846639Smckusick } else {
2856639Smckusick if (nfile > 1)
2866639Smckusick printf("%s:", file);
2876639Smckusick printf("%ld\n", tln);
2886639Smckusick }
2896639Smckusick }
2906639Smckusick return;
2916639Smckusick }
2926639Smckusick blkno++;
29321391Smckusick p2 = buf;
29421391Smckusick ebp = buf+c;
2956639Smckusick }
2966639Smckusick if ((c = *p2++) == '\n')
2976639Smckusick break;
2986639Smckusick if(c)
29921391Smckusick if (p1 < &linebuf[BUFSIZ-1])
3006639Smckusick *p1++ = c;
3016639Smckusick }
3026639Smckusick *p1++ = 0;
3036639Smckusick cbp = p2;
3046639Smckusick p1 = linebuf;
3056639Smckusick p2 = expbuf;
3066639Smckusick if (circf) {
3076639Smckusick if (advance(p1, p2))
3086639Smckusick goto found;
3096639Smckusick goto nfound;
3106639Smckusick }
3116639Smckusick /* fast check for first character */
3126639Smckusick if (*p2==CCHR) {
3136639Smckusick c = p2[1];
3146639Smckusick do {
3156639Smckusick if (*p1!=c && (!iflag || (c ^ *p1) != ' '
3166639Smckusick || letter(c) != letter(*p1)))
3176639Smckusick continue;
3186639Smckusick if (advance(p1, p2))
3196639Smckusick goto found;
3206639Smckusick } while (*p1++);
3216639Smckusick goto nfound;
3226639Smckusick }
3236639Smckusick /* regular algorithm */
3246639Smckusick do {
3256639Smckusick if (advance(p1, p2))
3266639Smckusick goto found;
3276639Smckusick } while (*p1++);
3286639Smckusick nfound:
3296639Smckusick if (vflag)
3306639Smckusick succeed(file);
3316639Smckusick continue;
3326639Smckusick found:
3336639Smckusick if (vflag==0)
3346639Smckusick succeed(file);
3356639Smckusick }
3366639Smckusick }
3376639Smckusick
advance(alp,aep)3386639Smckusick advance(alp, aep)
3396639Smckusick char *alp, *aep;
3406639Smckusick {
3416639Smckusick register char *lp, *ep, *curlp;
3426639Smckusick char *nextep;
3436639Smckusick
3446639Smckusick lp = alp;
3456639Smckusick ep = aep;
3466639Smckusick for (;;) switch (*ep++) {
3476639Smckusick
3486639Smckusick case CCHR:
3496639Smckusick if (!same(*ep, *lp))
3506639Smckusick return (0);
3516639Smckusick ep++, lp++;
3526639Smckusick continue;
3536639Smckusick
3546639Smckusick case CDOT:
3556639Smckusick if (*lp++)
3566639Smckusick continue;
3576639Smckusick return(0);
3586639Smckusick
3596639Smckusick case CDOL:
3606639Smckusick if (*lp==0)
3616639Smckusick continue;
3626639Smckusick return(0);
3636639Smckusick
3646639Smckusick case CEOF:
3656639Smckusick return(1);
3666639Smckusick
3676639Smckusick case CCL:
3686639Smckusick if (cclass(ep, *lp++, 1)) {
3696639Smckusick ep += *ep;
3706639Smckusick continue;
3716639Smckusick }
3726639Smckusick return(0);
3736639Smckusick
3746639Smckusick case NCCL:
3756639Smckusick if (cclass(ep, *lp++, 0)) {
3766639Smckusick ep += *ep;
3776639Smckusick continue;
3786639Smckusick }
3796639Smckusick return(0);
3806639Smckusick
3816639Smckusick case CDOT|STAR:
3826639Smckusick curlp = lp;
3836639Smckusick while (*lp++);
3846639Smckusick goto star;
3856639Smckusick
3866639Smckusick case CCHR|STAR:
3876639Smckusick curlp = lp;
3886639Smckusick while (same(*lp, *ep))
3896639Smckusick lp++;
3906639Smckusick lp++;
3916639Smckusick ep++;
3926639Smckusick goto star;
3936639Smckusick
3946639Smckusick case CCL|STAR:
3956639Smckusick case NCCL|STAR:
3966639Smckusick curlp = lp;
3976639Smckusick while (cclass(ep, *lp++, ep[-1]==(CCL|STAR)));
3986639Smckusick ep += *ep;
3996639Smckusick goto star;
4006639Smckusick
4016639Smckusick star:
4026639Smckusick do {
4036639Smckusick lp--;
4046639Smckusick if (advance(lp, ep))
4056639Smckusick return(1);
4066639Smckusick } while (lp > curlp);
4076639Smckusick return(0);
4086639Smckusick
4096639Smckusick case CBRC:
4106639Smckusick if (lp == expbuf)
4116639Smckusick continue;
4126639Smckusick #define uletter(c) (letter(c) || c == '_')
4136639Smckusick if ( ( uletter(*lp) || digit ( * lp ) ) && !uletter(lp[-1]) && !digit(lp[-1]))
4146639Smckusick continue;
4156639Smckusick return (0);
4166639Smckusick
4176639Smckusick case CLET:
4186639Smckusick if (!uletter(*lp) && !digit(*lp))
4196639Smckusick continue;
4206639Smckusick return (0);
4216639Smckusick
4226639Smckusick default:
42326447Slepreau fprintf(stderr, "grep: RE botch\n");
42426447Slepreau exit(2);
4256639Smckusick }
4266639Smckusick }
4276639Smckusick
cclass(aset,ac,af)4286639Smckusick cclass(aset, ac, af)
4296639Smckusick char *aset;
4306639Smckusick {
4316639Smckusick register char *set, c;
4326639Smckusick register n;
4336639Smckusick
4346639Smckusick set = aset;
4356639Smckusick if ((c = ac) == 0)
4366639Smckusick return(0);
4376639Smckusick n = *set++;
4386639Smckusick while (--n)
4396639Smckusick if (n > 2 && set[1] == '-') {
4406639Smckusick if (c >= (set[0] & 0177) && c <= (set[2] & 0177))
4416639Smckusick return (af);
4426639Smckusick set += 3;
4436639Smckusick n -= 2;
4446639Smckusick } else
4456639Smckusick if ((*set++ & 0177) == c)
4466639Smckusick return(af);
4476639Smckusick return(!af);
4486639Smckusick }
4496639Smckusick
succeed(f)4506639Smckusick succeed(f)
4516639Smckusick {
4526639Smckusick nsucc = 1;
4536639Smckusick if (sflag)
4546639Smckusick return;
4556639Smckusick if (cflag) {
4566639Smckusick tln++;
4576639Smckusick return;
4586639Smckusick }
45932365Sbostic if (oflag || !hflag && nfile > 1)
4606639Smckusick printf("%s:", f);
4616639Smckusick if (bflag)
4626639Smckusick printf("%d:", blkno);
4636639Smckusick if (nflag)
4646639Smckusick printf("%ld:", lnum);
4656639Smckusick printf("%s\n", linebuf);
4666639Smckusick }
4676639Smckusick
digit(c)4686639Smckusick digit(c)
4696639Smckusick char c;
4706639Smckusick {
4716639Smckusick return (c>='0' && c<='9');
4726639Smckusick }
473