Annotation of researchv10no/cmd/basic/bite/src/evalx.c, revision 1.1.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.