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