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*32363Sbostic static char sccsid[] = "@(#)old.ucb.grep.c 5.3 (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; 46*32363Sbostic int hflag; 476639Smckusick int iflag; 486639Smckusick int lflag; 496639Smckusick int wflag; 506639Smckusick int sflag; 516639Smckusick int nsucc; 526639Smckusick int circf; 536639Smckusick int blkno; 546639Smckusick long tln; 5526447Slepreau int retcode = 0; 566639Smckusick 576639Smckusick main(argc, argv) 586639Smckusick char **argv; 596639Smckusick { 606639Smckusick 616639Smckusick while (--argc > 0 && (++argv)[0][0]=='-') { 626639Smckusick char *cp = argv[0] + 1; 636639Smckusick while (*cp) switch (*cp++) { 646639Smckusick 656639Smckusick case 'v': 666639Smckusick vflag++; 676639Smckusick continue; 686639Smckusick 696639Smckusick case 'b': 706639Smckusick bflag++; 716639Smckusick continue; 726639Smckusick 73*32363Sbostic case 'h': 74*32363Sbostic hflag++; 75*32363Sbostic continue; 76*32363Sbostic 776639Smckusick case 'i': 786639Smckusick case 'y': /* -y for compatibility with btl grep */ 796639Smckusick iflag++; 806639Smckusick continue; 816639Smckusick 826639Smckusick case 'l': 836639Smckusick lflag++; 846639Smckusick case 'c': 856639Smckusick cflag++; 866639Smckusick continue; 876639Smckusick 886639Smckusick case 'w': 896639Smckusick wflag++; 906639Smckusick continue; 916639Smckusick 926639Smckusick case 's': 936639Smckusick sflag++; 946639Smckusick continue; 956639Smckusick 966639Smckusick case 'n': 976639Smckusick nflag++; 986639Smckusick continue; 996639Smckusick 1006639Smckusick case 'e': 1016639Smckusick --argc; 1026639Smckusick ++argv; 1036639Smckusick goto out; 1046639Smckusick 1056639Smckusick default: 10626447Slepreau fprintf(stderr, "grep: unknown flag\n"); 1076639Smckusick continue; 1086639Smckusick } 1096639Smckusick } 1106639Smckusick out: 1116639Smckusick if (argc<=0) 1126639Smckusick exit(2); 1136639Smckusick compile(*argv); 1146639Smckusick nfile = --argc; 1156639Smckusick if (argc<=0) { 1166639Smckusick if (lflag) 1176639Smckusick exit(1); 1186639Smckusick execute(0); 1196639Smckusick } 1206639Smckusick else while (--argc >= 0) { 1216639Smckusick argv++; 1226639Smckusick execute(*argv); 1236639Smckusick } 12426447Slepreau exit(retcode != 0 ? retcode : nsucc == 0); 1256639Smckusick } 1266639Smckusick 1276639Smckusick compile(astr) 1286639Smckusick char *astr; 1296639Smckusick { 1306639Smckusick register c; 1316639Smckusick register char *ep, *sp; 1326639Smckusick char *lastep; 1336639Smckusick int cclcnt; 1346639Smckusick 1356639Smckusick ep = expbuf; 1366639Smckusick sp = astr; 1376639Smckusick if (*sp == '^') { 1386639Smckusick circf++; 1396639Smckusick sp++; 1406639Smckusick } 1416639Smckusick if (wflag) 1426639Smckusick *ep++ = CBRC; 1436639Smckusick for (;;) { 1446639Smckusick if (ep >= &expbuf[ESIZE]) 1456639Smckusick goto cerror; 1466639Smckusick if ((c = *sp++) != '*') 1476639Smckusick lastep = ep; 1486639Smckusick switch (c) { 1496639Smckusick 1506639Smckusick case '\0': 1516639Smckusick if (wflag) 1526639Smckusick *ep++ = CLET; 1536639Smckusick *ep++ = CEOF; 1546639Smckusick return; 1556639Smckusick 1566639Smckusick case '.': 1576639Smckusick *ep++ = CDOT; 1586639Smckusick continue; 1596639Smckusick 1606639Smckusick case '*': 1616639Smckusick if (lastep==0) 1626639Smckusick goto defchar; 1636639Smckusick *lastep |= STAR; 1646639Smckusick continue; 1656639Smckusick 1666639Smckusick case '$': 1676639Smckusick if (*sp != '\0') 1686639Smckusick goto defchar; 1696639Smckusick *ep++ = CDOL; 1706639Smckusick continue; 1716639Smckusick 1726639Smckusick case '[': 1736639Smckusick *ep++ = CCL; 1746639Smckusick *ep++ = 0; 1756639Smckusick cclcnt = 1; 1766639Smckusick if ((c = *sp++) == '^') { 1776639Smckusick c = *sp++; 1786639Smckusick ep[-2] = NCCL; 1796639Smckusick } 1806639Smckusick do { 1816639Smckusick *ep++ = c; 1826639Smckusick cclcnt++; 1836639Smckusick if (c=='\0' || ep >= &expbuf[ESIZE]) 1846639Smckusick goto cerror; 1856639Smckusick } while ((c = *sp++) != ']'); 1866639Smckusick lastep[1] = cclcnt; 1876639Smckusick continue; 1886639Smckusick 1896639Smckusick case '\\': 1906639Smckusick if ((c = *sp++) == '\0') 1916639Smckusick goto cerror; 1926639Smckusick if (c == '<') { 1936639Smckusick *ep++ = CBRC; 1946639Smckusick continue; 1956639Smckusick } 1966639Smckusick if (c == '>') { 1976639Smckusick *ep++ = CLET; 1986639Smckusick continue; 1996639Smckusick } 2006639Smckusick defchar: 2016639Smckusick default: 2026639Smckusick *ep++ = CCHR; 2036639Smckusick *ep++ = c; 2046639Smckusick } 2056639Smckusick } 2066639Smckusick cerror: 20726447Slepreau fprintf(stderr, "grep: RE error\n"); 20826447Slepreau exit(2); 2096639Smckusick } 2106639Smckusick 2116639Smckusick same(a, b) 2126639Smckusick register int a, b; 2136639Smckusick { 2146639Smckusick 2156639Smckusick return (a == b || iflag && (a ^ b) == ' ' && letter(a) == letter(b)); 2166639Smckusick } 2176639Smckusick 2186639Smckusick letter(c) 2196639Smckusick register int c; 2206639Smckusick { 2216639Smckusick 2226639Smckusick if (c >= 'a' && c <= 'z') 2236639Smckusick return (c); 2246639Smckusick if (c >= 'A' && c <= 'Z') 2256639Smckusick return (c + 'a' - 'A'); 2266639Smckusick return (0); 2276639Smckusick } 2286639Smckusick 2296639Smckusick execute(file) 2306639Smckusick { 2316639Smckusick register char *p1, *p2; 2326639Smckusick register c; 2336639Smckusick int f; 2346639Smckusick char *ebp, *cbp; 23521391Smckusick static char *buf; 23621391Smckusick static int blksize; 23721391Smckusick struct stat stb; 2386639Smckusick 2396639Smckusick if (file) { 2406639Smckusick if ((f = open(file, 0)) < 0) { 24112090Smckusick perror(file); 24226447Slepreau retcode = 2; 2436639Smckusick } 2446639Smckusick } else 2456639Smckusick f = 0; 24621391Smckusick if (buf == NULL) { 24721391Smckusick if (fstat(f, &stb) > 0 && stb.st_blksize > 0) 24821391Smckusick blksize = stb.st_blksize; 24921391Smckusick else 25021391Smckusick blksize = BLKSIZE; 25121391Smckusick buf = (char *)malloc(blksize); 25221391Smckusick if (buf == NULL) { 25326447Slepreau fprintf(stderr, "grep: no memory for %s\n", file); 25426447Slepreau retcode = 2; 25521391Smckusick return; 25621391Smckusick } 25721391Smckusick } 25821391Smckusick ebp = buf; 25921391Smckusick cbp = buf; 2606639Smckusick lnum = 0; 2616639Smckusick tln = 0; 2626639Smckusick blkno = -1; 2636639Smckusick for (;;) { 2646639Smckusick lnum++; 2656639Smckusick if((lnum&0377) == 0) 2666639Smckusick fflush(stdout); 2676639Smckusick p1 = linebuf; 2686639Smckusick p2 = cbp; 2696639Smckusick for (;;) { 2706639Smckusick if (p2 >= ebp) { 27121391Smckusick if ((c = read(f, buf, blksize)) <= 0) { 2726639Smckusick close(f); 2736639Smckusick if (cflag) { 2746639Smckusick if (lflag) { 2756639Smckusick if (tln) 2766639Smckusick printf("%s\n", file); 2776639Smckusick } else { 2786639Smckusick if (nfile > 1) 2796639Smckusick printf("%s:", file); 2806639Smckusick printf("%ld\n", tln); 2816639Smckusick } 2826639Smckusick } 2836639Smckusick return; 2846639Smckusick } 2856639Smckusick blkno++; 28621391Smckusick p2 = buf; 28721391Smckusick ebp = buf+c; 2886639Smckusick } 2896639Smckusick if ((c = *p2++) == '\n') 2906639Smckusick break; 2916639Smckusick if(c) 29221391Smckusick if (p1 < &linebuf[BUFSIZ-1]) 2936639Smckusick *p1++ = c; 2946639Smckusick } 2956639Smckusick *p1++ = 0; 2966639Smckusick cbp = p2; 2976639Smckusick p1 = linebuf; 2986639Smckusick p2 = expbuf; 2996639Smckusick if (circf) { 3006639Smckusick if (advance(p1, p2)) 3016639Smckusick goto found; 3026639Smckusick goto nfound; 3036639Smckusick } 3046639Smckusick /* fast check for first character */ 3056639Smckusick if (*p2==CCHR) { 3066639Smckusick c = p2[1]; 3076639Smckusick do { 3086639Smckusick if (*p1!=c && (!iflag || (c ^ *p1) != ' ' 3096639Smckusick || letter(c) != letter(*p1))) 3106639Smckusick continue; 3116639Smckusick if (advance(p1, p2)) 3126639Smckusick goto found; 3136639Smckusick } while (*p1++); 3146639Smckusick goto nfound; 3156639Smckusick } 3166639Smckusick /* regular algorithm */ 3176639Smckusick do { 3186639Smckusick if (advance(p1, p2)) 3196639Smckusick goto found; 3206639Smckusick } while (*p1++); 3216639Smckusick nfound: 3226639Smckusick if (vflag) 3236639Smckusick succeed(file); 3246639Smckusick continue; 3256639Smckusick found: 3266639Smckusick if (vflag==0) 3276639Smckusick succeed(file); 3286639Smckusick } 3296639Smckusick } 3306639Smckusick 3316639Smckusick advance(alp, aep) 3326639Smckusick char *alp, *aep; 3336639Smckusick { 3346639Smckusick register char *lp, *ep, *curlp; 3356639Smckusick char *nextep; 3366639Smckusick 3376639Smckusick lp = alp; 3386639Smckusick ep = aep; 3396639Smckusick for (;;) switch (*ep++) { 3406639Smckusick 3416639Smckusick case CCHR: 3426639Smckusick if (!same(*ep, *lp)) 3436639Smckusick return (0); 3446639Smckusick ep++, lp++; 3456639Smckusick continue; 3466639Smckusick 3476639Smckusick case CDOT: 3486639Smckusick if (*lp++) 3496639Smckusick continue; 3506639Smckusick return(0); 3516639Smckusick 3526639Smckusick case CDOL: 3536639Smckusick if (*lp==0) 3546639Smckusick continue; 3556639Smckusick return(0); 3566639Smckusick 3576639Smckusick case CEOF: 3586639Smckusick return(1); 3596639Smckusick 3606639Smckusick case CCL: 3616639Smckusick if (cclass(ep, *lp++, 1)) { 3626639Smckusick ep += *ep; 3636639Smckusick continue; 3646639Smckusick } 3656639Smckusick return(0); 3666639Smckusick 3676639Smckusick case NCCL: 3686639Smckusick if (cclass(ep, *lp++, 0)) { 3696639Smckusick ep += *ep; 3706639Smckusick continue; 3716639Smckusick } 3726639Smckusick return(0); 3736639Smckusick 3746639Smckusick case CDOT|STAR: 3756639Smckusick curlp = lp; 3766639Smckusick while (*lp++); 3776639Smckusick goto star; 3786639Smckusick 3796639Smckusick case CCHR|STAR: 3806639Smckusick curlp = lp; 3816639Smckusick while (same(*lp, *ep)) 3826639Smckusick lp++; 3836639Smckusick lp++; 3846639Smckusick ep++; 3856639Smckusick goto star; 3866639Smckusick 3876639Smckusick case CCL|STAR: 3886639Smckusick case NCCL|STAR: 3896639Smckusick curlp = lp; 3906639Smckusick while (cclass(ep, *lp++, ep[-1]==(CCL|STAR))); 3916639Smckusick ep += *ep; 3926639Smckusick goto star; 3936639Smckusick 3946639Smckusick star: 3956639Smckusick do { 3966639Smckusick lp--; 3976639Smckusick if (advance(lp, ep)) 3986639Smckusick return(1); 3996639Smckusick } while (lp > curlp); 4006639Smckusick return(0); 4016639Smckusick 4026639Smckusick case CBRC: 4036639Smckusick if (lp == expbuf) 4046639Smckusick continue; 4056639Smckusick #define uletter(c) (letter(c) || c == '_') 4066639Smckusick if ( ( uletter(*lp) || digit ( * lp ) ) && !uletter(lp[-1]) && !digit(lp[-1])) 4076639Smckusick continue; 4086639Smckusick return (0); 4096639Smckusick 4106639Smckusick case CLET: 4116639Smckusick if (!uletter(*lp) && !digit(*lp)) 4126639Smckusick continue; 4136639Smckusick return (0); 4146639Smckusick 4156639Smckusick default: 41626447Slepreau fprintf(stderr, "grep: RE botch\n"); 41726447Slepreau exit(2); 4186639Smckusick } 4196639Smckusick } 4206639Smckusick 4216639Smckusick cclass(aset, ac, af) 4226639Smckusick char *aset; 4236639Smckusick { 4246639Smckusick register char *set, c; 4256639Smckusick register n; 4266639Smckusick 4276639Smckusick set = aset; 4286639Smckusick if ((c = ac) == 0) 4296639Smckusick return(0); 4306639Smckusick n = *set++; 4316639Smckusick while (--n) 4326639Smckusick if (n > 2 && set[1] == '-') { 4336639Smckusick if (c >= (set[0] & 0177) && c <= (set[2] & 0177)) 4346639Smckusick return (af); 4356639Smckusick set += 3; 4366639Smckusick n -= 2; 4376639Smckusick } else 4386639Smckusick if ((*set++ & 0177) == c) 4396639Smckusick return(af); 4406639Smckusick return(!af); 4416639Smckusick } 4426639Smckusick 4436639Smckusick succeed(f) 4446639Smckusick { 4456639Smckusick nsucc = 1; 4466639Smckusick if (sflag) 4476639Smckusick return; 4486639Smckusick if (cflag) { 4496639Smckusick tln++; 4506639Smckusick return; 4516639Smckusick } 452*32363Sbostic if (!hflag && nfile > 1) 4536639Smckusick printf("%s:", f); 4546639Smckusick if (bflag) 4556639Smckusick printf("%d:", blkno); 4566639Smckusick if (nflag) 4576639Smckusick printf("%ld:", lnum); 4586639Smckusick printf("%s\n", linebuf); 4596639Smckusick } 4606639Smckusick 4616639Smckusick digit(c) 4626639Smckusick char c; 4636639Smckusick { 4646639Smckusick return (c>='0' && c<='9'); 4656639Smckusick } 466