Annotation of researchv10dc/cmd/worm/scsi/tcl/tclExpr.c, revision 1.1

1.1     ! root        1: /* 
        !             2:  * tclExpr.c --
        !             3:  *
        !             4:  *     This file contains the code to evaluate expressions for
        !             5:  *     Tcl.
        !             6:  *
        !             7:  * Copyright 1987 Regents of the University of California
        !             8:  * Permission to use, copy, modify, and distribute this
        !             9:  * software and its documentation for any purpose and without
        !            10:  * fee is hereby granted, provided that the above copyright
        !            11:  * notice appear in all copies.  The University of California
        !            12:  * makes no representations about the suitability of this
        !            13:  * software for any purpose.  It is provided "as is" without
        !            14:  * express or implied warranty.
        !            15:  */
        !            16: 
        !            17: #ifndef lint
        !            18: static char rcsid[] = "$Header: /sprite/src/lib/tcl/RCS/tclExpr.c,v 1.13 90/03/22 15:24:59 ouster Exp $ SPRITE (Berkeley)";
        !            19: #pragma ref rcsid
        !            20: #endif not lint
        !            21: 
        !            22: #define        _POSIX_SOURCE
        !            23: 
        !            24: #include <stdio.h>
        !            25: #include <ctype.h>
        !            26: #include "tcl.h"
        !            27: #include "tclInt.h"
        !            28: 
        !            29: /*
        !            30:  * The data structure below describes the state of parsing an expression.
        !            31:  * It's passed among the routines in this module.
        !            32:  */
        !            33: 
        !            34: typedef struct {
        !            35:     Tcl_Interp *interp;                /* Intepreter to use for command execution
        !            36:                                 * and variable lookup. */
        !            37:     char *originalExpr;                /* The entire expression, as originally
        !            38:                                 * passed to Tcl_Expr. */
        !            39:     char *expr;                        /* Position to the next character to be
        !            40:                                 * scanned from the expression string. */
        !            41:     int token;                 /* Type of the last token to be parsed from
        !            42:                                 * expr.  See below for definitions.
        !            43:                                 * Corresponds to the characters just
        !            44:                                 * before expr. */
        !            45:     int number;                        /* If token is NUMBER, gives value of
        !            46:                                 * the number. */
        !            47: } ExprInfo;
        !            48: 
        !            49: /*
        !            50:  * The token types are defined below.  In addition, there is a table
        !            51:  * associating a precedence with each operator.  The order of types
        !            52:  * is important.  Consult the code before changing it.
        !            53:  */
        !            54: 
        !            55: #define NUMBER         0
        !            56: #define OPEN_PAREN     1
        !            57: #define CLOSE_PAREN    2
        !            58: #define END            3
        !            59: #define UNKNOWN                4
        !            60: 
        !            61: /*
        !            62:  * Binary operators:
        !            63:  */
        !            64: 
        !            65: #define MULT           8
        !            66: #define DIVIDE         9
        !            67: #define MOD            10
        !            68: #define PLUS           11
        !            69: #define MINUS          12
        !            70: #define LEFT_SHIFT     13
        !            71: #define RIGHT_SHIFT    14
        !            72: #define LESS           15
        !            73: #define GREATER                16
        !            74: #define LEQ            17
        !            75: #define GEQ            18
        !            76: #define EQUAL          19
        !            77: #define NEQ            20
        !            78: #define BIT_AND                21
        !            79: #define BIT_XOR                22
        !            80: #define BIT_OR         23
        !            81: #define AND            24
        !            82: #define OR             25
        !            83: #define QUESTY         26
        !            84: #define COLON          27
        !            85: 
        !            86: /*
        !            87:  * Unary operators:
        !            88:  */
        !            89: 
        !            90: #define        UNARY_MINUS     28
        !            91: #define NOT            29
        !            92: #define BIT_NOT                30
        !            93: 
        !            94: /*
        !            95:  * Precedence table.  The values for non-operator token types are ignored.
        !            96:  */
        !            97: 
        !            98: int precTable[] = {
        !            99:     0, 0, 0, 0, 0, 0, 0, 0,
        !           100:     11, 11, 11,                                /* MULT, DIVIDE, MOD */
        !           101:     10, 10,                            /* PLUS, MINUS */
        !           102:     9, 9,                              /* LEFT_SHIFT, RIGHT_SHIFT */
        !           103:     8, 8, 8, 8,                                /* LESS, GREATER, LEQ, GEQ */
        !           104:     7, 7,                              /* EQUAL, NEQ */
        !           105:     6,                                 /* BIT_AND */
        !           106:     5,                                 /* BIT_XOR */
        !           107:     4,                                 /* BIT_OR */
        !           108:     3,                                 /* AND */
        !           109:     2,                                 /* OR */
        !           110:     1, 1,                              /* QUESTY, COLON */
        !           111:     12, 12, 12                         /* UNARY_MINUS, NOT, BIT_NOT */
        !           112: };
        !           113: 
        !           114: /*
        !           115:  *----------------------------------------------------------------------
        !           116:  *
        !           117:  * ExprGetNum --
        !           118:  *
        !           119:  *     Parse off a number from a string.
        !           120:  *
        !           121:  * Results:
        !           122:  *     The return value is the integer value corresponding to the
        !           123:  *     leading digits of string.  If termPtr isn't NULL, *termPtr
        !           124:  *     is filled in with the address of the character after the
        !           125:  *     last one that is part of the number.
        !           126:  *
        !           127:  * Side effects:
        !           128:  *     None.
        !           129:  *
        !           130:  *----------------------------------------------------------------------
        !           131:  */
        !           132: 
        !           133: int
        !           134: ExprGetNum(string, termPtr)
        !           135:     register char *string;             /* ASCII representation of number.
        !           136:                                         * If leading digit is "0" then read
        !           137:                                         * in base 8;  if "0x", then read in
        !           138:                                         * base 16. */
        !           139:     register char **termPtr;           /* If non-NULL, fill in with address
        !           140:                                         * of terminating character. */
        !           141: {
        !           142:     int result, sign;
        !           143:     register char c;
        !           144: 
        !           145:     c = *string;
        !           146:     result = 0;
        !           147:     if (c == '-') {
        !           148:        sign = -1;
        !           149:        string++; c = *string;
        !           150:     } else {
        !           151:        sign = 1;
        !           152:     }
        !           153:     if (c == '0') {
        !           154:        string++; c = *string;
        !           155:        if (c == 'x') {
        !           156:            while (1) {
        !           157:                string++; c = *string;
        !           158:                if ((c >= '0') && (c <= '9')) {
        !           159:                    result = (result << 4) + (c - '0');
        !           160:                } else if ((c >= 'a') && (c <= 'f')) {
        !           161:                    result = (result << 4) + 10 + (c - 'a');
        !           162:                } else if ((c >= 'A') && (c <= 'F')) {
        !           163:                    result = (result << 4) + 10 + (c - 'A');
        !           164:                } else {
        !           165:                    break;
        !           166:                }
        !           167:            }
        !           168:        } else {
        !           169:            while ((c >= '0') && (c <= '7')) {
        !           170:                result = (result << 3) + (c - '0');
        !           171:                string++;  c = *string;
        !           172:            }
        !           173:        }
        !           174:     } else {
        !           175:        while ((c >= '0') && (c <= '9')) {
        !           176:            result = (result*10) + (c - '0');
        !           177:            string++;  c = *string;
        !           178:        }
        !           179:     }
        !           180:     if (termPtr != NULL) {
        !           181:        *termPtr = string;
        !           182:     }
        !           183:     return result*sign;
        !           184: }
        !           185: 
        !           186: /*
        !           187:  *----------------------------------------------------------------------
        !           188:  *
        !           189:  * ExprLex --
        !           190:  *
        !           191:  *     Lexical analyzer for expression parser.
        !           192:  *
        !           193:  * Results:
        !           194:  *     TCL_OK is returned unless an error occurred while doing lexical
        !           195:  *     analysis or executing an embedded command.  In that case a
        !           196:  *     standard Tcl error is returned, using interp->result to hold
        !           197:  *     an error message.  In the event of a successful return, the token
        !           198:  *     and (possibly) number fields in infoPtr are updated to refer to
        !           199:  *     the next symbol in the expression string, and the expr field is
        !           200:  *     advanced.
        !           201:  *
        !           202:  * Side effects:
        !           203:  *     None.
        !           204:  *
        !           205:  *----------------------------------------------------------------------
        !           206:  */
        !           207: 
        !           208: int
        !           209: ExprLex(interp, infoPtr)
        !           210:     Tcl_Interp *interp;                        /* Interpreter to use for error
        !           211:                                         * reporting. */
        !           212:     register ExprInfo *infoPtr;                /* Describes the state of the parse. */
        !           213: {
        !           214:     register char *p, c;
        !           215:     char *var, *term;
        !           216:     int result;
        !           217: 
        !           218:     /*
        !           219:      * The next token is either:
        !           220:      * (a)     a variable name (indicated by a $ sign plus a variable
        !           221:      *         name in the standard Tcl fashion);  lookup the value
        !           222:      *         of the variable and return its numeric equivalent as a
        !           223:      *         number.
        !           224:      * (b)     an embedded command (anything between '[' and ']').
        !           225:      *         Execute the command and convert its result to a number.
        !           226:      * (c)     a series of decimal digits.  Convert it to a number.
        !           227:      * (d)     space:  skip it.
        !           228:      * (d)     an operator.  See what kind it is.
        !           229:      */
        !           230: 
        !           231:     p = infoPtr->expr;
        !           232:     c = *p;
        !           233:     while (isspace(c)) {
        !           234:        p++;  c = *p;
        !           235:     }
        !           236:     infoPtr->expr = p+1;
        !           237:     switch (c) {
        !           238:        case '0':
        !           239:        case '1':
        !           240:        case '2':
        !           241:        case '3':
        !           242:        case '4':
        !           243:        case '5':
        !           244:        case '6':
        !           245:        case '7':
        !           246:        case '8':
        !           247:        case '9':
        !           248:            infoPtr->token = NUMBER;
        !           249:            infoPtr->number = ExprGetNum(p, &infoPtr->expr);
        !           250:            return TCL_OK;
        !           251: 
        !           252:        case '$':
        !           253:            infoPtr->token = NUMBER;
        !           254:            var = Tcl_ParseVar(infoPtr->interp, p, &infoPtr->expr);
        !           255:            if (var == NULL) {
        !           256:                return TCL_ERROR;
        !           257:            }
        !           258:            if (((Interp *) infoPtr->interp)->noEval) {
        !           259:                infoPtr->number = 0;
        !           260:                return TCL_OK;
        !           261:            }
        !           262:            infoPtr->number = ExprGetNum(var, &term);
        !           263:            if ((term == var) || (*term != 0)) {
        !           264:                c = *infoPtr->expr;
        !           265:                *infoPtr->expr = 0;
        !           266:                Tcl_Return(interp, (char *) NULL, TCL_STATIC);
        !           267:                sprintf(interp->result,
        !           268:                        "variable \"%.50s\" contained non-numeric value \"%.50s\"",
        !           269:                        p, var);
        !           270:                *infoPtr->expr = c;
        !           271:                return TCL_ERROR;
        !           272:            }
        !           273:            return TCL_OK;
        !           274: 
        !           275:        case '[':
        !           276:            infoPtr->token = NUMBER;
        !           277:            result = Tcl_Eval(infoPtr->interp, p+1, TCL_BRACKET_TERM,
        !           278:                    &infoPtr->expr);
        !           279:            if (result != TCL_OK) {
        !           280:                return result;
        !           281:            }
        !           282:            infoPtr->expr++;
        !           283:            if (((Interp *) infoPtr->interp)->noEval) {
        !           284:                infoPtr->number = 0;
        !           285:                Tcl_Return(interp, (char *) NULL, TCL_STATIC);
        !           286:                return TCL_OK;
        !           287:            }
        !           288:            infoPtr->number = ExprGetNum(interp->result, &term);
        !           289:            if ((term == interp->result) || (*term != 0)) {
        !           290:                char string[200];
        !           291:                infoPtr->expr[-1];
        !           292:                infoPtr->expr[-1] = 0;
        !           293:                sprintf(string, "command \"%.50s\" returned non-numeric result \"%.50s\"",
        !           294:                        p+1, interp->result);
        !           295:                infoPtr->expr[-1] = c;
        !           296:                Tcl_Return(interp, string, TCL_VOLATILE);
        !           297:                return TCL_ERROR;
        !           298:            }
        !           299:            Tcl_Return(interp, (char *) NULL, TCL_STATIC);
        !           300:            return TCL_OK;
        !           301: 
        !           302:        case '(':
        !           303:            infoPtr->token = OPEN_PAREN;
        !           304:            return TCL_OK;
        !           305: 
        !           306:        case ')':
        !           307:            infoPtr->token = CLOSE_PAREN;
        !           308:            return TCL_OK;
        !           309: 
        !           310:        case '*':
        !           311:            infoPtr->token = MULT;
        !           312:            return TCL_OK;
        !           313: 
        !           314:        case '/':
        !           315:            infoPtr->token = DIVIDE;
        !           316:            return TCL_OK;
        !           317: 
        !           318:        case '%':
        !           319:            infoPtr->token = MOD;
        !           320:            return TCL_OK;
        !           321: 
        !           322:        case '+':
        !           323:            infoPtr->token = PLUS;
        !           324:            return TCL_OK;
        !           325: 
        !           326:        case '-':
        !           327:            infoPtr->token = MINUS;
        !           328:            return TCL_OK;
        !           329: 
        !           330:        case '?':
        !           331:            infoPtr->token = QUESTY;
        !           332:            return TCL_OK;
        !           333: 
        !           334:        case ':':
        !           335:            infoPtr->token = COLON;
        !           336:            return TCL_OK;
        !           337: 
        !           338:        case '<':
        !           339:            switch (p[1]) {
        !           340:                case '<':
        !           341:                    infoPtr->expr = p+2;
        !           342:                    infoPtr->token = LEFT_SHIFT;
        !           343:                    break;
        !           344:                case '=':
        !           345:                    infoPtr->expr = p+2;
        !           346:                    infoPtr->token = LEQ;
        !           347:                    break;
        !           348:                default:
        !           349:                    infoPtr->token = LESS;
        !           350:                    break;
        !           351:            }
        !           352:            return TCL_OK;
        !           353: 
        !           354:        case '>':
        !           355:            switch (p[1]) {
        !           356:                case '>':
        !           357:                    infoPtr->expr = p+2;
        !           358:                    infoPtr->token = RIGHT_SHIFT;
        !           359:                    break;
        !           360:                case '=':
        !           361:                    infoPtr->expr = p+2;
        !           362:                    infoPtr->token = GEQ;
        !           363:                    break;
        !           364:                default:
        !           365:                    infoPtr->token = GREATER;
        !           366:                    break;
        !           367:            }
        !           368:            return TCL_OK;
        !           369: 
        !           370:        case '=':
        !           371:            if (p[1] == '=') {
        !           372:                infoPtr->expr = p+2;
        !           373:                infoPtr->token = EQUAL;
        !           374:            } else {
        !           375:                infoPtr->token = UNKNOWN;
        !           376:            }
        !           377:            return TCL_OK;
        !           378: 
        !           379:        case '!':
        !           380:            if (p[1] == '=') {
        !           381:                infoPtr->expr = p+2;
        !           382:                infoPtr->token = NEQ;
        !           383:            } else {
        !           384:                infoPtr->token = NOT;
        !           385:            }
        !           386:            return TCL_OK;
        !           387: 
        !           388:        case '&':
        !           389:            if (p[1] == '&') {
        !           390:                infoPtr->expr = p+2;
        !           391:                infoPtr->token = AND;
        !           392:            } else {
        !           393:                infoPtr->token = BIT_AND;
        !           394:            }
        !           395:            return TCL_OK;
        !           396: 
        !           397:        case '^':
        !           398:            infoPtr->token = BIT_XOR;
        !           399:            return TCL_OK;
        !           400: 
        !           401:        case '|':
        !           402:            if (p[1] == '|') {
        !           403:                infoPtr->expr = p+2;
        !           404:                infoPtr->token = OR;
        !           405:            } else {
        !           406:                infoPtr->token = BIT_OR;
        !           407:            }
        !           408:            return TCL_OK;
        !           409: 
        !           410:        case '~':
        !           411:            infoPtr->token = BIT_NOT;
        !           412:            return TCL_OK;
        !           413: 
        !           414:        case 0:
        !           415:            infoPtr->token = END;
        !           416:            infoPtr->expr = p;
        !           417:            return TCL_OK;
        !           418: 
        !           419:        default:
        !           420:            infoPtr->expr = p+1;
        !           421:            infoPtr->token = UNKNOWN;
        !           422:            return TCL_OK;
        !           423:     }
        !           424: }
        !           425: 
        !           426: /*
        !           427:  *----------------------------------------------------------------------
        !           428:  *
        !           429:  * ExprGetValue --
        !           430:  *
        !           431:  *     Parse a "value" from the remainder of the expression in infoPtr.
        !           432:  *
        !           433:  * Results:
        !           434:  *     Normally TCL_OK is returned.  The value of the parsed number is
        !           435:  *     returned in infoPtr->number.  If an error occurred, then
        !           436:  *     interp->result contains an error message and TCL_ERROR is returned.
        !           437:  *
        !           438:  * Side effects:
        !           439:  *     Information gets parsed from the remaining expression, and the
        !           440:  *     expr and token fields in infoPtr get updated.  Information is
        !           441:  *     parsed until either the end of the expression is reached (null
        !           442:  *     character or close paren), an error occurs, or a binary operator
        !           443:  *     is encountered with precedence <= prec.  In any of these cases,
        !           444:  *     infoPtr->token will be left pointing to the token AFTER the
        !           445:  *     expression.
        !           446:  *
        !           447:  *----------------------------------------------------------------------
        !           448:  */
        !           449: 
        !           450: int
        !           451: ExprGetValue(interp, infoPtr, prec)
        !           452:     Tcl_Interp *interp;                        /* Interpreter to use for error
        !           453:                                         * reporting. */
        !           454:     register ExprInfo *infoPtr;                /* Describes the state of the parse
        !           455:                                         * just before the value (i.e. ExprLex
        !           456:                                         * will be called to get first token
        !           457:                                         * of value). */
        !           458:     int prec;                          /* Treat any un-parenthesized operator
        !           459:                                         * with precedence <= this as the end
        !           460:                                         * of the expression. */
        !           461: {
        !           462:     Interp *iPtr = (Interp *) interp;
        !           463:     int result, operator, operand;
        !           464:     int gotOp;                         /* Non-zero means already lexed the
        !           465:                                         * operator (while picking up value
        !           466:                                         * for unary operator).  Don't lex
        !           467:                                         * again. */
        !           468: 
        !           469:     /*
        !           470:      * There are two phases to this procedure.  First, pick off an initial
        !           471:      * value.  Then, parse (binary operator, value) pairs until done.
        !           472:      */
        !           473: 
        !           474:     gotOp = 0;
        !           475:     result = ExprLex(interp, infoPtr);
        !           476:     if (result != TCL_OK) {
        !           477:        return result;
        !           478:     }
        !           479:     if (infoPtr->token == OPEN_PAREN) {
        !           480: 
        !           481:        /*
        !           482:         * Parenthesized sub-expression.
        !           483:         */
        !           484: 
        !           485:        result = ExprGetValue(interp, infoPtr, -1);
        !           486:        if (result != TCL_OK) {
        !           487:            return result;
        !           488:        }
        !           489:        if (infoPtr->token != CLOSE_PAREN) {
        !           490:            Tcl_Return(interp, (char *) NULL, TCL_STATIC);
        !           491:            sprintf(interp->result,
        !           492:                    "unmatched parentheses in expression \"%.50s\"",
        !           493:                    infoPtr->originalExpr);
        !           494:            return TCL_ERROR;
        !           495:        }
        !           496:     } else {
        !           497:        if (infoPtr->token == MINUS) {
        !           498:            infoPtr->token = UNARY_MINUS;
        !           499:        }
        !           500:        if (infoPtr->token >= UNARY_MINUS) {
        !           501: 
        !           502:            /*
        !           503:             * Process unary operators.
        !           504:             */
        !           505: 
        !           506:            operator = infoPtr->token;
        !           507:            result = ExprGetValue(interp, infoPtr, precTable[infoPtr->token]);
        !           508:            if (result != TCL_OK) {
        !           509:                return result;
        !           510:            }
        !           511:            switch (operator) {
        !           512:                case UNARY_MINUS:
        !           513:                    infoPtr->number = -infoPtr->number;
        !           514:                    break;
        !           515:                case NOT:
        !           516:                    infoPtr->number = !infoPtr->number;
        !           517:                    break;
        !           518:                case BIT_NOT:
        !           519:                    infoPtr->number = ~infoPtr->number;
        !           520:                    break;
        !           521:            }
        !           522:            gotOp = 1;
        !           523:        } else if (infoPtr->token != NUMBER) {
        !           524:            goto syntaxError;
        !           525:        }
        !           526:     }
        !           527: 
        !           528:     /*
        !           529:      * Got the first operand.  Now fetch (operator, operand) pairs.
        !           530:      */
        !           531: 
        !           532:     if (!gotOp) {
        !           533:        result = ExprLex(interp, infoPtr);
        !           534:        if (result != TCL_OK) {
        !           535:            return result;
        !           536:        }
        !           537:     }
        !           538:     while (1) {
        !           539:        operand = infoPtr->number;
        !           540:        operator = infoPtr->token;
        !           541:        if ((operator < MULT) || (operator >= UNARY_MINUS)) {
        !           542:            if ((operator == END) || (operator == CLOSE_PAREN)) {
        !           543:                return TCL_OK;
        !           544:            } else {
        !           545:                goto syntaxError;
        !           546:            }
        !           547:        }
        !           548:        if (precTable[operator] <= prec) {
        !           549:            return TCL_OK;
        !           550:        }
        !           551: 
        !           552:        /*
        !           553:         * If we're doing an AND or OR and the first operand already
        !           554:         * determines the result, don't execute anything in the
        !           555:         * second operand:  just parse.  Same style for ?: pairs.
        !           556:         */
        !           557: 
        !           558:        if (((operator == AND) && !operand)
        !           559:                || ((operator == OR) && operand)) {
        !           560:            iPtr->noEval++;
        !           561:            result = ExprGetValue(interp, infoPtr, precTable[operator]);
        !           562:            iPtr->noEval--;
        !           563:        } else if (operator == QUESTY) {
        !           564:            if (operand != 0) {
        !           565:                result = ExprGetValue(interp, infoPtr, precTable[operator]);
        !           566:                operand = infoPtr->number;
        !           567:                if (result != TCL_OK)
        !           568:                    return result;
        !           569:                if (infoPtr->token != COLON)
        !           570:                    goto syntaxError;
        !           571:                iPtr->noEval++;
        !           572:                result = ExprGetValue(interp, infoPtr, precTable[operator]);
        !           573:                iPtr->noEval--;
        !           574:            } else {
        !           575:                iPtr->noEval++;
        !           576:                result = ExprGetValue(interp, infoPtr, precTable[operator]);
        !           577:                iPtr->noEval--;
        !           578:                if (result != TCL_OK)
        !           579:                    return result;
        !           580:                if (infoPtr->token != COLON)
        !           581:                    goto syntaxError;
        !           582:                result = ExprGetValue(interp, infoPtr, precTable[operator]);
        !           583:                operand = infoPtr->number;
        !           584:            }
        !           585:            infoPtr->number = operand;
        !           586:        } else {
        !           587:            result = ExprGetValue(interp, infoPtr, precTable[operator]);
        !           588:        }
        !           589:        if (result != TCL_OK) {
        !           590:            return result;
        !           591:        }
        !           592:        if ((infoPtr->token < MULT) && (infoPtr->token != NUMBER)
        !           593:                && (infoPtr->token != END)
        !           594:                && (infoPtr->token != CLOSE_PAREN)) {
        !           595:            goto syntaxError;
        !           596:        }
        !           597:        switch (operator) {
        !           598:            case MULT:
        !           599:                infoPtr->number = operand * infoPtr->number;
        !           600:                break;
        !           601:            case DIVIDE:
        !           602:                if (infoPtr->number == 0) {
        !           603:                    Tcl_Return(interp, "divide by zero", TCL_STATIC);
        !           604:                    return TCL_ERROR;
        !           605:                }
        !           606:                infoPtr->number = operand / infoPtr->number;
        !           607:                break;
        !           608:            case MOD:
        !           609:                if (infoPtr->number == 0) {
        !           610:                    Tcl_Return(interp, "divide by zero", TCL_STATIC);
        !           611:                    return TCL_ERROR;
        !           612:                }
        !           613:                infoPtr->number = operand % infoPtr->number;
        !           614:                break;
        !           615:            case PLUS:
        !           616:                infoPtr->number = operand + infoPtr->number;
        !           617:                break;
        !           618:            case MINUS:
        !           619:                infoPtr->number = operand - infoPtr->number;
        !           620:                break;
        !           621:            case LEFT_SHIFT:
        !           622:                infoPtr->number = operand << infoPtr->number;
        !           623:                break;
        !           624:            case RIGHT_SHIFT:
        !           625:                infoPtr->number = operand >> infoPtr->number;
        !           626:                break;
        !           627:            case LESS:
        !           628:                infoPtr->number = operand < infoPtr->number;
        !           629:                break;
        !           630:            case GREATER:
        !           631:                infoPtr->number = operand > infoPtr->number;
        !           632:                break;
        !           633:            case LEQ:
        !           634:                infoPtr->number = operand <= infoPtr->number;
        !           635:                break;
        !           636:            case GEQ:
        !           637:                infoPtr->number = operand >= infoPtr->number;
        !           638:                break;
        !           639:            case EQUAL:
        !           640:                infoPtr->number = operand == infoPtr->number;
        !           641:                break;
        !           642:            case NEQ:
        !           643:                infoPtr->number = operand != infoPtr->number;
        !           644:                break;
        !           645:            case BIT_AND:
        !           646:                infoPtr->number = operand & infoPtr->number;
        !           647:                break;
        !           648:            case BIT_XOR:
        !           649:                infoPtr->number = operand ^ infoPtr->number;
        !           650:                break;
        !           651:            case BIT_OR:
        !           652:                infoPtr->number = operand | infoPtr->number;
        !           653:                break;
        !           654:            case AND:
        !           655:                infoPtr->number = operand && infoPtr->number;
        !           656:                break;
        !           657:            case OR:
        !           658:                infoPtr->number = operand || infoPtr->number;
        !           659:                break;
        !           660:        }
        !           661:     }
        !           662: 
        !           663:     syntaxError:
        !           664:     Tcl_Return(interp, (char *) NULL, TCL_STATIC);
        !           665:     sprintf(interp->result, "syntax error in expression \"%.50s\"",
        !           666:            infoPtr->originalExpr);
        !           667:     return TCL_ERROR;
        !           668: }
        !           669: 
        !           670: /*
        !           671:  *----------------------------------------------------------------------
        !           672:  *
        !           673:  * Tcl_Expr --
        !           674:  *
        !           675:  *     Parse and evaluate an expression.
        !           676:  *
        !           677:  * Results:
        !           678:  *     The return value is TCL_OK if the expression was correctly parsed;
        !           679:  *     if there was a syntax error or some other error during parsing,
        !           680:  *     then another Tcl return value is returned and Tcl_Result points
        !           681:  *     to an error message.  If all went well, *valuePtr is filled in
        !           682:  *     with the result corresponding to the expression string.
        !           683:  *
        !           684:  * Side effects:
        !           685:  *     None.
        !           686:  *
        !           687:  *----------------------------------------------------------------------
        !           688:  */
        !           689: 
        !           690: int
        !           691: Tcl_Expr(interp, string, valuePtr)
        !           692:     Tcl_Interp *interp;                /* Intepreter to use for variables etc. */
        !           693:     char *string;              /* Expression to evaluate. */
        !           694:     int *valuePtr;             /* Where to store result of evaluation. */
        !           695: {
        !           696:     ExprInfo info;
        !           697:     int result;
        !           698: 
        !           699:     info.interp = interp;
        !           700:     info.originalExpr = string;
        !           701:     info.expr = string;
        !           702:     result = ExprGetValue(interp, &info, -1);
        !           703:     if (result != TCL_OK) {
        !           704:        return result;
        !           705:     }
        !           706:     if (info.token != END) {
        !           707:        Tcl_Return(interp, (char *) NULL, TCL_STATIC);
        !           708:        sprintf(interp->result, "syntax error in expression \"%.50s\"", string);
        !           709:        return TCL_ERROR;
        !           710:     }
        !           711:     *valuePtr = info.number;
        !           712:     return TCL_OK;
        !           713: }

unix.superglobalmegacorp.com

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