home *** CD-ROM | disk | FTP | other *** search
- /*
- * 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 <stdio.h>
- #include <ctype.h>
- #include <sys/param.h>
-
- #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);
- }
-