Annotation of coherent/d/bin/grep/grep2.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Regular expression routines.
        !             3:  * These routines are currently used by grep but
        !             4:  * they are somewhat general and thus could be
        !             5:  * used elsewhere.
        !             6:  */
        !             7: 
        !             8: #include <stdio.h>
        !             9: #include <ctype.h>
        !            10: #include "grep.h"
        !            11: 
        !            12: char   *newcc();
        !            13: char   *e_exec();
        !            14: 
        !            15: 
        !            16: static char    repri[] = {
        !            17:        0 /* REEND */,  2 /* STEND */,
        !            18:        3 /* OR */,     6 /* LPAR */,
        !            19:        1 /* RPAR */,   5 /* CLOS */,
        !            20:        5 /* NECLOS */, 5 /* ZORO */,
        !            21:        4 /* CONC */
        !            22: };
        !            23: 
        !            24: RE     **rebuild();
        !            25: RE     *renode();
        !            26: static union rebit     relval;
        !            27: static char    cc[NCLASS];
        !            28: static (*reinf)();
        !            29: static (*reunf)();
        !            30: static char    *rein;
        !            31: 
        !            32: static char    resyn[] = "Regular expression syntax error";
        !            33: static char    reoflo[] = "Regular expression overflow";
        !            34: static char    nospace[] = "Out of space";
        !            35: 
        !            36: char   *reerror;               /* Erro code */
        !            37: int    redual;                 /* Set for dual-case comparisons */
        !            38: int    refull;                 /* Full expressions accepted */
        !            39: 
        !            40: /*
        !            41:  * Lexical token reader for
        !            42:  * regular expressions.
        !            43:  */
        !            44: static
        !            45: relex(ec)
        !            46: {
        !            47:        register c;
        !            48: 
        !            49:        if ((c = (*reinf)()) == ec)
        !            50:                return (REEND);
        !            51:        switch (c) {
        !            52:        case EOF:
        !            53:        case '\n':
        !            54:                reerror = "Non-terminated regular expression";
        !            55:                return (REEND);
        !            56: 
        !            57:        case '[':
        !            58:                return (cclass(ec));
        !            59: 
        !            60:        case '^':
        !            61:                return (BOL);
        !            62: 
        !            63:        case '$':
        !            64:                return (EOL);
        !            65: 
        !            66:        case '(':
        !            67:                if (!refull)
        !            68:                        goto def;
        !            69:                return (LPAR);
        !            70: 
        !            71:        case ')':
        !            72:                if (!refull)
        !            73:                        goto def;
        !            74:                return (RPAR);
        !            75: 
        !            76:        case '.':
        !            77:                return (ANY);
        !            78: 
        !            79:        case '|':
        !            80:                if (!refull)
        !            81:                        goto def;
        !            82:                return (OR);
        !            83: 
        !            84:        case '*':
        !            85:                return (CLOS);
        !            86: 
        !            87:        case '?':
        !            88:                if (!refull)
        !            89:                        goto def;
        !            90:                return (ZORO);
        !            91: 
        !            92:        case '+':
        !            93:                if (!refull)
        !            94:                        goto def;
        !            95:                return (NECLOS);
        !            96: 
        !            97:        case '\\':
        !            98:                c = (*reinf)();
        !            99:        default:
        !           100:        def:
        !           101:                relval.u_ival = c;
        !           102:                return (redual ? DCONC : CONC);
        !           103:        }
        !           104: }
        !           105: 
        !           106: /*
        !           107:  * Read in a character class from
        !           108:  * an RE (called from relex).
        !           109:  */
        !           110: static
        !           111: cclass(ec)
        !           112: int ec;
        !           113: {
        !           114:        register c, i, pc;
        !           115:        int comp;
        !           116: 
        !           117:        for (i=0; i<sizeof cc; i++)
        !           118:                cc[i] = 0;
        !           119:        if ((c = (*reinf)()) != '^') {
        !           120:                comp = 0;
        !           121:                (*reunf)(c);
        !           122:        } else
        !           123:                comp = 1;
        !           124:        pc = ec;
        !           125:        while ((c = (*reinf)()) != ']') {
        !           126:                if (c == ec) {
        !           127:                        reerror = "Non-terminated character class";
        !           128:                        return (REEND);
        !           129:                }
        !           130:                if (c=='-' && pc!=ec) {
        !           131:                        if ((c = (*reinf)()) == ']')
        !           132:                                break;
        !           133:                        for (i=pc; i<=c; i++)
        !           134:                                cc[i/NBPC] |= 1<<(i%NBPC);
        !           135:                        pc = ec;
        !           136:                } else {
        !           137:                        cc[c/NBPC] |= 1<<(c%NBPC);
        !           138:                        pc = c;
        !           139:                }
        !           140:        }
        !           141:        if (comp)
        !           142:                for (i=0; i<sizeof cc; i++)
        !           143:                        cc[i] ^= -1;
        !           144:        if ((relval.u_cptr = newcc(cc)) == NULL)
        !           145:                return (REEND);
        !           146:        return (redual ? DCCLASS : CCLASS);
        !           147: }
        !           148: 
        !           149: /*
        !           150:  * Allocate space for a new character class
        !           151:  * and copy into it.
        !           152:  */
        !           153: static char *
        !           154: newcc(occ)
        !           155: register char *occ;
        !           156: {
        !           157:        register char *ncc;
        !           158:        register unsigned n;
        !           159:        char *rcc;
        !           160: 
        !           161:        n = NCLASS;
        !           162:        if ((rcc = ncc = malloc(n)) == NULL) {
        !           163:                reerror = nospace;
        !           164:                return (NULL);
        !           165:        }
        !           166:        do {
        !           167:                *ncc++ = *occ++;
        !           168:        } while (--n);
        !           169:        return (rcc);
        !           170: }
        !           171: 
        !           172: /*
        !           173:  * Parse a regular expression.
        !           174:  * The arguments are an input string to parse (`in'),
        !           175:  * the end character to terminated the expression (`ec'),
        !           176:  * and (if `in' is NULL) functions to get and unget characters,
        !           177:  * getf and ungetf, respectively.
        !           178:  */
        !           179: RE *
        !           180: reparse(in, ec, getf, ungetf)
        !           181: char *in;
        !           182: int (*getf)(), (*ungetf)();
        !           183: {
        !           184:        RE *restk[NRE];
        !           185:        struct opstk {
        !           186:                char    o_op;
        !           187:                char    o_pri;
        !           188:        } opstk[NRE];
        !           189:        register struct opstk *osp;
        !           190:        register op;
        !           191:        register RE **rsp;
        !           192:        int concflg, op1, pri;
        !           193: 
        !           194:        if ((rein = in) != NULL) {
        !           195:                reinf = reget;
        !           196:                reunf = reunget;
        !           197:        } else {
        !           198:                reinf = getf;
        !           199:                reunf = ungetf;
        !           200:        }
        !           201:        reerror = NULL;
        !           202:        concflg = 0;
        !           203:        osp = opstk;
        !           204:        osp->o_op = STEND;
        !           205:        osp->o_pri = repri[STEND];
        !           206:        rsp = restk;
        !           207:        *rsp++ = NULL;
        !           208: 
        !           209:        for (;;) {
        !           210:                if (termop(op = relex(ec))) {
        !           211:                        if ((*rsp++ = renode(op, relval.u_cptr, NULL)) == NULL)
        !           212:                                return (NULL);
        !           213:                        if (rsp >= &restk[NRE-1]) {
        !           214:                                reerror = reoflo;
        !           215:                                return (NULL);
        !           216:                        }
        !           217:                        if (!concflg) {
        !           218:                                concflg++;
        !           219:                                continue;
        !           220:                        } else
        !           221:                                op = CONC;
        !           222:                } else if (op == OR) {
        !           223:                        if (!concflg) {
        !           224:                                reerror = resyn;
        !           225:                                return (NULL);
        !           226:                        }
        !           227:                        concflg = 0;
        !           228:                } else if (op==CLOS || op==NECLOS || op==ZORO) {
        !           229:                        if (!concflg) {
        !           230:                                reerror = resyn;
        !           231:                                return (NULL);
        !           232:                        }
        !           233:                } else if (op == LPAR) {
        !           234:                        if (concflg) {
        !           235:                                (++osp)->o_op = CONC;
        !           236:                                osp->o_pri = repri[CONC];
        !           237:                                concflg = 0;
        !           238:                        }
        !           239:                }
        !           240:                pri = repri[op];
        !           241:                for (;;) {
        !           242:                        if (reerror != NULL)
        !           243:                                return (NULL);
        !           244:                        if (pri>osp->o_pri || (op==CONC && osp->o_op==CONC)) {
        !           245:                                if (op == LPAR)
        !           246:                                        pri = repri[RPAR];
        !           247:                                if (osp >= &opstk[NRE-1]) {
        !           248:                                        reerror = reoflo;
        !           249:                                        return (NULL);
        !           250:                                }
        !           251:                                (++osp)->o_op = op;
        !           252:                                osp->o_pri = pri;
        !           253:                                if (!postop(op))
        !           254:                                        break;
        !           255:                                else
        !           256:                                        pri = repri[REEND];
        !           257:                        }
        !           258:                        switch (op1 = (osp--)->o_op) {
        !           259:                        case STEND:
        !           260:                                if (op == REEND)
        !           261:                                        return (*--rsp);
        !           262:                                osp++;
        !           263:                                break;
        !           264: 
        !           265:                        case LPAR:
        !           266:                                if (op != RPAR) {
        !           267:                                        reerror = "Unbalanced parentheses";
        !           268:                                        return (NULL);
        !           269:                                }
        !           270:                                break;
        !           271: 
        !           272:                        default:
        !           273:                                rsp = rebuild(rsp, op1);
        !           274:                                continue;
        !           275:                        }
        !           276:                        break;
        !           277:                }
        !           278:        }
        !           279: }
        !           280: 
        !           281: 
        !           282: static RE **
        !           283: rebuild(rsp, op)
        !           284: register RE **rsp;
        !           285: {
        !           286:        register RE *left, *right;
        !           287: 
        !           288:        switch (op) {
        !           289:        case OR:
        !           290:                right = *--rsp;
        !           291:                left = *--rsp;
        !           292:                break;
        !           293: 
        !           294:        case CLOS:
        !           295:        case NECLOS:
        !           296:        case ZORO:
        !           297:                left = *--rsp;
        !           298:                right = NULL;
        !           299:                break;
        !           300: 
        !           301:        case CONC:
        !           302:                right = *--rsp;
        !           303:                left = *--rsp;
        !           304:                if (left->r_next == NULL)
        !           305:                        left->r_next = right;
        !           306:                else {
        !           307:                        for (; left->r_next->r_next!=NULL; left = left->r_next)
        !           308:                                ;
        !           309:                        left->r_next->r_next = right;
        !           310:                }
        !           311:                return (++rsp);
        !           312: 
        !           313:        default:
        !           314:                reerror = "RE botch in rebuild";
        !           315:        }
        !           316:        *rsp++ = renode(op, left, right);
        !           317:        return (rsp);
        !           318: }
        !           319: 
        !           320: /*
        !           321:  * Build regular expression node.
        !           322:  */
        !           323: static RE *
        !           324: renode(op, left, right)
        !           325: RE *left, *right;
        !           326: {
        !           327:        register RE *rep;
        !           328: 
        !           329:        if ((rep = (RE *)malloc(sizeof (RE))) == NULL) {
        !           330:                reerror = nospace;
        !           331:                return (NULL);
        !           332:        }
        !           333:        rep->r_next = (RE*)NULL;
        !           334:        rep->r_op = op;
        !           335:        rep->r_left.u_re = left;
        !           336:        rep->r_right.u_re = right;
        !           337:        return (rep);
        !           338: }
        !           339: 
        !           340: static char    *sb;            /* string beginning */
        !           341: 
        !           342: /*
        !           343:  * User-callable driver for regular expression
        !           344:  * execution.  Called with regular expression code and
        !           345:  * text string.
        !           346:  */
        !           347: reinterp(rep, s)
        !           348: RE *rep;
        !           349: register char *s;
        !           350: {
        !           351:        sb = s;
        !           352:        if (rep!=NULL && rep->r_op==BOL)
        !           353:                return(e_exec(rep, s) != NULL);
        !           354:        for (; *s!='\0'; s++)
        !           355:                if (e_exec(rep, s) != NULL)
        !           356:                        return (1);
        !           357:        return (0);
        !           358: }
        !           359: 
        !           360: /*
        !           361:  * Internal regular expression
        !           362:  * execution routines
        !           363:  */
        !           364: static char *
        !           365: e_exec(rep, s)
        !           366: register RE *rep;
        !           367: register char *s;
        !           368: {
        !           369:        register c;
        !           370:        char *ss, *es;
        !           371: 
        !           372:        for ( ; rep!=NULL; rep = rep->r_next)
        !           373:                switch (rep->r_op) {
        !           374:                case BOL:
        !           375:                        if (s != sb)
        !           376:                                return (NULL);
        !           377:                        break;
        !           378: 
        !           379:                case EOL:
        !           380:                        if (*s != '\0')
        !           381:                                return (NULL);
        !           382:                        break;
        !           383: 
        !           384:                case ANY:
        !           385:                        if (*s++ == '\0')
        !           386:                                return (NULL);
        !           387:                        break;
        !           388: 
        !           389:                case CONC:
        !           390:                        if (*s++ != rep->r_left.u_ival)
        !           391:                                return (NULL);
        !           392:                        break;
        !           393: 
        !           394:                case DCONC:
        !           395:                        if (islower(rep->r_left.u_ival)) {
        !           396:                                if (isupper(c = *s++))
        !           397:                                        c = tolower(c);
        !           398:                                if (c != rep->r_left.u_ival)
        !           399:                                        return (NULL);
        !           400:                        } else
        !           401:                                if (*s++ != rep->r_left.u_ival)
        !           402:                                        return (NULL);
        !           403:                        break;
        !           404: 
        !           405:                case CCLASS:
        !           406:                        c = *s++;
        !           407:                        if ((rep->r_left.u_cptr[c/NBPC] & (1<<(c%NBPC))) == 0)
        !           408:                                return (NULL);
        !           409:                        break;
        !           410: 
        !           411:                case DCCLASS:
        !           412:                        if ((c = *s++)>='A' && c<='Z')
        !           413:                                c |= 'a'-'A';
        !           414:                        if ((rep->r_left.u_cptr[c/NBPC] & (1<<(c%NBPC))) == 0)
        !           415:                                return (NULL);
        !           416:                        break;
        !           417: 
        !           418:                case OR:
        !           419:                        ss = s;
        !           420:                        if ((s = e_exec(rep->r_left.u_re, s)) == NULL)
        !           421:                                if ((s = e_exec(rep->r_right.u_re, ss))==NULL)
        !           422:                                        return (NULL);
        !           423:                        break;
        !           424: 
        !           425:                case CLOS:
        !           426:                        ss = s;
        !           427:                        while ((es = e_exec(rep->r_left.u_re, s)) != NULL)
        !           428:                                s = es;
        !           429:                        while (s >= ss)
        !           430:                                if ((es = e_exec(rep->r_next, s--))!=NULL)
        !           431:                                        return(es);
        !           432:                        return (NULL);
        !           433: 
        !           434:                case NECLOS:
        !           435:                        ss = s;
        !           436:                        while ((es = e_exec(rep->r_left.u_re, s)) != NULL)
        !           437:                                s = es;
        !           438:                        while (s > ss)
        !           439:                                if ((es = e_exec(rep->r_next, s--))!=NULL)
        !           440:                                        return (es);
        !           441:                        return (NULL);
        !           442: 
        !           443:                case ZORO:
        !           444:                        ss = s;
        !           445:                        if ((es = e_exec(rep->r_left.u_re, s)) != NULL)
        !           446:                                s = es;
        !           447:                        while (s >= ss)
        !           448:                                if ((es = e_exec(rep->r_next, s--))!=NULL)
        !           449:                                        return (es);
        !           450:                        return (NULL);
        !           451: 
        !           452:                default:
        !           453:                        fprintf(stderr, "Regular expression botch\n");
        !           454:                        exit(2);
        !           455:                }
        !           456:        return (s);
        !           457: }
        !           458: 
        !           459: /*
        !           460:  * Default functions to get and unget
        !           461:  * characters from the regular expression.
        !           462:  */
        !           463: static
        !           464: reget()
        !           465: {
        !           466:        return (*rein++);
        !           467: }
        !           468: 
        !           469: static
        !           470: reunget(c)
        !           471: {
        !           472:        --rein;
        !           473: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.