1*48267Sbostic /*- 2*48267Sbostic * Copyright (c) 1980 The Regents of the University of California. 3*48267Sbostic * All rights reserved. 4*48267Sbostic * 5*48267Sbostic * %sccs.include.proprietary.c% 621559Sdist */ 721559Sdist 814516Ssam #ifndef lint 921559Sdist char copyright[] = 10*48267Sbostic "@(#) Copyright (c) 1980 The Regents of the University of California.\n\ 1121559Sdist All rights reserved.\n"; 12*48267Sbostic #endif /* not lint */ 136639Smckusick 1421559Sdist #ifndef lint 15*48267Sbostic static char sccsid[] = "@(#)old.ucb.grep.c 5.6 (Berkeley) 04/17/91"; 16*48267Sbostic #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 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 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 2176639Smckusick same(a, b) 2186639Smckusick register int a, b; 2196639Smckusick { 2206639Smckusick 2216639Smckusick return (a == b || iflag && (a ^ b) == ' ' && letter(a) == letter(b)); 2226639Smckusick } 2236639Smckusick 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 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 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 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 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 4686639Smckusick digit(c) 4696639Smckusick char c; 4706639Smckusick { 4716639Smckusick return (c>='0' && c<='9'); 4726639Smckusick } 473