From: Ken Thompson Date: Mon, 26 Feb 1979 19:51:09 +0000 (-0500) Subject: Research V7 development X-Git-Tag: Bell-32V^2~134 X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/commitdiff_plain/f264897b5e0ba1b10ca1c9841cb68ec8eeb013a7?ds=inline Research V7 development Work on file usr/src/cmd/grep.c Co-Authored-By: Lee E. McMahon Synthesized-from: v7 --- diff --git a/usr/src/cmd/grep.c b/usr/src/cmd/grep.c new file mode 100644 index 0000000000..da87cb433e --- /dev/null +++ b/usr/src/cmd/grep.c @@ -0,0 +1,478 @@ +/* + * grep -- print lines matching (or not matching) a pattern + * + * status returns: + * 0 - ok, and some matches + * 1 - ok, but no matches + * 2 - some error + */ + +#include +#include +#include + +#define CBRA 1 +#define CCHR 2 +#define CDOT 4 +#define CCL 6 +#define NCCL 8 +#define CDOL 10 +#define CEOF 11 +#define CKET 12 +#define CBACK 18 + +#define STAR 01 + +#define LBSIZE 512 +#define ESIZE 256 +#define NBRA 9 + +char expbuf[ESIZE]; +long lnum; +char linebuf[LBSIZE+1]; +char ybuf[ESIZE]; +int bflag; +int lflag; +int nflag; +int cflag; +int vflag; +int nfile; +int hflag = 1; +int sflag; +int yflag; +int circf; +long tln; +int nsucc; +char *braslist[NBRA]; +char *braelist[NBRA]; +char bittab[] = { + 1, + 2, + 4, + 8, + 16, + 32, + 64, + 128 +}; + +main(argc, argv) +char **argv; +{ + while (--argc > 0 && (++argv)[0][0]=='-') + switch (argv[0][1]) { + + case 'y': + yflag++; + continue; + + case 'h': + hflag = 0; + continue; + + case 's': + sflag++; + continue; + + case 'v': + vflag++; + continue; + + case 'b': + bflag++; + continue; + + case 'l': + lflag++; + continue; + + case 'c': + cflag++; + continue; + + case 'n': + nflag++; + continue; + + case 'e': + --argc; + ++argv; + goto out; + + default: + errexit("grep: unknown flag\n", (char *)NULL); + continue; + } +out: + if (argc<=0) + exit(2); + if (yflag) { + register char *p, *s; + for (s = ybuf, p = *argv; *p; ) { + if (*p == '\\') { + *s++ = *p++; + if (*p) + *s++ = *p++; + } else if (*p == '[') { + while (*p != '\0' && *p != ']') + *s++ = *p++; + } else if (islower(*p)) { + *s++ = '['; + *s++ = toupper(*p); + *s++ = *p++; + *s++ = ']'; + } else + *s++ = *p++; + if (s >= ybuf+ESIZE-5) + errexit("grep: argument too long\n", (char *)NULL); + } + *s = '\0'; + *argv = ybuf; + } + compile(*argv); + nfile = --argc; + if (argc<=0) { + if (lflag) + exit(1); + execute((char *)NULL); + } else while (--argc >= 0) { + argv++; + execute(*argv); + } + exit(nsucc == 0); +} + +compile(astr) +char *astr; +{ + register c; + register char *ep, *sp; + char *cstart; + char *lastep; + int cclcnt; + char bracket[NBRA], *bracketp; + int closed; + char numbra; + char neg; + + ep = expbuf; + sp = astr; + lastep = 0; + bracketp = bracket; + closed = numbra = 0; + if (*sp == '^') { + circf++; + sp++; + } + for (;;) { + if (ep >= &expbuf[ESIZE]) + goto cerror; + if ((c = *sp++) != '*') + lastep = ep; + switch (c) { + + case '\0': + *ep++ = CEOF; + return; + + case '.': + *ep++ = CDOT; + continue; + + case '*': + if (lastep==0 || *lastep==CBRA || *lastep==CKET) + goto defchar; + *lastep |= STAR; + continue; + + case '$': + if (*sp != '\0') + goto defchar; + *ep++ = CDOL; + continue; + + case '[': + if(&ep[17] >= &expbuf[ESIZE]) + goto cerror; + *ep++ = CCL; + neg = 0; + if((c = *sp++) == '^') { + neg = 1; + c = *sp++; + } + cstart = sp; + do { + if (c=='\0') + goto cerror; + if (c=='-' && sp>cstart && *sp!=']') { + for (c = sp[-2]; c<*sp; c++) + ep[c>>3] |= bittab[c&07]; + sp++; + } + ep[c>>3] |= bittab[c&07]; + } while((c = *sp++) != ']'); + if(neg) { + for(cclcnt = 0; cclcnt < 16; cclcnt++) + ep[cclcnt] ^= -1; + ep[0] &= 0376; + } + + ep += 16; + + continue; + + case '\\': + if((c = *sp++) == '(') { + if(numbra >= NBRA) { + goto cerror; + } + *bracketp++ = numbra; + *ep++ = CBRA; + *ep++ = numbra++; + continue; + } + if(c == ')') { + if(bracketp <= bracket) { + goto cerror; + } + *ep++ = CKET; + *ep++ = *--bracketp; + closed++; + continue; + } + + if(c >= '1' && c <= '9') { + if((c -= '1') >= closed) + goto cerror; + *ep++ = CBACK; + *ep++ = c; + continue; + } + + defchar: + default: + *ep++ = CCHR; + *ep++ = c; + } + } + cerror: + errexit("grep: RE error\n", (char *)NULL); +} + +execute(file) +char *file; +{ + register char *p1, *p2; + register c; + + if (file) { + if (freopen(file, "r", stdin) == NULL) + errexit("grep: can't open %s\n", file); + } + lnum = 0; + tln = 0; + for (;;) { + lnum++; + p1 = linebuf; + while ((c = getchar()) != '\n') { + if (c == EOF) { + if (cflag) { + if (nfile>1) + printf("%s:", file); + printf("%D\n", tln); + } + return; + } + *p1++ = c; + if (p1 >= &linebuf[LBSIZE-1]) + break; + } + *p1++ = '\0'; + p1 = linebuf; + p2 = expbuf; + if (circf) { + if (advance(p1, p2)) + goto found; + goto nfound; + } + /* fast check for first character */ + if (*p2==CCHR) { + c = p2[1]; + do { + if (*p1!=c) + continue; + if (advance(p1, p2)) + goto found; + } while (*p1++); + goto nfound; + } + /* regular algorithm */ + do { + if (advance(p1, p2)) + goto found; + } while (*p1++); + nfound: + if (vflag) + succeed(file); + continue; + found: + if (vflag==0) + succeed(file); + } +} + +advance(lp, ep) +register char *lp, *ep; +{ + register char *curlp; + char c; + char *bbeg; + int ct; + + for (;;) switch (*ep++) { + + case CCHR: + if (*ep++ == *lp++) + continue; + return(0); + + case CDOT: + if (*lp++) + continue; + return(0); + + case CDOL: + if (*lp==0) + continue; + return(0); + + case CEOF: + return(1); + + case CCL: + c = *lp++ & 0177; + if(ep[c>>3] & bittab[c & 07]) { + ep += 16; + continue; + } + return(0); + case CBRA: + braslist[*ep++] = lp; + continue; + + case CKET: + braelist[*ep++] = lp; + continue; + + case CBACK: + bbeg = braslist[*ep]; + if (braelist[*ep]==0) + return(0); + ct = braelist[*ep++] - bbeg; + if(ecmp(bbeg, lp, ct)) { + lp += ct; + continue; + } + return(0); + + case CBACK|STAR: + bbeg = braslist[*ep]; + if (braelist[*ep]==0) + return(0); + ct = braelist[*ep++] - bbeg; + curlp = lp; + while(ecmp(bbeg, lp, ct)) + lp += ct; + while(lp >= curlp) { + if(advance(lp, ep)) return(1); + lp -= ct; + } + return(0); + + + case CDOT|STAR: + curlp = lp; + while (*lp++); + goto star; + + case CCHR|STAR: + curlp = lp; + while (*lp++ == *ep); + ep++; + goto star; + + case CCL|STAR: + curlp = lp; + do { + c = *lp++ & 0177; + } while(ep[c>>3] & bittab[c & 07]); + ep += 16; + goto star; + + star: + if(--lp == curlp) { + continue; + } + + if(*ep == CCHR) { + c = ep[1]; + do { + if(*lp != c) + continue; + if(advance(lp, ep)) + return(1); + } while(lp-- > curlp); + return(0); + } + + do { + if (advance(lp, ep)) + return(1); + } while (lp-- > curlp); + return(0); + + default: + errexit("grep RE botch\n", (char *)NULL); + } +} + +succeed(f) +char *f; +{ + long ftell(); + nsucc = 1; + if (sflag) + return; + if (cflag) { + tln++; + return; + } + if (lflag) { + printf("%s\n", f); + fseek(stdin, 0l, 2); + return; + } + if (nfile > 1 && hflag) + printf("%s:", f); + if (bflag) + printf("%ld:", (ftell(stdin)-1)/BSIZE); + if (nflag) + printf("%ld:", lnum); + printf("%s\n", linebuf); +} + +ecmp(a, b, count) +char *a, *b; +{ + register cc = count; + while(cc--) + if(*a++ != *b++) return(0); + return(1); +} + +errexit(s, f) +char *s, *f; +{ + fprintf(stderr, s, f); + exit(2); +}