home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) 1990 Regents of the University of California */
-
- #ifndef lint
- static char SCCSid[] = "@(#)rexpr.c 2.2 11/1/92 LBL";
- #endif
-
- #include <stdio.h>
- #include <ctype.h>
- /*
- * rexpr.c - regular expression parser (ala grep)
- */
-
- #define CCHR 2
- #define CDOT 4
- #define CCL 6
- #define NCCL 8
- #define CDOL 10
- #define CEOF 11
- #define CBRC 14
- #define CLET 15
- #define STAR 01
-
- #define ESIZE 255
-
- #define same(a,b) (a==b || (iflag && (a^b)==' ' && isalpha(a)))
-
- #ifdef BSD
- #define memcpy(to,from,len) bcopy(from,to,len)
- #endif
-
- static int advance(), cclass();
-
- static char expbuf[ESIZE];
- static int iflag;
- static int circf;
-
- int explen; /* length of the last expression found */
-
- int
- ecompile(sp, iflg, wflag) /* compile the expression */
- register char *sp;
- int iflg, wflag;
- {
- register c;
- register char *ep;
- char *lastep;
- int cclcnt;
-
- iflag = iflg;
- ep = expbuf;
- explen = 0;
- if (*sp == '^') {
- circf = 1;
- sp++;
- } else
- circf = 0;
- if (wflag)
- *ep++ = CBRC;
- for (;;) {
- if (ep >= &expbuf[ESIZE])
- return(-1);
- if ((c = *sp++) != '*')
- lastep = ep;
- switch (c) {
-
- case '\0':
- if (wflag)
- *ep++ = CLET;
- *ep++ = CEOF;
- explen = ep - expbuf;
- return(0);
-
- case '.':
- *ep++ = CDOT;
- continue;
-
- case '*':
- if (lastep==0)
- goto defchar;
- *lastep |= STAR;
- continue;
-
- case '$':
- if (*sp != '\0')
- goto defchar;
- *ep++ = CDOL;
- continue;
-
- case '[':
- *ep++ = CCL;
- *ep++ = 0;
- cclcnt = 1;
- if ((c = *sp++) == '^') {
- c = *sp++;
- ep[-2] = NCCL;
- }
- do {
- *ep++ = c;
- cclcnt++;
- if (c=='\0' || ep >= &expbuf[ESIZE])
- return(-1);
- } while ((c = *sp++) != ']');
- lastep[1] = cclcnt;
- continue;
-
- case '\\':
- if ((c = *sp++) == '\0')
- return(-1);
- if (c == '<') {
- if (ep == expbuf || ep[-1] != CBRC)
- *ep++ = CBRC;
- continue;
- }
- if (c == '>') {
- *ep++ = CLET;
- continue;
- }
- defchar:
- default:
- *ep++ = CCHR;
- *ep++ = c;
- }
- }
- }
-
- char *
- expsave() /* save compiled string */
- {
- extern char *malloc();
- register char *ep;
-
- if (explen == 0)
- return(NULL);
- if ((ep = malloc(explen+3)) == NULL)
- return(NULL);
- ep[0] = iflag;
- ep[1] = circf;
- ep[2] = explen;
- (void)memcpy(ep+3, expbuf, explen);
- return(ep);
- }
-
- expset(ep) /* install saved string */
- register char *ep;
- {
- iflag = ep[0];
- circf = ep[1];
- (void)memcpy(expbuf, ep+3, ep[2]&0xff);
- }
-
- char *
- eindex(sp) /* find the expression in string sp */
- register char *sp;
- {
- /* check for match at beginning of line, watch CBRC */
- if (advance(sp, expbuf[0]==CBRC ? expbuf+1 : expbuf))
- return(sp);
- if (circf)
- return(NULL);
- /* fast check for first character */
- if (expbuf[0]==CCHR) {
- register c = expbuf[1];
- while (*++sp)
- if (same(*sp, c) && advance(sp, expbuf))
- return(sp);
- return(NULL);
- }
- /* regular algorithm */
- while (*++sp)
- if (advance(sp, expbuf))
- return(sp);
- return(NULL);
- }
-
- static int
- advance(alp, ep)
- char *alp;
- register char *ep;
- {
- register char *lp;
- char *curlp;
-
- lp = alp;
- for (;;) switch (*ep++) {
-
- case CCHR:
- if (!same(*ep, *lp))
- return (0);
- ep++, lp++;
- continue;
-
- case CDOT:
- if (*lp++)
- continue;
- return(0);
-
- case CDOL:
- if (*lp==0)
- continue;
- return(0);
-
- case CEOF:
- explen = lp - alp;
- return(1);
-
- case CCL:
- if (cclass(ep, *lp++, 1)) {
- ep += *ep;
- continue;
- }
- return(0);
-
- case NCCL:
- if (cclass(ep, *lp++, 0)) {
- ep += *ep;
- continue;
- }
- return(0);
-
- case CDOT|STAR:
- curlp = lp;
- while (*lp++);
- goto star;
-
- case CCHR|STAR:
- curlp = lp;
- while (same(*lp, *ep))
- lp++;
- lp++;
- ep++;
- goto star;
-
- case CCL|STAR:
- case NCCL|STAR:
- curlp = lp;
- while (cclass(ep, *lp++, ep[-1]==(CCL|STAR)));
- ep += *ep;
- star:
- do {
- lp--;
- if (advance(lp, ep)) {
- explen += lp - alp;
- return(1);
- }
- } while (lp > curlp);
- return(0);
-
- case CBRC:
- if ((isalnum(*lp) || *lp == '_') && !(isalnum(lp[-1]) || lp[-1] == '_'))
- continue;
- return (0);
-
- case CLET:
- if (!isalnum(*lp) && *lp != '_')
- continue;
- return (0);
-
- default:
- fprintf(stderr, "RE botch\n");
- }
- }
-
- static int
- cclass(set, c, af)
- register char *set;
- register c;
- {
- register n;
-
- if (c == 0)
- return(0);
- n = *set++;
- while (--n)
- if (n > 2 && set[1] == '-') {
- if (c >= set[0] && c <= set[2])
- return (af);
- set += 3;
- n -= 2;
- } else
- if (*set++ == c)
- return(af);
- return(!af);
- }
-