121559Sdist /* 221559Sdist * Copyright (c) 1980 Regents of the University of California. 321559Sdist * All rights reserved. The Berkeley software License Agreement 421559Sdist * specifies the terms and conditions for redistribution. 521559Sdist */ 621559Sdist 714516Ssam #ifndef lint 821559Sdist char copyright[] = 921559Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 1021559Sdist All rights reserved.\n"; 1121559Sdist #endif not lint 126639Smckusick 1321559Sdist #ifndef lint 14*32365Sbostic static char sccsid[] = "@(#)old.ucb.grep.c 5.4 (Berkeley) 10/07/87"; 1521559Sdist #endif not lint 1621559Sdist 176639Smckusick #include <stdio.h> 1821391Smckusick #include <sys/types.h> 1921391Smckusick #include <sys/stat.h> 206639Smckusick /* 216639Smckusick * grep -- print lines matching (or not matching) a pattern 226639Smckusick */ 236639Smckusick 2421391Smckusick #define BLKSIZE 8192 256639Smckusick #define CCHR 2 266639Smckusick #define CDOT 4 276639Smckusick #define CCL 6 286639Smckusick #define NCCL 8 296639Smckusick #define CDOL 10 306639Smckusick #define CEOF 11 316639Smckusick 326639Smckusick #define CBRC 14 336639Smckusick #define CLET 15 346639Smckusick #define STAR 01 356639Smckusick 366639Smckusick #define ESIZE 256 376639Smckusick 386639Smckusick char expbuf[ESIZE]; 396639Smckusick long lnum; 4021391Smckusick char linebuf[BUFSIZ+1]; 416639Smckusick int bflag; 426639Smckusick int nflag; 436639Smckusick int cflag; 446639Smckusick int vflag; 456639Smckusick int nfile; 4632363Sbostic int hflag; 47*32365Sbostic int oflag; 486639Smckusick int iflag; 496639Smckusick int lflag; 506639Smckusick int wflag; 516639Smckusick int sflag; 526639Smckusick int nsucc; 536639Smckusick int circf; 546639Smckusick int blkno; 556639Smckusick long tln; 5626447Slepreau int retcode = 0; 576639Smckusick 586639Smckusick main(argc, argv) 596639Smckusick char **argv; 606639Smckusick { 616639Smckusick 626639Smckusick while (--argc > 0 && (++argv)[0][0]=='-') { 636639Smckusick char *cp = argv[0] + 1; 646639Smckusick while (*cp) switch (*cp++) { 656639Smckusick 666639Smckusick case 'v': 676639Smckusick vflag++; 686639Smckusick continue; 696639Smckusick 706639Smckusick case 'b': 716639Smckusick bflag++; 726639Smckusick continue; 736639Smckusick 74*32365Sbostic case 'o': 75*32365Sbostic oflag++; 76*32365Sbostic continue; 77*32365Sbostic 7832363Sbostic case 'h': 7932363Sbostic hflag++; 8032363Sbostic continue; 8132363Sbostic 826639Smckusick case 'i': 836639Smckusick case 'y': /* -y for compatibility with btl grep */ 846639Smckusick iflag++; 856639Smckusick continue; 866639Smckusick 876639Smckusick case 'l': 886639Smckusick lflag++; 896639Smckusick case 'c': 906639Smckusick cflag++; 916639Smckusick continue; 926639Smckusick 936639Smckusick case 'w': 946639Smckusick wflag++; 956639Smckusick continue; 966639Smckusick 976639Smckusick case 's': 986639Smckusick sflag++; 996639Smckusick continue; 1006639Smckusick 1016639Smckusick case 'n': 1026639Smckusick nflag++; 1036639Smckusick continue; 1046639Smckusick 1056639Smckusick case 'e': 1066639Smckusick --argc; 1076639Smckusick ++argv; 1086639Smckusick goto out; 1096639Smckusick 1106639Smckusick default: 11126447Slepreau fprintf(stderr, "grep: unknown flag\n"); 1126639Smckusick continue; 1136639Smckusick } 1146639Smckusick } 1156639Smckusick out: 1166639Smckusick if (argc<=0) 1176639Smckusick exit(2); 1186639Smckusick compile(*argv); 1196639Smckusick nfile = --argc; 1206639Smckusick if (argc<=0) { 1216639Smckusick if (lflag) 1226639Smckusick exit(1); 1236639Smckusick execute(0); 1246639Smckusick } 1256639Smckusick else while (--argc >= 0) { 1266639Smckusick argv++; 1276639Smckusick execute(*argv); 1286639Smckusick } 12926447Slepreau exit(retcode != 0 ? retcode : nsucc == 0); 1306639Smckusick } 1316639Smckusick 1326639Smckusick compile(astr) 1336639Smckusick char *astr; 1346639Smckusick { 1356639Smckusick register c; 1366639Smckusick register char *ep, *sp; 1376639Smckusick char *lastep; 1386639Smckusick int cclcnt; 1396639Smckusick 1406639Smckusick ep = expbuf; 1416639Smckusick sp = astr; 1426639Smckusick if (*sp == '^') { 1436639Smckusick circf++; 1446639Smckusick sp++; 1456639Smckusick } 1466639Smckusick if (wflag) 1476639Smckusick *ep++ = CBRC; 1486639Smckusick for (;;) { 1496639Smckusick if (ep >= &expbuf[ESIZE]) 1506639Smckusick goto cerror; 1516639Smckusick if ((c = *sp++) != '*') 1526639Smckusick lastep = ep; 1536639Smckusick switch (c) { 1546639Smckusick 1556639Smckusick case '\0': 1566639Smckusick if (wflag) 1576639Smckusick *ep++ = CLET; 1586639Smckusick *ep++ = CEOF; 1596639Smckusick return; 1606639Smckusick 1616639Smckusick case '.': 1626639Smckusick *ep++ = CDOT; 1636639Smckusick continue; 1646639Smckusick 1656639Smckusick case '*': 1666639Smckusick if (lastep==0) 1676639Smckusick goto defchar; 1686639Smckusick *lastep |= STAR; 1696639Smckusick continue; 1706639Smckusick 1716639Smckusick case '$': 1726639Smckusick if (*sp != '\0') 1736639Smckusick goto defchar; 1746639Smckusick *ep++ = CDOL; 1756639Smckusick continue; 1766639Smckusick 1776639Smckusick case '[': 1786639Smckusick *ep++ = CCL; 1796639Smckusick *ep++ = 0; 1806639Smckusick cclcnt = 1; 1816639Smckusick if ((c = *sp++) == '^') { 1826639Smckusick c = *sp++; 1836639Smckusick ep[-2] = NCCL; 1846639Smckusick } 1856639Smckusick do { 1866639Smckusick *ep++ = c; 1876639Smckusick cclcnt++; 1886639Smckusick if (c=='\0' || ep >= &expbuf[ESIZE]) 1896639Smckusick goto cerror; 1906639Smckusick } while ((c = *sp++) != ']'); 1916639Smckusick lastep[1] = cclcnt; 1926639Smckusick continue; 1936639Smckusick 1946639Smckusick case '\\': 1956639Smckusick if ((c = *sp++) == '\0') 1966639Smckusick goto cerror; 1976639Smckusick if (c == '<') { 1986639Smckusick *ep++ = CBRC; 1996639Smckusick continue; 2006639Smckusick } 2016639Smckusick if (c == '>') { 2026639Smckusick *ep++ = CLET; 2036639Smckusick continue; 2046639Smckusick } 2056639Smckusick defchar: 2066639Smckusick default: 2076639Smckusick *ep++ = CCHR; 2086639Smckusick *ep++ = c; 2096639Smckusick } 2106639Smckusick } 2116639Smckusick cerror: 21226447Slepreau fprintf(stderr, "grep: RE error\n"); 21326447Slepreau exit(2); 2146639Smckusick } 2156639Smckusick 2166639Smckusick same(a, b) 2176639Smckusick register int a, b; 2186639Smckusick { 2196639Smckusick 2206639Smckusick return (a == b || iflag && (a ^ b) == ' ' && letter(a) == letter(b)); 2216639Smckusick } 2226639Smckusick 2236639Smckusick letter(c) 2246639Smckusick register int c; 2256639Smckusick { 2266639Smckusick 2276639Smckusick if (c >= 'a' && c <= 'z') 2286639Smckusick return (c); 2296639Smckusick if (c >= 'A' && c <= 'Z') 2306639Smckusick return (c + 'a' - 'A'); 2316639Smckusick return (0); 2326639Smckusick } 2336639Smckusick 2346639Smckusick execute(file) 2356639Smckusick { 2366639Smckusick register char *p1, *p2; 2376639Smckusick register c; 2386639Smckusick int f; 2396639Smckusick char *ebp, *cbp; 24021391Smckusick static char *buf; 24121391Smckusick static int blksize; 24221391Smckusick struct stat stb; 2436639Smckusick 2446639Smckusick if (file) { 2456639Smckusick if ((f = open(file, 0)) < 0) { 24612090Smckusick perror(file); 24726447Slepreau retcode = 2; 2486639Smckusick } 2496639Smckusick } else 2506639Smckusick f = 0; 25121391Smckusick if (buf == NULL) { 25221391Smckusick if (fstat(f, &stb) > 0 && stb.st_blksize > 0) 25321391Smckusick blksize = stb.st_blksize; 25421391Smckusick else 25521391Smckusick blksize = BLKSIZE; 25621391Smckusick buf = (char *)malloc(blksize); 25721391Smckusick if (buf == NULL) { 25826447Slepreau fprintf(stderr, "grep: no memory for %s\n", file); 25926447Slepreau retcode = 2; 26021391Smckusick return; 26121391Smckusick } 26221391Smckusick } 26321391Smckusick ebp = buf; 26421391Smckusick cbp = buf; 2656639Smckusick lnum = 0; 2666639Smckusick tln = 0; 2676639Smckusick blkno = -1; 2686639Smckusick for (;;) { 2696639Smckusick lnum++; 2706639Smckusick if((lnum&0377) == 0) 2716639Smckusick fflush(stdout); 2726639Smckusick p1 = linebuf; 2736639Smckusick p2 = cbp; 2746639Smckusick for (;;) { 2756639Smckusick if (p2 >= ebp) { 27621391Smckusick if ((c = read(f, buf, blksize)) <= 0) { 2776639Smckusick close(f); 2786639Smckusick if (cflag) { 2796639Smckusick if (lflag) { 2806639Smckusick if (tln) 2816639Smckusick printf("%s\n", file); 2826639Smckusick } else { 2836639Smckusick if (nfile > 1) 2846639Smckusick printf("%s:", file); 2856639Smckusick printf("%ld\n", tln); 2866639Smckusick } 2876639Smckusick } 2886639Smckusick return; 2896639Smckusick } 2906639Smckusick blkno++; 29121391Smckusick p2 = buf; 29221391Smckusick ebp = buf+c; 2936639Smckusick } 2946639Smckusick if ((c = *p2++) == '\n') 2956639Smckusick break; 2966639Smckusick if(c) 29721391Smckusick if (p1 < &linebuf[BUFSIZ-1]) 2986639Smckusick *p1++ = c; 2996639Smckusick } 3006639Smckusick *p1++ = 0; 3016639Smckusick cbp = p2; 3026639Smckusick p1 = linebuf; 3036639Smckusick p2 = expbuf; 3046639Smckusick if (circf) { 3056639Smckusick if (advance(p1, p2)) 3066639Smckusick goto found; 3076639Smckusick goto nfound; 3086639Smckusick } 3096639Smckusick /* fast check for first character */ 3106639Smckusick if (*p2==CCHR) { 3116639Smckusick c = p2[1]; 3126639Smckusick do { 3136639Smckusick if (*p1!=c && (!iflag || (c ^ *p1) != ' ' 3146639Smckusick || letter(c) != letter(*p1))) 3156639Smckusick continue; 3166639Smckusick if (advance(p1, p2)) 3176639Smckusick goto found; 3186639Smckusick } while (*p1++); 3196639Smckusick goto nfound; 3206639Smckusick } 3216639Smckusick /* regular algorithm */ 3226639Smckusick do { 3236639Smckusick if (advance(p1, p2)) 3246639Smckusick goto found; 3256639Smckusick } while (*p1++); 3266639Smckusick nfound: 3276639Smckusick if (vflag) 3286639Smckusick succeed(file); 3296639Smckusick continue; 3306639Smckusick found: 3316639Smckusick if (vflag==0) 3326639Smckusick succeed(file); 3336639Smckusick } 3346639Smckusick } 3356639Smckusick 3366639Smckusick advance(alp, aep) 3376639Smckusick char *alp, *aep; 3386639Smckusick { 3396639Smckusick register char *lp, *ep, *curlp; 3406639Smckusick char *nextep; 3416639Smckusick 3426639Smckusick lp = alp; 3436639Smckusick ep = aep; 3446639Smckusick for (;;) switch (*ep++) { 3456639Smckusick 3466639Smckusick case CCHR: 3476639Smckusick if (!same(*ep, *lp)) 3486639Smckusick return (0); 3496639Smckusick ep++, lp++; 3506639Smckusick continue; 3516639Smckusick 3526639Smckusick case CDOT: 3536639Smckusick if (*lp++) 3546639Smckusick continue; 3556639Smckusick return(0); 3566639Smckusick 3576639Smckusick case CDOL: 3586639Smckusick if (*lp==0) 3596639Smckusick continue; 3606639Smckusick return(0); 3616639Smckusick 3626639Smckusick case CEOF: 3636639Smckusick return(1); 3646639Smckusick 3656639Smckusick case CCL: 3666639Smckusick if (cclass(ep, *lp++, 1)) { 3676639Smckusick ep += *ep; 3686639Smckusick continue; 3696639Smckusick } 3706639Smckusick return(0); 3716639Smckusick 3726639Smckusick case NCCL: 3736639Smckusick if (cclass(ep, *lp++, 0)) { 3746639Smckusick ep += *ep; 3756639Smckusick continue; 3766639Smckusick } 3776639Smckusick return(0); 3786639Smckusick 3796639Smckusick case CDOT|STAR: 3806639Smckusick curlp = lp; 3816639Smckusick while (*lp++); 3826639Smckusick goto star; 3836639Smckusick 3846639Smckusick case CCHR|STAR: 3856639Smckusick curlp = lp; 3866639Smckusick while (same(*lp, *ep)) 3876639Smckusick lp++; 3886639Smckusick lp++; 3896639Smckusick ep++; 3906639Smckusick goto star; 3916639Smckusick 3926639Smckusick case CCL|STAR: 3936639Smckusick case NCCL|STAR: 3946639Smckusick curlp = lp; 3956639Smckusick while (cclass(ep, *lp++, ep[-1]==(CCL|STAR))); 3966639Smckusick ep += *ep; 3976639Smckusick goto star; 3986639Smckusick 3996639Smckusick star: 4006639Smckusick do { 4016639Smckusick lp--; 4026639Smckusick if (advance(lp, ep)) 4036639Smckusick return(1); 4046639Smckusick } while (lp > curlp); 4056639Smckusick return(0); 4066639Smckusick 4076639Smckusick case CBRC: 4086639Smckusick if (lp == expbuf) 4096639Smckusick continue; 4106639Smckusick #define uletter(c) (letter(c) || c == '_') 4116639Smckusick if ( ( uletter(*lp) || digit ( * lp ) ) && !uletter(lp[-1]) && !digit(lp[-1])) 4126639Smckusick continue; 4136639Smckusick return (0); 4146639Smckusick 4156639Smckusick case CLET: 4166639Smckusick if (!uletter(*lp) && !digit(*lp)) 4176639Smckusick continue; 4186639Smckusick return (0); 4196639Smckusick 4206639Smckusick default: 42126447Slepreau fprintf(stderr, "grep: RE botch\n"); 42226447Slepreau exit(2); 4236639Smckusick } 4246639Smckusick } 4256639Smckusick 4266639Smckusick cclass(aset, ac, af) 4276639Smckusick char *aset; 4286639Smckusick { 4296639Smckusick register char *set, c; 4306639Smckusick register n; 4316639Smckusick 4326639Smckusick set = aset; 4336639Smckusick if ((c = ac) == 0) 4346639Smckusick return(0); 4356639Smckusick n = *set++; 4366639Smckusick while (--n) 4376639Smckusick if (n > 2 && set[1] == '-') { 4386639Smckusick if (c >= (set[0] & 0177) && c <= (set[2] & 0177)) 4396639Smckusick return (af); 4406639Smckusick set += 3; 4416639Smckusick n -= 2; 4426639Smckusick } else 4436639Smckusick if ((*set++ & 0177) == c) 4446639Smckusick return(af); 4456639Smckusick return(!af); 4466639Smckusick } 4476639Smckusick 4486639Smckusick succeed(f) 4496639Smckusick { 4506639Smckusick nsucc = 1; 4516639Smckusick if (sflag) 4526639Smckusick return; 4536639Smckusick if (cflag) { 4546639Smckusick tln++; 4556639Smckusick return; 4566639Smckusick } 457*32365Sbostic if (oflag || !hflag && nfile > 1) 4586639Smckusick printf("%s:", f); 4596639Smckusick if (bflag) 4606639Smckusick printf("%d:", blkno); 4616639Smckusick if (nflag) 4626639Smckusick printf("%ld:", lnum); 4636639Smckusick printf("%s\n", linebuf); 4646639Smckusick } 4656639Smckusick 4666639Smckusick digit(c) 4676639Smckusick char c; 4686639Smckusick { 4696639Smckusick return (c>='0' && c<='9'); 4706639Smckusick } 471