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*46829Sbostic static char sccsid[] = "@(#)old.ucb.grep.c 5.5 (Berkeley) 03/01/91"; 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; 4732365Sbostic 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 7432365Sbostic case 'o': 7532365Sbostic oflag++; 7632365Sbostic continue; 7732365Sbostic 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) 235*46829Sbostic char *file; 2366639Smckusick { 2376639Smckusick register char *p1, *p2; 2386639Smckusick register c; 2396639Smckusick int f; 2406639Smckusick char *ebp, *cbp; 24121391Smckusick static char *buf; 24221391Smckusick static int blksize; 24321391Smckusick struct stat stb; 2446639Smckusick 2456639Smckusick if (file) { 2466639Smckusick if ((f = open(file, 0)) < 0) { 24712090Smckusick perror(file); 24826447Slepreau retcode = 2; 2496639Smckusick } 2506639Smckusick } else 2516639Smckusick f = 0; 25221391Smckusick if (buf == NULL) { 25321391Smckusick if (fstat(f, &stb) > 0 && stb.st_blksize > 0) 25421391Smckusick blksize = stb.st_blksize; 25521391Smckusick else 25621391Smckusick blksize = BLKSIZE; 25721391Smckusick buf = (char *)malloc(blksize); 25821391Smckusick if (buf == NULL) { 25926447Slepreau fprintf(stderr, "grep: no memory for %s\n", file); 26026447Slepreau retcode = 2; 26121391Smckusick return; 26221391Smckusick } 26321391Smckusick } 26421391Smckusick ebp = buf; 26521391Smckusick cbp = buf; 2666639Smckusick lnum = 0; 2676639Smckusick tln = 0; 2686639Smckusick blkno = -1; 2696639Smckusick for (;;) { 2706639Smckusick lnum++; 2716639Smckusick if((lnum&0377) == 0) 2726639Smckusick fflush(stdout); 2736639Smckusick p1 = linebuf; 2746639Smckusick p2 = cbp; 2756639Smckusick for (;;) { 2766639Smckusick if (p2 >= ebp) { 27721391Smckusick if ((c = read(f, buf, blksize)) <= 0) { 2786639Smckusick close(f); 2796639Smckusick if (cflag) { 2806639Smckusick if (lflag) { 2816639Smckusick if (tln) 2826639Smckusick printf("%s\n", file); 2836639Smckusick } else { 2846639Smckusick if (nfile > 1) 2856639Smckusick printf("%s:", file); 2866639Smckusick printf("%ld\n", tln); 2876639Smckusick } 2886639Smckusick } 2896639Smckusick return; 2906639Smckusick } 2916639Smckusick blkno++; 29221391Smckusick p2 = buf; 29321391Smckusick ebp = buf+c; 2946639Smckusick } 2956639Smckusick if ((c = *p2++) == '\n') 2966639Smckusick break; 2976639Smckusick if(c) 29821391Smckusick if (p1 < &linebuf[BUFSIZ-1]) 2996639Smckusick *p1++ = c; 3006639Smckusick } 3016639Smckusick *p1++ = 0; 3026639Smckusick cbp = p2; 3036639Smckusick p1 = linebuf; 3046639Smckusick p2 = expbuf; 3056639Smckusick if (circf) { 3066639Smckusick if (advance(p1, p2)) 3076639Smckusick goto found; 3086639Smckusick goto nfound; 3096639Smckusick } 3106639Smckusick /* fast check for first character */ 3116639Smckusick if (*p2==CCHR) { 3126639Smckusick c = p2[1]; 3136639Smckusick do { 3146639Smckusick if (*p1!=c && (!iflag || (c ^ *p1) != ' ' 3156639Smckusick || letter(c) != letter(*p1))) 3166639Smckusick continue; 3176639Smckusick if (advance(p1, p2)) 3186639Smckusick goto found; 3196639Smckusick } while (*p1++); 3206639Smckusick goto nfound; 3216639Smckusick } 3226639Smckusick /* regular algorithm */ 3236639Smckusick do { 3246639Smckusick if (advance(p1, p2)) 3256639Smckusick goto found; 3266639Smckusick } while (*p1++); 3276639Smckusick nfound: 3286639Smckusick if (vflag) 3296639Smckusick succeed(file); 3306639Smckusick continue; 3316639Smckusick found: 3326639Smckusick if (vflag==0) 3336639Smckusick succeed(file); 3346639Smckusick } 3356639Smckusick } 3366639Smckusick 3376639Smckusick advance(alp, aep) 3386639Smckusick char *alp, *aep; 3396639Smckusick { 3406639Smckusick register char *lp, *ep, *curlp; 3416639Smckusick char *nextep; 3426639Smckusick 3436639Smckusick lp = alp; 3446639Smckusick ep = aep; 3456639Smckusick for (;;) switch (*ep++) { 3466639Smckusick 3476639Smckusick case CCHR: 3486639Smckusick if (!same(*ep, *lp)) 3496639Smckusick return (0); 3506639Smckusick ep++, lp++; 3516639Smckusick continue; 3526639Smckusick 3536639Smckusick case CDOT: 3546639Smckusick if (*lp++) 3556639Smckusick continue; 3566639Smckusick return(0); 3576639Smckusick 3586639Smckusick case CDOL: 3596639Smckusick if (*lp==0) 3606639Smckusick continue; 3616639Smckusick return(0); 3626639Smckusick 3636639Smckusick case CEOF: 3646639Smckusick return(1); 3656639Smckusick 3666639Smckusick case CCL: 3676639Smckusick if (cclass(ep, *lp++, 1)) { 3686639Smckusick ep += *ep; 3696639Smckusick continue; 3706639Smckusick } 3716639Smckusick return(0); 3726639Smckusick 3736639Smckusick case NCCL: 3746639Smckusick if (cclass(ep, *lp++, 0)) { 3756639Smckusick ep += *ep; 3766639Smckusick continue; 3776639Smckusick } 3786639Smckusick return(0); 3796639Smckusick 3806639Smckusick case CDOT|STAR: 3816639Smckusick curlp = lp; 3826639Smckusick while (*lp++); 3836639Smckusick goto star; 3846639Smckusick 3856639Smckusick case CCHR|STAR: 3866639Smckusick curlp = lp; 3876639Smckusick while (same(*lp, *ep)) 3886639Smckusick lp++; 3896639Smckusick lp++; 3906639Smckusick ep++; 3916639Smckusick goto star; 3926639Smckusick 3936639Smckusick case CCL|STAR: 3946639Smckusick case NCCL|STAR: 3956639Smckusick curlp = lp; 3966639Smckusick while (cclass(ep, *lp++, ep[-1]==(CCL|STAR))); 3976639Smckusick ep += *ep; 3986639Smckusick goto star; 3996639Smckusick 4006639Smckusick star: 4016639Smckusick do { 4026639Smckusick lp--; 4036639Smckusick if (advance(lp, ep)) 4046639Smckusick return(1); 4056639Smckusick } while (lp > curlp); 4066639Smckusick return(0); 4076639Smckusick 4086639Smckusick case CBRC: 4096639Smckusick if (lp == expbuf) 4106639Smckusick continue; 4116639Smckusick #define uletter(c) (letter(c) || c == '_') 4126639Smckusick if ( ( uletter(*lp) || digit ( * lp ) ) && !uletter(lp[-1]) && !digit(lp[-1])) 4136639Smckusick continue; 4146639Smckusick return (0); 4156639Smckusick 4166639Smckusick case CLET: 4176639Smckusick if (!uletter(*lp) && !digit(*lp)) 4186639Smckusick continue; 4196639Smckusick return (0); 4206639Smckusick 4216639Smckusick default: 42226447Slepreau fprintf(stderr, "grep: RE botch\n"); 42326447Slepreau exit(2); 4246639Smckusick } 4256639Smckusick } 4266639Smckusick 4276639Smckusick cclass(aset, ac, af) 4286639Smckusick char *aset; 4296639Smckusick { 4306639Smckusick register char *set, c; 4316639Smckusick register n; 4326639Smckusick 4336639Smckusick set = aset; 4346639Smckusick if ((c = ac) == 0) 4356639Smckusick return(0); 4366639Smckusick n = *set++; 4376639Smckusick while (--n) 4386639Smckusick if (n > 2 && set[1] == '-') { 4396639Smckusick if (c >= (set[0] & 0177) && c <= (set[2] & 0177)) 4406639Smckusick return (af); 4416639Smckusick set += 3; 4426639Smckusick n -= 2; 4436639Smckusick } else 4446639Smckusick if ((*set++ & 0177) == c) 4456639Smckusick return(af); 4466639Smckusick return(!af); 4476639Smckusick } 4486639Smckusick 4496639Smckusick succeed(f) 4506639Smckusick { 4516639Smckusick nsucc = 1; 4526639Smckusick if (sflag) 4536639Smckusick return; 4546639Smckusick if (cflag) { 4556639Smckusick tln++; 4566639Smckusick return; 4576639Smckusick } 45832365Sbostic if (oflag || !hflag && nfile > 1) 4596639Smckusick printf("%s:", f); 4606639Smckusick if (bflag) 4616639Smckusick printf("%d:", blkno); 4626639Smckusick if (nflag) 4636639Smckusick printf("%ld:", lnum); 4646639Smckusick printf("%s\n", linebuf); 4656639Smckusick } 4666639Smckusick 4676639Smckusick digit(c) 4686639Smckusick char c; 4696639Smckusick { 4706639Smckusick return (c>='0' && c<='9'); 4716639Smckusick } 472