Annotation of researchv10no/cmd/basic/bite/src/evalx.c, revision 1.1

1.1     ! root        1: /* Copyright Bell Telephone Laboratories Whippany, N.J.
        !             2: 
        !             3:  *     /////////////////////////////////////
        !             4:  *     /////////////////////////////////////
        !             5:  *     ////////////// evalx.c //////////////
        !             6:  *     /// J. P. Hawkins WH X4610 8C-001 ///
        !             7:  *     ///// Fri Aug 24 16:40:38 1979 //////
        !             8:  *     /////////////////////////////////////
        !             9:  *     /////////////////////////////////////
        !            10: 
        !            11:  *
        !            12:  * calling format:
        !            13:  *
        !            14:  *     double value;
        !            15:  *     double evalx();
        !            16:  *     value = evalx(expstr)
        !            17:  *
        !            18:  *     where:  dummy is now unused
        !            19:  *             expstr is the char string representing the expression
        !            20:  *                     to be evaluated. The string must be terminated
        !            21:  *                     by a character between values 0 -> 37(8).
        !            22:  *                     0 is the usual ascii string terminator. Values
        !            23:  *                     between 001(8) and 37(8) are keyword codes
        !            24:  *                     for secondary operations like "then" in an "if"
        !            25:  *                     statement or "to" in a "for" statement.
        !            26:  *
        !            27:  */
        !            28: /*   "@(#) evalx.c:  V 1.9  4/21/81" */
        !            29: /*
        !            30:  * MOD,J.P.Hawkins,31-JAN-81 detects strings and string vars. mixed in
        !            31:  *             numerical expressions as reject.
        !            32:  */
        !            33: #include       "bas.h"
        !            34: #define        STKSIZ  6       /* stack size */
        !            35: 
        !            36: int strflg;
        !            37: /*
        !            38: #define        skip00() {while(*expptr == ' ' || *expptr == '\t') *expptr++;}
        !            39: */
        !            40: #define        skip00()        {}      /* do nothing */
        !            41: extern int     stpflg;         /* stop flag for fatal error */
        !            42:        double  pow();
        !            43:        double  atof1();
        !            44:        double  mathcall();
        !            45: 
        !            46:        char    *eoexpr;        /* pointer to end of expression */
        !            47: /*
        !            48:  *
        !            49:  *
        !            50:  */
        !            51: double
        !            52: evalx(exps)
        !            53: char   exps[];         /* pointer to expression string */
        !            54: {
        !            55:        char    *expptr;        /* expression string pointer */
        !            56:        char    ostack[STKSIZ]; /* operator stack */
        !            57:        double  nstack[STKSIZ]; /* number stack         */
        !            58:        int     opflag;         /* set when operator encountered
        !            59:                                    cleared when variable or non-op
        !            60:                                     encountered. Used to deal with
        !            61:                                      unaries by forcing a 0.0 on the
        !            62:                                        number stack */
        !            63:        int     o, n;           /* indicies for ostack & nstack */
        !            64: 
        !            65:        char    field[80];      /* expression field */
        !            66:        int     type;           /* field type returned by class */
        !            67:        expptr = exps;  /* init expression string pointer */
        !            68:        o = n = STKSIZ; /* init operator and
        !            69:                            variable stack pointer */
        !            70:        opflag = 0;     /* init opflag */
        !            71: /*
        !            72:  *
        !            73:  * The only ways out of this loop are string terminator or
        !            74:  * expression terminator (null char)
        !            75:  * the codes 1 through 37(8) represent encoded keywords (defined in bed.c)
        !            76:  * those being:
        !            77:  * goto,go to,then,to,step,<=,=<,<,>=,=>,>, =, or <>
        !            78:  *
        !            79:  * This "while" loop is
        !            80:  * not indented so "all this stuff" fits across standard page
        !            81:  */
        !            82: while(!(*expptr >= '\0' && *expptr <= '\37'))
        !            83: {
        !            84:        if((type = class(&expptr, field)) < 0) /* get field and type */
        !            85:        {
        !            86:                error(inst.thing.linno, 8);     /* EXPR SYNTAX */
        !            87:                error(inst.thing.linno, 15);            /* FATAL ERROR */
        !            88:                stpflg = 1;
        !            89:                return(0.0);/* return zero on error */
        !            90:        }
        !            91: 
        !            92:        switch(type){
        !            93: #ifdef STRINGS
        !            94:                case SVCLASS:
        !            95:                case STCLASS:
        !            96:                case SFCLASS:
        !            97:                case SACLASS:
        !            98:                        error(inst.thing.linno, 49); /* ST. in NUM */
        !            99:                        stpflg = 1;
        !           100:                        return(0.0);
        !           101:                        break;
        !           102: #endif
        !           103:                case VRCLASS:   /* VARIABLE CLASS */
        !           104:                        getvar(field, &nstack[--n]);
        !           105:                        opflag = 0;
        !           106:                        break;
        !           107:                case VACLASS:   /* SUBSCRIPTED VARIABLE */
        !           108:                        agetvar(field,&nstack[--n]);
        !           109:                        opflag = 0;
        !           110:                        break;
        !           111:                case NMCLASS:   /* NUMERIC FIELD */
        !           112:                        nstack[--n] = atof1(field);
        !           113:                        opflag = 0;
        !           114:                        break;
        !           115:                case FNCLASS:   /* FUNCTION REFERENCE */
        !           116:                        nstack[--n] = mathcall(field);
        !           117:                        opflag = 0;
        !           118:                        break;
        !           119:                case OPCLASS:   /* OPERATOR */
        !           120:                        switch(*field) {
        !           121:                                case '(': /* begin of expres */
        !           122:                                        nstack[--n] = evalx(expptr);
        !           123:                                        opflag = 0;
        !           124:                                        expptr = eoexpr; /* put pointer
        !           125:                                                           to correct place */
        !           126:                                        break;
        !           127:                                case ')': /* end of express */
        !           128:                                        /*
        !           129:                                         * eval the rest of the expr
        !           130:                                         * between the parens
        !           131:                                         */
        !           132:                                        cleanup(nstack,ostack,&n,&o);
        !           133:                                        eoexpr = expptr;
        !           134:                                        return(nstack[n]);
        !           135:                                        break;
        !           136:                                case '+':
        !           137:                                case '-':
        !           138:                                case '*':
        !           139:                                case '/':
        !           140:                                case '^':
        !           141:                                        /*
        !           142:                                         * handle unaries by forcing
        !           143:                                         * a 0.0 onto the nstack before
        !           144:                                         * stacking the operator.
        !           145:                                         * This occurs when two operators
        !           146:                                         * in a row are encountered or the
        !           147:                                         * variable stack is empty when
        !           148:                                         * an operator encountered.
        !           149:                                         */
        !           150:                                        if(opflag || n == STKSIZ)
        !           151:                                                nstack[--n] = 0.0;
        !           152:                                        opflag = 1;
        !           153:                                        stackop(*field,nstack,ostack,&n,&o);
        !           154:                                        break;
        !           155:                                default:
        !           156:                                        break;
        !           157:                        }
        !           158:                        break;
        !           159:                default:
        !           160:                        printf("WHAT HAPPENED? TYPE = %d\n", type);
        !           161:                        break;
        !           162:                }
        !           163:                /*
        !           164:                 * skip trailing white space so that
        !           165:                 * test at top of this loop fails when
        !           166:                 * it's supposed to
        !           167:                 */
        !           168:                skip00();
        !           169: }      /* END OF WHILE LOOP */
        !           170: 
        !           171:        cleanup(nstack,ostack,&n,&o);
        !           172:        eoexpr = expptr;        /* save end of expr pointer for
        !           173:                                    "for", "if" and other commands */
        !           174:        return(nstack[n]);
        !           175: }
        !           176: /*
        !           177:  *
        !           178:  * //// STACK OPERATOR IF PRECIDENCE TEST IS PASSED ////
        !           179:  */
        !           180: stackop(op,nstack,ostack,n,o)
        !           181: char   op;
        !           182: double nstack[];
        !           183: char   ostack[];
        !           184: int    *n;
        !           185: int    *o;
        !           186: {
        !           187: 
        !           188:        /*
        !           189:         * if precidence of current operator is
        !           190:         * HIGHER than the operator on top of the stack
        !           191:         * or the OPERATOR stack is EMPTY,
        !           192:         * the precidence test has "passed" so just push
        !           193:         * the current operator onto the operator stack.
        !           194:         */
        !           195:        if(*o == STKSIZ)        /* if stack is empty */
        !           196:        {
        !           197:                ostack[--(*o)] = op;    /* stack operator
        !           198:                                            precidence done only
        !           199:                                             if stack NOT empty */
        !           200:                return 0;
        !           201:        }
        !           202:        if(precid(op) > precid(ostack[*o]))
        !           203:        {
        !           204:                ostack[--(*o)] = op;
        !           205:        }
        !           206:        else
        !           207:        {
        !           208:                /*
        !           209:                 * OTHERWISE if the current operator
        !           210:                 * precidence is LESS than or EQUAL to the
        !           211:                 * operator on the top of the stack
        !           212:                 * "unstack" the operators from the operator
        !           213:                 * stack until either the stack is empty
        !           214:                 * or the precidence test passes
        !           215:                 */
        !           216:                while((precid(op) <= precid(ostack[*o])) && *o < STKSIZ)
        !           217:                        if(unstack(nstack,ostack,n,o) < 0)
        !           218:                        {
        !           219:                                return(-1); /* break loop if bad operator
        !           220:                                                encountered */
        !           221:                        }
        !           222: 
        !           223:                ostack[--(*o)] = op;
        !           224:        }
        !           225:        return 0;
        !           226: }
        !           227: /*
        !           228:  *
        !           229:  * //// RETURN PRECIDENCE OF OPERATOR IN c ////
        !           230:  */
        !           231: precid(c)
        !           232: char c;
        !           233: {
        !           234: static char olist[] = "+1-1*2/2^3"; /* list of operators & precidence */
        !           235:        register int p; /* scanning register */
        !           236: 
        !           237:        for(p=0; olist[p] != '\0'; p += 2)
        !           238:        {
        !           239:                if(c == olist[p])
        !           240:                        return(olist[p+1] - '0');
        !           241:        }
        !           242:        return(-1);     /* if we get here, we're in trouble! */
        !           243: }
        !           244: 
        !           245: 
        !           246: 
        !           247: 
        !           248: /*
        !           249:  * //// CLEANUP THE REST OF THE EXPRESSION ////
        !           250:  *
        !           251:  * "pop and do" operations on opstack until
        !           252:  * stack empty
        !           253:  */
        !           254: cleanup(nstack,ostack,n,o)
        !           255: double nstack[];
        !           256: char   ostack[];
        !           257: int    *n;
        !           258: int    *o;
        !           259: {
        !           260:        while(*o < STKSIZ)
        !           261:                if(unstack(nstack,ostack,n,o) < 0)
        !           262:                        return(-1);     /* break loop if bad operator
        !           263:                                                encountered */
        !           264:        return 0;
        !           265: }
        !           266: /*
        !           267:  *
        !           268:  * //// POP OPERATER OFF TOP OF OPSTACK ////
        !           269:  * //// AND PERFORM THAT OPERATION ON //////
        !           270:  * //// TOP TWO NUMBERS ON NSTACK //////////
        !           271:  * //// NSTACK GETS POPPED AND RESULT //////
        !           272:  * //// IS LEFT ON TOP /////////////////////
        !           273:  * //// THOSE OPERATIONS ON TOP TWO NUMS /////
        !           274:  */
        !           275: unstack(nstack,ostack,n,o)
        !           276: double nstack[];
        !           277: char   ostack[];
        !           278: int    *n;
        !           279: int    *o;
        !           280: {
        !           281:        switch(ostack[*o])
        !           282:        {
        !           283:                case '^':
        !           284:                        nstack[*n+1] = pow(nstack[*n+1],nstack[*n]);
        !           285:                        break;
        !           286:                case '*':
        !           287:                        nstack[*n+1] = nstack[*n+1] * nstack[*n];
        !           288:                        break;
        !           289:                case '/':
        !           290:                        if(nstack[*n] == 0.0) /* catch overflow */
        !           291:                        {
        !           292:                                error(inst.thing.linno, 29); /* OVERFLOW ERR */
        !           293:                                break;
        !           294:                        }
        !           295:                        nstack[*n+1] = nstack[*n+1] / nstack[*n];
        !           296:                        break;
        !           297:                case '+':
        !           298:                        nstack[*n+1] = nstack[*n+1] + nstack[*n];
        !           299:                        break;
        !           300:                case '-':
        !           301:                        nstack[*n+1] = nstack[*n+1] - nstack[*n];
        !           302:                        break;
        !           303:                default:
        !           304:                        error(inst.thing.linno, 8);
        !           305:                        return(-1);
        !           306:                        break;
        !           307:        }
        !           308:        (*n)++;         /* pop number stack */
        !           309:        (*o)++;         /* pop operator stack */
        !           310:        return(0);
        !           311: }
        !           312: /*
        !           313:  *
        !           314:  * ////// CALL MATH FUNCTION ////////
        !           315:  *
        !           316:  *
        !           317:  *
        !           318:  * callin format:
        !           319:  *     value = mathcall(string);
        !           320:  *
        !           321:  *     where: value = floating point value returned by call
        !           322:  *            string = pointer to a null terminated string containong
        !           323:  *                     the func text and expression within () - 
        !           324:  *                     i.e. "sin(EXPRESSION TEXT)"
        !           325:  */
        !           326: 
        !           327: /*
        !           328:  *
        !           329:  * //////// BASIC INTERPRETER MATH TABLE ////////
        !           330:  *
        !           331:  */
        !           332: #ifndef TEST
        !           333: double sin();
        !           334: double cos();
        !           335: double atan();
        !           336: double log();
        !           337: double tan();
        !           338: double fact();
        !           339: #ifdef STRINGS
        !           340: double len();
        !           341: double val();
        !           342: double asc();
        !           343: #endif
        !           344: #endif
        !           345: /*
        !           346:  * //// INSTRUMENT FUNCTIONS ////
        !           347:  */
        !           348: #ifdef TEST
        !           349: double dvmr();
        !           350: double button();
        !           351: double berror();
        !           352: #endif
        !           353: double exp();
        !           354: double _int(num)
        !           355: double num;
        !           356: {
        !           357:        long    trunc;  
        !           358:        trunc=num;
        !           359:        num=trunc;
        !           360:        return(num);
        !           361: }
        !           362: #ifndef TEST
        !           363: double sqroot(num)
        !           364: double num;
        !           365: {
        !           366:        if(num < 0.0)   
        !           367:                error(inst.thing.linno, 19);
        !           368:        return(pow(num, 0.5));  
        !           369: }
        !           370: 
        !           371: #endif
        !           372: double absolute(num)
        !           373: double num;
        !           374: {
        !           375:        double  fabs();
        !           376:        return(fabs(num));
        !           377: }
        !           378: 
        !           379: double rndgen(num)
        !           380: double num;
        !           381: {
        !           382:        double  rndnum;
        !           383:        rndnum = rand();        
        !           384:        return((rndnum/32767.0) * num + 1);     
        !           385: }
        !           386: /*
        !           387:  *
        !           388:  * This is the BASIC interpreter math func strin and routine
        !           389:  * dispatch table.
        !           390:  *
        !           391:  */
        !           392: 
        !           393: /*
        !           394:  * each entry contains the text for the MATH FUNCTION
        !           395:  * in question and the address of the routine which services it
        !           396:  */
        !           397: struct tbl
        !           398:        {
        !           399:                char *cmdtxt;
        !           400:                double (*func)();
        !           401:        };
        !           402: #ifndef TEST
        !           403: struct tbl mathtbl[] = {
        !           404:        {"sin",         sin},
        !           405:        {"cos",         cos},
        !           406:        {"exp",         exp},
        !           407:        {"log",         log},
        !           408:        {"int",         _int},
        !           409:        {"sqr",         sqroot}, 
        !           410:        {"abs",         absolute},
        !           411:        {"atn",         atan},
        !           412:        {"rnd",         rndgen},        
        !           413:        {"tan",         tan},
        !           414:        {"fact",        fact},
        !           415: #ifdef STRINGS
        !           416:        {(char *)1,     0},     /* String function fence */
        !           417:        {"len",         len},
        !           418:        {"val",         val},
        !           419:        {"asc",         asc},
        !           420: #endif
        !           421: /* THIS STUFF NOT INCLUDED YET
        !           422:        {"cot",         cotang},
        !           423:        {"clg",         log10},
        !           424:        {"sgn",         sign},
        !           425: */
        !           426:        {0,             0}      
        !           427:        };
        !           428: #endif
        !           429: #ifdef TEST
        !           430: struct tbl mathtbl[] {
        !           431:        {"abs",         absolute},
        !           432:        {"rnd",         rndgen},
        !           433:        {"int",         _int},
        !           434:        {"exp",         exp},
        !           435:        {"dvmr",        dvmr},
        !           436:        {"btn",         button},
        !           437:        {"error",       berror},
        !           438:        {0,             0}
        !           439:        };
        !           440: #endif
        !           441: /*
        !           442:  *
        !           443:  */
        !           444: double
        !           445: mathcall(s)
        !           446: char   s[];
        !           447: {
        !           448:        char    funnam[10]; /* func name copied from 's'
        !           449:                                used for string search */
        !           450:        register char *x; /* pointer to paren enclosed expression */
        !           451:        double  evalx();
        !           452:        double  value;  /* final value returned */
        !           453:        double  exvalue; /* value of expression before being operated
        !           454:                             upon by the math func */
        !           455:        register  int i;                /* index reg. for expediency */
        !           456:        x = s;          /* set pointer to func string */
        !           457:        /*
        !           458:         * copy the func name part up to the '('
        !           459:         * to use for a string search in the table of names
        !           460:         */
        !           461:        for(i=0; *x != '(' ;)
        !           462:        {
        !           463:                funnam[i++] = *x++;
        !           464:        }
        !           465:        funnam[i] = '\0';       /* null terminate */
        !           466:        /*
        !           467:         * compare each string in table with funnam
        !           468:         * when match is found, call using offset code
        !           469:         * if end-of-table (null) encountered return 0
        !           470:         */
        !           471: #ifdef STRINGS
        !           472:        strflg = 0;
        !           473: #endif
        !           474:        for(i=0; mathtbl[i].cmdtxt != 0 ; i++)
        !           475:        {
        !           476: #ifdef STRINGS
        !           477:                if(mathtbl[i].cmdtxt == (char *)1)
        !           478:                {
        !           479:                        i++;
        !           480:                        strflg = 1;     /* its a string type */
        !           481:                }
        !           482: #endif
        !           483:                if(!(strcmp(funnam, mathtbl[i].cmdtxt)))
        !           484:                {
        !           485:                        x++;
        !           486: #ifdef STRINGS
        !           487:                        if(strflg == 0)
        !           488:                        {
        !           489: #endif
        !           490:                                exvalue = evalx(x); 
        !           491:                                value = (*mathtbl[i].func)(exvalue);
        !           492:                                return(value);
        !           493: #ifdef STRINGS
        !           494:                        }
        !           495:                        else
        !           496:                        {
        !           497:                                value = (*mathtbl[i].func)(x);
        !           498:                                return(value);
        !           499:                        }
        !           500: #endif
        !           501:                }
        !           502:        }
        !           503:        error(inst.thing.linno, 17);    /* unknown math function */
        !           504:        return(0.0);    /* oops not in this table, pal */
        !           505: }

unix.superglobalmegacorp.com

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