[BACK]Return to expr.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / m4

Annotation of src/usr.bin/m4/expr.c, Revision 1.1

1.1     ! deraadt     1: /*     $NetBSD: expr.c,v 1.7 1995/09/28 05:37:31 tls Exp $     */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 1989, 1993
        !             5:  *     The Regents of the University of California.  All rights reserved.
        !             6:  *
        !             7:  * This code is derived from software contributed to Berkeley by
        !             8:  * Ozan Yigit at York University.
        !             9:  *
        !            10:  * Redistribution and use in source and binary forms, with or without
        !            11:  * modification, are permitted provided that the following conditions
        !            12:  * are met:
        !            13:  * 1. Redistributions of source code must retain the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer.
        !            15:  * 2. Redistributions in binary form must reproduce the above copyright
        !            16:  *    notice, this list of conditions and the following disclaimer in the
        !            17:  *    documentation and/or other materials provided with the distribution.
        !            18:  * 3. All advertising materials mentioning features or use of this software
        !            19:  *    must display the following acknowledgement:
        !            20:  *     This product includes software developed by the University of
        !            21:  *     California, Berkeley and its contributors.
        !            22:  * 4. Neither the name of the University nor the names of its contributors
        !            23:  *    may be used to endorse or promote products derived from this software
        !            24:  *    without specific prior written permission.
        !            25:  *
        !            26:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            27:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            28:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            29:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            30:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            31:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            32:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            33:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            34:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            35:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            36:  * SUCH DAMAGE.
        !            37:  */
        !            38:
        !            39: #ifndef lint
        !            40: #if 0
        !            41: static char sccsid[] = "@(#)expr.c     8.2 (Berkeley) 4/29/95";
        !            42: #else
        !            43: static char rcsid[] = "$NetBSD: expr.c,v 1.7 1995/09/28 05:37:31 tls Exp $";
        !            44: #endif
        !            45: #endif /* not lint */
        !            46:
        !            47: #include <sys/cdefs.h>
        !            48: #include <stdio.h>
        !            49:
        !            50: /*
        !            51:  *      expression evaluator: performs a standard recursive
        !            52:  *      descent parse to evaluate any expression permissible
        !            53:  *      within the following grammar:
        !            54:  *
        !            55:  *      expr    :       query EOS
        !            56:  *      query   :       lor
        !            57:  *              |       lor "?" query ":" query
        !            58:  *      lor     :       land { "||" land }
        !            59:  *      land    :       not { "&&" not }
        !            60:  *     not     :       eqrel
        !            61:  *             |       '!' not
        !            62:  *      eqrel   :       shift { eqrelop shift }
        !            63:  *      shift   :       primary { shop primary }
        !            64:  *      primary :       term { addop term }
        !            65:  *      term    :       exp { mulop exp }
        !            66:  *     exp     :       unary { expop unary }
        !            67:  *      unary   :       factor
        !            68:  *              |       unop unary
        !            69:  *      factor  :       constant
        !            70:  *              |       "(" query ")"
        !            71:  *      constant:       num
        !            72:  *              |       "'" CHAR "'"
        !            73:  *      num     :       DIGIT
        !            74:  *              |       DIGIT num
        !            75:  *      shop    :       "<<"
        !            76:  *              |       ">>"
        !            77:  *      eqrel   :       "="
        !            78:  *              |       "=="
        !            79:  *              |       "!="
        !            80:  *             |       "<"
        !            81:  *              |       ">"
        !            82:  *              |       "<="
        !            83:  *              |       ">="
        !            84:  *
        !            85:  *
        !            86:  *      This expression evaluator is lifted from a public-domain
        !            87:  *      C Pre-Processor included with the DECUS C Compiler distribution.
        !            88:  *      It is hacked somewhat to be suitable for m4.
        !            89:  *
        !            90:  *      Originally by:  Mike Lutz
        !            91:  *                      Bob Harper
        !            92:  */
        !            93:
        !            94: #define TRUE    1
        !            95: #define FALSE   0
        !            96: #define EOS     (char) 0
        !            97: #define EQL     0
        !            98: #define NEQ     1
        !            99: #define LSS     2
        !           100: #define LEQ     3
        !           101: #define GTR     4
        !           102: #define GEQ     5
        !           103: #define OCTAL   8
        !           104: #define DECIMAL 10
        !           105:
        !           106: static char *nxtch;                   /* Parser scan pointer */
        !           107:
        !           108: static int query __P((void));
        !           109: static int lor __P((void));
        !           110: static int land __P((void));
        !           111: static int not __P((void));
        !           112: static int eqrel __P((void));
        !           113: static int shift __P((void));
        !           114: static int primary __P((void));
        !           115: static int term __P((void));
        !           116: static int exp __P((void));
        !           117: static int unary __P((void));
        !           118: static int factor __P((void));
        !           119: static int constant __P((void));
        !           120: static int num __P((void));
        !           121: static int geteqrel __P((void));
        !           122: static int skipws __P((void));
        !           123: static void experr __P((char *));
        !           124:
        !           125: /*
        !           126:  * For longjmp
        !           127:  */
        !           128: #include <setjmp.h>
        !           129: static jmp_buf expjump;
        !           130:
        !           131: /*
        !           132:  * macros:
        !           133:  *      ungetch - Put back the last character examined.
        !           134:  *      getch   - return the next character from expr string.
        !           135:  */
        !           136: #define ungetch()       nxtch--
        !           137: #define getch()         *nxtch++
        !           138:
        !           139: int
        !           140: expr(expbuf)
        !           141: char *expbuf;
        !           142: {
        !           143:        register int rval;
        !           144:
        !           145:        nxtch = expbuf;
        !           146:        if (setjmp(expjump) != 0)
        !           147:                return FALSE;
        !           148:
        !           149:        rval = query();
        !           150:        if (skipws() == EOS)
        !           151:                return rval;
        !           152:
        !           153:        printf("m4: ill-formed expression.\n");
        !           154:        return FALSE;
        !           155: }
        !           156:
        !           157: /*
        !           158:  * query : lor | lor '?' query ':' query
        !           159:  */
        !           160: static int
        !           161: query()
        !           162: {
        !           163:        register int bool, true_val, false_val;
        !           164:
        !           165:        bool = lor();
        !           166:        if (skipws() != '?') {
        !           167:                ungetch();
        !           168:                return bool;
        !           169:        }
        !           170:
        !           171:        true_val = query();
        !           172:        if (skipws() != ':')
        !           173:                experr("bad query");
        !           174:
        !           175:        false_val = query();
        !           176:        return bool ? true_val : false_val;
        !           177: }
        !           178:
        !           179: /*
        !           180:  * lor : land { '||' land }
        !           181:  */
        !           182: static int
        !           183: lor()
        !           184: {
        !           185:        register int c, vl, vr;
        !           186:
        !           187:        vl = land();
        !           188:        while ((c = skipws()) == '|') {
        !           189:                if (getch() != '|')
        !           190:                        ungetch();
        !           191:                vr = land();
        !           192:                vl = vl || vr;
        !           193:        }
        !           194:
        !           195:        ungetch();
        !           196:        return vl;
        !           197: }
        !           198:
        !           199: /*
        !           200:  * land : not { '&&' not }
        !           201:  */
        !           202: static int
        !           203: land()
        !           204: {
        !           205:        register int c, vl, vr;
        !           206:
        !           207:        vl = not();
        !           208:        while ((c = skipws()) == '&') {
        !           209:                if (getch() != '&')
        !           210:                        ungetch();
        !           211:                vr = not();
        !           212:                vl = vl && vr;
        !           213:        }
        !           214:
        !           215:        ungetch();
        !           216:        return vl;
        !           217: }
        !           218:
        !           219: /*
        !           220:  * not : eqrel | '!' not
        !           221:  */
        !           222: static int
        !           223: not()
        !           224: {
        !           225:        register int val, c;
        !           226:
        !           227:        if ((c = skipws()) == '!' && getch() != '=') {
        !           228:                ungetch();
        !           229:                val = not();
        !           230:                return !val;
        !           231:        }
        !           232:
        !           233:        if (c == '!')
        !           234:                ungetch();
        !           235:        ungetch();
        !           236:        return eqrel();
        !           237: }
        !           238:
        !           239: /*
        !           240:  * eqrel : shift { eqrelop shift }
        !           241:  */
        !           242: static int
        !           243: eqrel()
        !           244: {
        !           245:        register int vl, vr, eqrel;
        !           246:
        !           247:        vl = shift();
        !           248:        while ((eqrel = geteqrel()) != -1) {
        !           249:                vr = shift();
        !           250:
        !           251:                switch (eqrel) {
        !           252:
        !           253:                case EQL:
        !           254:                        vl = (vl == vr);
        !           255:                        break;
        !           256:                case NEQ:
        !           257:                        vl = (vl != vr);
        !           258:                        break;
        !           259:
        !           260:                case LEQ:
        !           261:                        vl = (vl <= vr);
        !           262:                        break;
        !           263:                case LSS:
        !           264:                        vl = (vl < vr);
        !           265:                        break;
        !           266:                case GTR:
        !           267:                        vl = (vl > vr);
        !           268:                        break;
        !           269:                case GEQ:
        !           270:                        vl = (vl >= vr);
        !           271:                        break;
        !           272:                }
        !           273:        }
        !           274:        return vl;
        !           275: }
        !           276:
        !           277: /*
        !           278:  * shift : primary { shop primary }
        !           279:  */
        !           280: static int
        !           281: shift()
        !           282: {
        !           283:        register int vl, vr, c;
        !           284:
        !           285:        vl = primary();
        !           286:        while (((c = skipws()) == '<' || c == '>') && getch() == c) {
        !           287:                vr = primary();
        !           288:
        !           289:                if (c == '<')
        !           290:                        vl <<= vr;
        !           291:                else
        !           292:                        vl >>= vr;
        !           293:        }
        !           294:
        !           295:        if (c == '<' || c == '>')
        !           296:                ungetch();
        !           297:        ungetch();
        !           298:        return vl;
        !           299: }
        !           300:
        !           301: /*
        !           302:  * primary : term { addop term }
        !           303:  */
        !           304: static int
        !           305: primary()
        !           306: {
        !           307:        register int c, vl, vr;
        !           308:
        !           309:        vl = term();
        !           310:        while ((c = skipws()) == '+' || c == '-') {
        !           311:                vr = term();
        !           312:
        !           313:                if (c == '+')
        !           314:                        vl += vr;
        !           315:                else
        !           316:                        vl -= vr;
        !           317:        }
        !           318:
        !           319:        ungetch();
        !           320:        return vl;
        !           321: }
        !           322:
        !           323: /*
        !           324:  * <term> := <exp> { <mulop> <exp> }
        !           325:  */
        !           326: static int
        !           327: term()
        !           328: {
        !           329:        register int c, vl, vr;
        !           330:
        !           331:        vl = exp();
        !           332:        while ((c = skipws()) == '*' || c == '/' || c == '%') {
        !           333:                vr = exp();
        !           334:
        !           335:                switch (c) {
        !           336:                case '*':
        !           337:                        vl *= vr;
        !           338:                        break;
        !           339:                case '/':
        !           340:                        vl /= vr;
        !           341:                        break;
        !           342:                case '%':
        !           343:                        vl %= vr;
        !           344:                        break;
        !           345:                }
        !           346:        }
        !           347:        ungetch();
        !           348:        return vl;
        !           349: }
        !           350:
        !           351: /*
        !           352:  * <term> := <unary> { <expop> <unary> }
        !           353:  */
        !           354: static int
        !           355: exp()
        !           356: {
        !           357:        register c, vl, vr, n;
        !           358:
        !           359:        vl = unary();
        !           360:        switch (c = skipws()) {
        !           361:
        !           362:        case '*':
        !           363:                if (getch() != '*') {
        !           364:                        ungetch();
        !           365:                        break;
        !           366:                }
        !           367:
        !           368:        case '^':
        !           369:                vr = exp();
        !           370:                n = 1;
        !           371:                while (vr-- > 0)
        !           372:                        n *= vl;
        !           373:                return n;
        !           374:        }
        !           375:
        !           376:        ungetch();
        !           377:        return vl;
        !           378: }
        !           379:
        !           380: /*
        !           381:  * unary : factor | unop unary
        !           382:  */
        !           383: static int
        !           384: unary()
        !           385: {
        !           386:        register int val, c;
        !           387:
        !           388:        if ((c = skipws()) == '+' || c == '-' || c == '~') {
        !           389:                val = unary();
        !           390:
        !           391:                switch (c) {
        !           392:                case '+':
        !           393:                        return val;
        !           394:                case '-':
        !           395:                        return -val;
        !           396:                case '~':
        !           397:                        return ~val;
        !           398:                }
        !           399:        }
        !           400:
        !           401:        ungetch();
        !           402:        return factor();
        !           403: }
        !           404:
        !           405: /*
        !           406:  * factor : constant | '(' query ')'
        !           407:  */
        !           408: static int
        !           409: factor()
        !           410: {
        !           411:        register int val;
        !           412:
        !           413:        if (skipws() == '(') {
        !           414:                val = query();
        !           415:                if (skipws() != ')')
        !           416:                        experr("bad factor");
        !           417:                return val;
        !           418:        }
        !           419:
        !           420:        ungetch();
        !           421:        return constant();
        !           422: }
        !           423:
        !           424: /*
        !           425:  * constant: num | 'char'
        !           426:  * Note: constant() handles multi-byte constants
        !           427:  */
        !           428: static int
        !           429: constant()
        !           430: {
        !           431:        register int i;
        !           432:        register int value;
        !           433:        register char c;
        !           434:        int v[sizeof(int)];
        !           435:
        !           436:        if (skipws() != '\'') {
        !           437:                ungetch();
        !           438:                return num();
        !           439:        }
        !           440:        for (i = 0; i < sizeof(int); i++) {
        !           441:                if ((c = getch()) == '\'') {
        !           442:                        ungetch();
        !           443:                        break;
        !           444:                }
        !           445:                if (c == '\\') {
        !           446:                        switch (c = getch()) {
        !           447:                        case '0':
        !           448:                        case '1':
        !           449:                        case '2':
        !           450:                        case '3':
        !           451:                        case '4':
        !           452:                        case '5':
        !           453:                        case '6':
        !           454:                        case '7':
        !           455:                                ungetch();
        !           456:                                c = num();
        !           457:                                break;
        !           458:                        case 'n':
        !           459:                                c = 012;
        !           460:                                break;
        !           461:                        case 'r':
        !           462:                                c = 015;
        !           463:                                break;
        !           464:                        case 't':
        !           465:                                c = 011;
        !           466:                                break;
        !           467:                        case 'b':
        !           468:                                c = 010;
        !           469:                                break;
        !           470:                        case 'f':
        !           471:                                c = 014;
        !           472:                                break;
        !           473:                        }
        !           474:                }
        !           475:                v[i] = c;
        !           476:        }
        !           477:        if (i == 0 || getch() != '\'')
        !           478:                experr("illegal character constant");
        !           479:        for (value = 0; --i >= 0;) {
        !           480:                value <<= 8;
        !           481:                value += v[i];
        !           482:        }
        !           483:        return value;
        !           484: }
        !           485:
        !           486: /*
        !           487:  * num : digit | num digit
        !           488:  */
        !           489: static int
        !           490: num()
        !           491: {
        !           492:        register int rval, c, base;
        !           493:        int ndig;
        !           494:
        !           495:        base = ((c = skipws()) == '0') ? OCTAL : DECIMAL;
        !           496:        rval = 0;
        !           497:        ndig = 0;
        !           498:        while (c >= '0' && c <= (base == OCTAL ? '7' : '9')) {
        !           499:                rval *= base;
        !           500:                rval += (c - '0');
        !           501:                c = getch();
        !           502:                ndig++;
        !           503:        }
        !           504:        ungetch();
        !           505:
        !           506:        if (ndig == 0)
        !           507:                experr("bad constant");
        !           508:
        !           509:        return rval;
        !           510:
        !           511: }
        !           512:
        !           513: /*
        !           514:  * eqrel : '=' | '==' | '!=' | '<' | '>' | '<=' | '>='
        !           515:  */
        !           516: static int
        !           517: geteqrel()
        !           518: {
        !           519:        register int c1, c2;
        !           520:
        !           521:        c1 = skipws();
        !           522:        c2 = getch();
        !           523:
        !           524:        switch (c1) {
        !           525:
        !           526:        case '=':
        !           527:                if (c2 != '=')
        !           528:                        ungetch();
        !           529:                return EQL;
        !           530:
        !           531:        case '!':
        !           532:                if (c2 == '=')
        !           533:                        return NEQ;
        !           534:                ungetch();
        !           535:                ungetch();
        !           536:                return -1;
        !           537:
        !           538:        case '<':
        !           539:                if (c2 == '=')
        !           540:                        return LEQ;
        !           541:                ungetch();
        !           542:                return LSS;
        !           543:
        !           544:        case '>':
        !           545:                if (c2 == '=')
        !           546:                        return GEQ;
        !           547:                ungetch();
        !           548:                return GTR;
        !           549:
        !           550:        default:
        !           551:                ungetch();
        !           552:                ungetch();
        !           553:                return -1;
        !           554:        }
        !           555: }
        !           556:
        !           557: /*
        !           558:  * Skip over any white space and return terminating char.
        !           559:  */
        !           560: static int
        !           561: skipws()
        !           562: {
        !           563:        register char c;
        !           564:
        !           565:        while ((c = getch()) <= ' ' && c > EOS)
        !           566:                ;
        !           567:        return c;
        !           568: }
        !           569:
        !           570: /*
        !           571:  * resets environment to eval(), prints an error
        !           572:  * and forces eval to return FALSE.
        !           573:  */
        !           574: static void
        !           575: experr(msg)
        !           576: char *msg;
        !           577: {
        !           578:        printf("m4: %s in expr.\n", msg);
        !           579:        longjmp(expjump, -1);
        !           580: }