From:	CRDGW2::CRDGW2::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX" 19-AUG-1989 02:17
To:	MRGATE::"ARISIA::EVERHART"
Subj:	VMS MORE 5 OF 7

Received: From KL.SRI.COM by CRVAX.SRI.COM with TCP; Fri, 18 AUG 89 22:12:01 PDT
Received: from ucbvax.Berkeley.EDU by KL.SRI.COM with TCP; Fri, 18 Aug 89 21:55:02 PDT
Received: by ucbvax.Berkeley.EDU (5.61/1.37)
	id AA29225; Fri, 18 Aug 89 21:50:50 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews
	for info-vax@kl.sri.com (info-vax@kl.sri.com)
	(contact usenet@ucbvax.Berkeley.EDU if you have questions)
Date: 19 Aug 89 03:58:44 GMT
From: gem.mps.ohio-state.edu!ginosko!aplcen!jhunix!jhuvms.bitnet@tut.cis.ohio-state.edu  (Xuning Shan)
Organization: Dept. of Chemical Engineering, The Johns Hopkins University
Subject: VMS MORE 5 OF 7
Message-Id: <2324@jhunix.HCF.JHU.EDU>
Sender: info-vax-request@kl.sri.com
To: info-vax@kl.sri.com

-+-+-+-+-+-+-+-+ START OF PART 5 -+-+-+-+-+-+-+-+
X        sta = NOP;
X        for (p = pat; *p; p++) `123
X                lp = mp;
X                switch (*p) `123
X                case '.':       /* match any char..  */
X                        store(ANY);
X                        break;
X                case '`094':       /* match beginning.. */
X                        if (p == pat)
X                                store(BOL);
X                        else `123
X                                store(CHR);
X                                store(*p);
X                        `125
X                        break;
X                case '$':       /* match endofline.. */
X                        if (!*(p + 1))
X                                store(EOL);
X                        else `123
X                                store(CHR);
X                                store(*p);
X                        `125
X                        break;
X    `032
X                case '`091':       /* match char class.. */
X    `032
X                        if (*++p == '`094') `123
X                                store(NCL);
X                                p++;
X                        `125 else
X                                store(CCL);
X                        if (*p == '-')  /* real dash */
X                                chset(*p++);
X                        if (*p == '`093')  /* real brac */
X                                chset(*p++);
X                        while (*p && *p != '`093') `123
X                                if (*p == '-' && *(p + 1) && *(p + 1) != '`0
V93') `123
X                                        p++;
X                                        c1 = *(p - 2) + 1;
X                                        c2 = *p++;
X                                        while (c1 <= c2)
X                                                chset(c1++);
X                                `125
X#ifdef EXTEND
X                                else if (*p == '\\' && *(p + 1)) `123
X                                        p++;
X                                        chset(*p++);
X                                `125
X#endif
X                                else
X                                        chset(*p++);
X                        `125
X                        if (!*p)
X                                badpat("Missing `093");
X    `032
X                        for (n = 0; n < BITBLK; bittab`091n++`093 = (char) 0
V)
X                                store(bittab`091n`093);
X                        break;
X                case '*':       /* match 0 or more.. */
X                case '+':       /* match 1 or more.. */
X                        if (p == pat)
X                                badpat("Empty closure");
X                        lp = sp;/* previous opcode */
X                        if (*lp == CLO) /* equivalence..   */
X                                break;
X                        switch (*lp) `123
X                        case BOL:
X                        case BOT:
X                        case EOT:
X                        case BOW:
X                        case EOW:
X                        case REF:
X                                badpat("Illegal closure");
X                        default:
X                                break;
X                        `125
X                        if (*p == '+')
X                                for (sp = mp; lp < sp; lp++)
X                                        store(*lp);
X                        store(END);
X                        store(END);
X                        sp = mp;
X                        while (--mp > lp)
X                                *mp = mp`091-1`093;
X                        store(CLO);
X                        mp = sp;
X                        break;
X                case '\\':      /* tags, backrefs .. */
X                        switch (*++p) `123
X                        case '(':
X                                if (tagc < MAXTAG) `123
X                                        tagstk`091++tagi`093 = tagc;
X                                        store(BOT);
X                                        store(tagc++);
X                                `125 else
X                                        badpat("Too many \\(\\) pairs");
X                                break;
X                        case ')':
X                                if (*sp == BOT)
X                                        badpat("Null pattern inside \\(\\)")
V;
X                                if (tagi > 0) `123
X                                        store(EOT);
X                                        store(tagstk`091tagi--`093);
X                                `125 else
X                                        badpat("Unmatched \\)");
X                                break;
X                        case '<':
X                                store(BOW);
X                                break;
X                        case '>':
X                                if (*sp == BOW)
X                                        badpat("Null pattern inside \\<\\>")
V;
X                                store(EOW);
X                                break;
X                        case '1':
X                        case '2':
X                        case '3':
X                        case '4':
X                        case '5':
X                        case '6':
X                        case '7':
X                        case '8':
X                        case '9':
X                                n = *p - '0';
X                                if (tagi > 0 && tagstk`091tagi`093 == n)
X                                        badpat("Cyclical reference");
X                                if (tagc > n) `123
X                                        store(REF);
X                                        store(n);
X                                `125 else
X                                        badpat("Undetermined reference");
X                                break;
X#ifdef EXTEND
X                        case 'b':
X                                store(CHR);
X                                store('\b');
X                                break;
X                        case 'n':
X                                store(CHR);
X                                store('\n');
X                                break;
X                        case 'f':
X                                store(CHR);
X                                store('\f');
X                                break;
X                        case 'r':
X                                store(CHR);
X                                store('\r');
X                                break;
X                        case 't':
X                                store(CHR);
X                                store('\t');
X                                break;
X#endif
X                        default:
X                                store(CHR);
X                                store(*p);
X                        `125
X                        break;
X    `032
X                default:        /* an ordinary char  */
X                        store(CHR);
X                        store(*p);
X                        break;
X                `125
X                sp = lp;
X        `125
X        if (tagi > 0)
X                badpat("Unmatched \\(");
X        store(END);
X        sta = OKP;
X        return (0);
X`125
X    `032
Xnoshare static char *bol;
Xnoshare static char *bopat`091MAXTAG`093;
Xnoshare static char *eopat`091MAXTAG`093;
Xchar           *pmatch();
X/** re_exec: execute dfa to find a match.
X * special cases: (dfa`0910`093) BOL Match only once, starting from the begi
Vnning. CHR
X * First locate the character without calling pmatch, and if found, call
X * pmatch for the remaining string. END re_comp failed, poor luser did not
X * check for it. Fail fast.
X * If a match is found, bopat`0910`093 and eopat`0910`093 are set to the beg
Vinning and the
X * end of the matched fragment, respectively.*/
X    `032
Xint re_exec(lp)
Xregister char  *lp;
X`123
X        register char   c;
X        register char  *ep = 0;
X        register CHAR  *ap = dfa;
X        bol = lp;
X        bopat`0910`093 = 0;
X        bopat`0911`093 = 0;
X        bopat`0912`093 = 0;
X        bopat`0913`093 = 0;
X        bopat`0914`093 = 0;
X        bopat`0915`093 = 0;
X        bopat`0916`093 = 0;
X        bopat`0917`093 = 0;
X        bopat`0918`093 = 0;
X        bopat`0919`093 = 0;
X        switch (*ap) `123
X        case BOL:               /* anchored: match from BOL only */
X                ep = pmatch(lp, ap);
X                break;
X        case CHR:               /* ordinary char: locate it fast */
X                c = *(ap + 1);
X                while (*lp && *lp != c)
X                        lp++;
X                if (!*lp)       /* if EOS, fail, else fall thru. */
X                        return (0);
X        default:                /* regular matching all the way. */
X                while (*lp) `123
X                        if ((ep = pmatch(lp, ap)))
X                                break;
X                        lp++;
X                `125
X                break;
X        case END:               /* munged automaton. fail always */
X                return (0);
X        `125
X        if (!ep)
X                return (0);
X        bopat`0910`093 = lp;
X        eopat`0910`093 = ep;
X        return (1);
X`125
X/** pmatch: internal routine for the hard part
X * This code is mostly snarfed from an early grep written by David Conroy. T
Vhe
X * backref and tag stuff, and various other mods are by oZ.
X *
X * special cases: (dfa`091n`093, dfa`091n+1`093) CLO ANY We KNOW ".*" will m
Vatch ANYTHING
X * upto the end of line. Thus, go to the end of line straight, without
X * calling pmatch recursively. As in the other closure cases, the remaining
X * pattern must be matched by moving backwards on the string recursively, to
X * find a match for xy (x is ".*" and y is the remaining pattern) where the
X * match satisfies the LONGEST match for x followed by a match for y. CLO CH
VR
X * We can again scan the string forward for the single char without
X * recursion, and at the point of failure, we execute the remaining dfa
X * recursively, as described above.
X * At the end of a successful match, bopat`091n`093 and eopat`091n`093 are s
Vet to the
X * beginning and end of subpatterns matched by tagged expressions (n = 1 to
X * 9). */
Xextern void     re_fail();
X/*character classification table for word boundary operators BOW and EOW.
X * the reason for not using ctype macros is that we can let the user add int
Vo
X * our own table. see re_modw. This table is not in the bitset form, since w
Ve
X * may wish to extend it in the future for other character classifications.
X * TRUE for 0-9 A-Z a-z _ */
Xnoshare static char chrtyp`091MAXCHR`093 = `123
X        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X        0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
X        1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
X        0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
X        1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
X        1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
X        1, 0, 0, 0, 0, 1, 0, 1, 1, 1,
X        1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
X        1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
X        1, 1, 1, 0, 0, 0, 0, 0
X`125;
X    `032
X#define inascii(x)    (0177&(x))
X#define iswordc(x)     chrtyp`091inascii(x)`093
X#define isinset(x,y)     ((x)`091((y)&BLKIND)>>3`093 & (1<<((y)&BITIND)))
X/* skip values for CLO XXX to skip past the closure */
X    `032
X#define ANYSKIP    2            /* CLO ANY END ...       */
X#define CHRSKIP    3            /* CLO CHR chr END ...       */
X#define CCLSKIP 18              /* CLO CCL 16bytes END ... */
Xstatic char    *pmatch(lp, ap)
X        register char  *lp;
X        register CHAR  *ap;
X`123
X        register char  *e;      /* extra pointer for CLO */
X        register char  *bp;     /* beginning of subpat.. */
X        register char  *ep;     /* ending of subpat..     */
X        register int    op, c, n;
X        char           *are;    /* to save the line ptr. */
X        while ((op = *ap++) != END)
X                switch (op) `123
X                case CHR:
X                        if (*lp++ != *ap++)
X                                return (0);
X                        break;
X                case ANY:
X                        if (!*lp++)
X                                return (0);
X                        break;
X                case CCL:
X                        c = *lp++;
X                        if (!isinset(ap, c))
X                                return (0);
X                        ap += BITBLK;
X                        break;
X                case NCL:
X                        c = *lp++;
X                        if (isinset(ap, c))
X                                return (0);
X                        ap += BITBLK;
X                        break;
X                case BOL:
X                        if (lp != bol)
X                                return (0);
X                        break;
X                case EOL:
X                        if (*lp)
X                                return (0);
X                        break;
X                case BOT:
X                        bopat`091*ap++`093 = lp;
X                        break;
X                case EOT:
X                        eopat`091*ap++`093 = lp;
X                        break;
X                case BOW:
X                        if (!(lp != bol && iswordc(lp`091-1`093)) && iswordc
V(*lp))
X                                break;
X                        return (0);
X                case EOW:
X                        if ((lp != bol && iswordc(lp`091-1`093)) && !iswordc
V(*lp))
X                                break;
X                        return (0);
X                case REF:
X                        n = *ap++;
X                        bp = bopat`091n`093;
X                        ep = eopat`091n`093;
X                        while (bp < ep)
X                                if (*bp++ != *lp++)
X                                        return (0);
X                        break;
X                case CLO:
X                        are = lp;
X                        switch (*ap) `123
X                        case ANY:
X                                while (*lp)
X                                        lp++;
X                                n = ANYSKIP;
X                                break;
+-+-+-+-+-+-+-+-  END  OF PART 5 +-+-+-+-+-+-+-+-

