Annotation of researchv10no/cmd/basic/bas/expr.c, revision 1.1.1.1

1.1       root        1: #include <stdio.h>
                      2: #include "ctype.h"
                      3: #include "typedef.h"
                      4: #include "basic.h"
                      5: #include "tokens.h"
                      6: 
                      7: #define NOOP           0
                      8: #define TYPEMASK       07
                      9: #define min(a,b)       ((a)<(b)?(a):(b))
                     10: #define prio(x)        priority[-x]
                     11: #define between(a,b,c) ((a)<=(b)&&(b)<=(c))
                     12: #define FIRSTOP        OR
                     13: #define LASTOP         PLUS
                     14: #define OPCOUNT        20
                     15: #define MAXOP          10      
                     16: #define MAXDIGITS      64
                     17: 
                     18: static char    priority[OPCOUNT];
                     19: static char    priodefs[] = {
                     20:        20,     EXP,
                     21:        11,     MUL,    DIV,
                     22:        10,     PLUS,   MINUS,
                     23:        9,      EQ,     NE,     GE,     LE,     LT,     GT,
                     24:        7,      AND,
                     25:        6,      OR,
                     26:        0,      NOOP
                     27:        };
                     28: 
                     29: Stkptr pushvar(), nextframe();
                     30: Symptr getvar();
                     31: char   *allocstr(), *getsvar();
                     32: double popfloat(), modf(), atof(), cvtnumber(), exp(), log(), fabs(), floor();
                     33: 
                     34: 
                     35: /*
                     36:  * initprio --- initialize the operator-priority map
                     37:  */
                     38: 
                     39: initprio()
                     40: {
                     41:        register int    pri;
                     42:        register char   *p;
                     43: 
                     44:        for (p = priodefs; p < priodefs + sizeof priodefs; p++)
                     45:                if (*p >= 0)
                     46:                        pri = *p;
                     47:                else
                     48:                        prio(*p) = pri;
                     49:        if (tflg)
                     50:                for (pri = FIRSTOP; pri <= LASTOP; pri++)
                     51:                        fprintf(stderr, "priority[%d] == %d\n", pri, prio(pri));
                     52: }
                     53: 
                     54: 
                     55: /*
                     56:  * expr --- interpret an expression, push result onto stack
                     57:  */
                     58: 
                     59: expr()
                     60: {
                     61:        register int    op, evop;
                     62:        register char   *opptr;
                     63:        char            opstk[MAXOP];
                     64:        int             c;
                     65: 
                     66: #define getop()        (between(FIRSTOP,*inptr,LASTOP)? *inptr++ : 0)
                     67: #define getitem()      {\
                     68:                        c = *inptr;\
                     69:                        if (isalpha(c))\
                     70:                                pushvar();\
                     71:                        else if (isdigit(c))\
                     72:                                pushfloat(cvtnumber(&inptr, MAXINT));\
                     73:                        else\
                     74:                                item();\
                     75:                        }
                     76: 
                     77:        getitem();
                     78:        if ((op = getop()) == 0)
                     79:                return;
                     80:        opptr = opstk;
                     81:        *opptr++ = NOOP;
                     82:        for (;;)
                     83:                if (prio(opptr[-1]) >= prio(op)) {
                     84:                        evop = *--opptr;
                     85:                        if (evop == NOOP)
                     86:                                return;
                     87:                        eval(evop);
                     88:                        }
                     89:                else {
                     90:                        getitem();
                     91:                        *opptr++ = op;
                     92:                        if (opptr > opstk + MAXOP)
                     93:                                err("expression too complex");
                     94:                        op = getop();
                     95:                        }
                     96: }
                     97: 
                     98: 
                     99: /*
                    100:  * eval --- evaluate the specified operator using stacked operands
                    101:  */
                    102: 
                    103: eval(op)
                    104: {
                    105:        double          fp1, fp2;
                    106:        register Stkptr s;
                    107: 
                    108:        s = (Stkptr)stkptr;
                    109:        if (s->k_type == STRINGEXPR) {
                    110:                streval(op);
                    111:                return;
                    112:                }
                    113:        fp2 = popfloat();
                    114:        s = (Stkptr)stkptr;
                    115:        if (s->k_type != FLOATEXPR)
                    116:                badstk(FLOATEXPR);
                    117:        fp1 = s->k_un.k_dbl;
                    118: 
                    119:        switch(op) {
                    120:        case PLUS:
                    121:                fp1 += fp2;
                    122:                break;
                    123:        case MINUS:
                    124:                fp1 -= fp2;
                    125:                break;
                    126:        case MUL:
                    127:                fp1 *= fp2;
                    128:                break;
                    129:        case DIV:
                    130:                fp1 /= fp2;
                    131:                break;
                    132:        case EXP:
                    133:                if (fp1 > 0)
                    134:                        fp1 = exp(log(fp1) * fp2);
                    135:                else if (fp1 != 0 && fp2 == 0)
                    136:                        fp1 = 1;
                    137:                else if (fp1 == 0 && fp2 != 0)
                    138:                        fp1 = 0;
                    139:                else if (fp1 < 0 && (fp2 - 2*floor(fp2 / 2.)) == 0)
                    140:                        fp1 = exp(log(fabs(fp1)) * fp2);
                    141:                else if (fp1 < 0 && (fp2 - floor(fp2)) == 0)
                    142:                        fp1 = -exp(log(fabs(fp1)) * fp2);
                    143:                else {fp1 = 0;
                    144:                fprintf(stderr, "0 to the 0 power and negative numbers");
                    145:                fprintf(stderr, " to noninteger powers \n");
                    146:                fprintf(stderr, " can not be calculated. 0 was returned.\n");
                    147:                        };
                    148:                break;
                    149:        case GT:
                    150:                fp1 = (fp1 > fp2);
                    151:                break;
                    152:        case LT:
                    153:                fp1 = (fp1 < fp2);
                    154:                break;
                    155:        case LE:
                    156:                fp1 = (fp1 <= fp2);
                    157:                break;
                    158:        case GE:
                    159:                fp1 = (fp1 >= fp2);
                    160:                break;
                    161:        case EQ:
                    162:                fp1 = (fp1 == fp2);
                    163:                break;
                    164:        case NE:
                    165:                fp1 = (fp1 != fp2);
                    166:                break;
                    167:        case OR:
                    168:                fp1 = ((fp1 != 0) || (fp2 != 0));
                    169:                break;
                    170:        case AND:
                    171:                fp1 = ((fp1 != 0) && (fp2 != 0));
                    172:                break;
                    173:        default:
                    174:                err("bad operator");
                    175:                }
                    176:        s->k_un.k_dbl = fp1;
                    177: }
                    178: 
                    179: 
                    180: /*
                    181:  * streval --- evaluate an operator with string operands
                    182:  */
                    183: 
                    184: streval(op)
                    185: {
                    186:        register int    i;
                    187:        char            *ptr1, *ptr2;
                    188:        int             len1, len2;
                    189: 
                    190:        if (op == PLUS) {
                    191:                concat();
                    192:                return;
                    193:                }
                    194:        popstring(&ptr2, &len2);
                    195:        popstring(&ptr1, &len1);
                    196:        i = strcmpn(ptr1, len1, ptr2, len2);
                    197: 
                    198:        switch(op) {
                    199:        case GT:
                    200:                i = (i > 0);
                    201:                break;
                    202:        case LT:
                    203:                i = (i < 0);
                    204:                break;
                    205:        case LE:
                    206:                i = (i <= 0);
                    207:                break;
                    208:        case GE:
                    209:                i = (i >= 0);
                    210:                break;
                    211:        case EQ:
                    212:                i = (i == 0);
                    213:                break;
                    214:        case NE:
                    215:                i = (i != 0);
                    216:                break;
                    217:        default:
                    218:                err("bad operator");
                    219:                }
                    220:        pushint(i);
                    221: }
                    222: 
                    223: 
                    224: /*
                    225:  * strcmpn --- compare fixed length strings
                    226:  */
                    227: 
                    228: strcmpn(ptr1, len1, ptr2, len2)
                    229: char   *ptr1, *ptr2;
                    230: {
                    231:        register int    l;
                    232:        register char   *p1, *p2;
                    233: 
                    234:        l = min(len1, len2);
                    235:        len1 -= l;
                    236:        len2 -= l;
                    237:        p1 = ptr1;
                    238:        p2 = ptr2;
                    239:        while (l > 0 && *p1++ == *p2++)
                    240:                --l;
                    241:        if (l != 0)
                    242:                return(*--p1 - *--p2);
                    243:        while (len1 > 0) {      /* string 1 longer */
                    244:                if (*p1++ != ' ')
                    245:                        return(*--p1 - ' ');
                    246:                --len1;
                    247:                }
                    248:        while (len2 > 0) {      /* string 2 longer */
                    249:                if (*p2++ != ' ')
                    250:                        return(' ' - *--p2);
                    251:                --len2;
                    252:                }
                    253:        return(0);              /* strings are equal */
                    254: }
                    255: 
                    256: 
                    257: /*
                    258:  * item --- interpret a basic expression element
                    259:  */
                    260: 
                    261: item()
                    262: {
                    263:        register Stkptr s;
                    264:        register int    c;
                    265:        
                    266:        switch((c = *inptr++)) {
                    267: 
                    268:        case FN:        /* function call */
                    269:                --inptr;        /* back up to FN token */
                    270:                fn();
                    271:                break;
                    272:        case PLUS:      /* unary + */
                    273:                item();
                    274:                break;
                    275:        case MINUS:     /* unary - */
                    276:                item();
                    277:                s = (Stkptr)stkptr;
                    278:                if (s->k_type != FLOATEXPR)
                    279:                        err("float required");
                    280:                s->k_un.k_dbl = -s->k_un.k_dbl;
                    281:                break;
                    282:        case LPAR:      /* parenthesized expr */
                    283:                expr();
                    284:                expectc(RPAR);
                    285:                break;
                    286:        case QUOTE:     /* string constant */
                    287:        case PRIME:
                    288:                strconst(c);
                    289:                break;
                    290:        default:        /* float constant, variable, or builtin func */
                    291:                --inptr;
                    292:                if (isdigit(c) || c == '.')
                    293:                        pushfloat(cvtnumber(&inptr, MAXINT));
                    294:                else if (isalpha(c))
                    295:                        pushvar();
                    296:                else if (function())
                    297:                        ;
                    298:                else
                    299:                        err("bad operand");
                    300:                }
                    301: }
                    302: 
                    303: 
                    304: /*
                    305:  * cvtnumber --- convert a string to floating point
                    306:  */
                    307: 
                    308: double cvtnumber(ptr, len)
                    309: char           **ptr;
                    310: register int   len;
                    311: {
                    312:        register char   *n, *p;
                    313:        char            numbuff[MAXDIGITS];
                    314:        double          f;
                    315:        
                    316:        p = *ptr;
                    317:        n = numbuff;
                    318:        if (*p == '+') {
                    319:                ++p;
                    320:                --len;
                    321:                }
                    322:        else if (*p == '-') {
                    323:                *n++ = *p++;
                    324:                --len;
                    325:                }
                    326:        for (; isdigit(*p) || *p == '.' || *p == 'e'; ) {
                    327:                if (n >= &numbuff[MAXDIGITS-1]) {
                    328:                        *ptr = p;
                    329:                        err("too many digits");
                    330:                        }
                    331:                *n++ = *p++;
                    332:                if (--len <= 0)
                    333:                        break;
                    334:                }
                    335:        *n = 0;
                    336:        f = atof(numbuff);
                    337:        *ptr = p;
                    338:        return(f);
                    339: }
                    340: 
                    341: 
                    342: /*
                    343:  * strconst --- interpret a string constant in an expression
                    344:  */
                    345: 
                    346: strconst(c)
                    347: {
                    348:        Stkfr           s;
                    349:        
                    350:        s.k_un.k_str.s_ptr = inptr;
                    351:        while (*inptr && *inptr != c)
                    352:                ++inptr;
                    353:        s.k_un.k_str.s_len = inptr - s.k_un.k_str.s_ptr;
                    354:        s.k_len = STRFRLEN;
                    355:        s.k_type = STRINGEXPR;
                    356:        push(&s);
                    357:        if (*inptr == c)
                    358:                ++inptr;
                    359: }
                    360: 
                    361: 
                    362: /*
                    363:  * badtype --- report a data type error
                    364:  */
                    365: 
                    366: badtype()
                    367: {
                    368: 
                    369:        err("bad type");
                    370: }
                    371: 
                    372: 
                    373: /*
                    374:  * pushvar --- push the value of a variable onto the stack
                    375:  */
                    376: 
                    377: Stkptr pushvar()
                    378: {
                    379:        register char   *s;
                    380:        register int    i;
                    381:        int             type;
                    382:        
                    383:        s = getsvar(&type);
                    384:        
                    385:        switch(type) {
                    386:        case STRING:
                    387:                pushstring(((String *)s)->s_ptr, ((String *)s)->s_len);
                    388:                break;
                    389:        case INT:
                    390:                pushint(*(int *)s);
                    391:                break;
                    392:        case FLOAT:
                    393:                if (SINGLE)
                    394:                        pushfloat(*(float *)s);
                    395:                else
                    396:                        pushfloat(*(double *)s);
                    397:                break;
                    398:        default:
                    399:                err("value expected");
                    400:                }
                    401:        return((Stkptr)stkptr);
                    402: }
                    403: 
                    404: 
                    405: /*
                    406:  * getsc --- convert multi-dimensional subscript to single-dimensional
                    407:  */
                    408: 
                    409: getsc(v)
                    410: register Symptr v;
                    411: {
                    412:        register int    i, j, n;
                    413:        
                    414:        if (nsubs != v->v_nsubs)
                    415:                err("wrong number of subscripts");
                    416:        for (j = 0, n = 0;; ) {
                    417:                i = subsc[j];
                    418:                if (i < 1 || i > v->v_un.v_vec.v_subsc[j])
                    419:                        err("subscript %d out of range (%d)", j + 1, i);
                    420:                n += i - 1;
                    421:                if (++j >= nsubs)
                    422:                        break;
                    423:                n *= v->v_un.v_vec.v_subsc[j];
                    424:                }
                    425:        return(n);
                    426: }
                    427: 
                    428: 
                    429: /*
                    430:  * intvalued --- determine if a floating point number is integral
                    431:  */
                    432: 
                    433: intvalued(f)
                    434: double f;
                    435: {
                    436:        double  ipart;
                    437: 
                    438:        return(modf(f, &ipart) == 0.0);
                    439: }
                    440: 
                    441: 
                    442: /*
                    443:  * let --- interpret a LET statement
                    444:  */
                    445: 
                    446: let()
                    447: {
                    448:        register Stkptr s;
                    449:        register char   *v;
                    450:        register int    i;
                    451:        int             type, stype;
                    452:        
                    453: 
                    454:        v = getsvar(&type);     /* v points to value in variable */
                    455: 
                    456:        expectc(EQ);
                    457:        expr();
                    458:        s = (Stkptr)stkptr;     /* get the expression */
                    459: 
                    460:        stype = s->k_type & TYPEMASK;
                    461: 
                    462:        if (stype != type && (stype == STRING || type == STRING))
                    463:                mixed();
                    464: 
                    465:        switch(type) {
                    466:                case FLOAT:
                    467:                        if (SINGLE)
                    468:                                *(float *)v = popfloat();
                    469:                        else
                    470:                                *(double *)v = popfloat();
                    471:                        break;
                    472:                case INT:
                    473:                        *(int *)v = popint();
                    474:                        /* pushfloat(*(double *)v); */
                    475:                        break;
                    476:                case STRING:
                    477:                        storestring(v);
                    478:                        break;
                    479:                default:
                    480:                        err("invalid variable");
                    481:                }
                    482: 
                    483: }
                    484: 
                    485: 
                    486: /*
                    487:  * cvt --- convert value at top of stack to type "type"
                    488:  */
                    489: 
                    490: cvt(type)
                    491: {
                    492:        register Stkptr s;
                    493:        register int    stype;
                    494:        
                    495:        s = (Stkptr)stkptr;
                    496:        type &= TYPEMASK;
                    497:        stype = s->k_type & TYPEMASK;
                    498:        if (stype == type)
                    499:                return;
                    500:        switch(type) {
                    501:        case FLOAT:
                    502:                if (stype == INT) {
                    503:                        pushfloat((double)popint());
                    504:                        return;
                    505:                        }
                    506:                break;
                    507:        case INT:
                    508:                if (stype == FLOAT) {
                    509:                        pushint((int)popfloat());
                    510:                        return;
                    511:                        }
                    512:                }
                    513:        err("invalid type conversion");
                    514: }
                    515: 
                    516: 
                    517: /*
                    518:  * concat --- concatenate the strings at the top of the stack
                    519:  *           don't pop the strings until they have been copied
                    520:  *           to their new location in case garbage collection
                    521:  *           takes place during allocation
                    522:  */
                    523: 
                    524: concat()
                    525: {
                    526:        register Stkptr s, p;
                    527:        register char   *q;
                    528:        int             slen, plen;
                    529:        
                    530:        s = (Stkptr)stkptr;
                    531:        slen = s->k_un.k_str.s_len;
                    532:        p = nextframe(s);
                    533:        plen = p->k_un.k_str.s_len;
                    534:        if (p->k_type != STRINGEXPR)
                    535:                mixed();
                    536:        if (slen + plen > MAXSTRING)
                    537:                err("string too long");
                    538:        q = allocstr(NULL, slen + plen, 0);
                    539:        move(plen, p->k_un.k_str.s_ptr, q);
                    540:        move(slen, s->k_un.k_str.s_ptr, q + plen);
                    541:        pop(STRINGEXPR);                /* get rid of topmost string */
                    542:        p->k_un.k_str.s_ptr = q;        /* replace the other */
                    543:        p->k_un.k_str.s_len += slen;
                    544: }
                    545: 
                    546: 
                    547: /*
                    548:  * getsvar --- return pointer to value of a variable
                    549:  *            return its type in "type"
                    550:  */
                    551: 
                    552: char *getsvar(type)
                    553: int    *type;
                    554: {
                    555:        register char   *p;
                    556:        register Symptr v;
                    557:        register int    i;
                    558:        
                    559:        v = getvar(type, NO);
                    560:        if (nsubs == 0)
                    561:                return((char *)&v->v_un);       /* not subscripted */
                    562:        i = getsc(v);           /* get and check subscript */
                    563:        switch(*type) {
                    564:        case FLOAT:
                    565:                if (SINGLE)
                    566:                        p = (char *)&v->v_un.v_vec.v_vecun.v_fltvec[i];
                    567:                else
                    568:                        p = (char *)&v->v_un.v_vec.v_vecun.v_dblvec[i];
                    569:                break;
                    570:        case INT:
                    571:                p = (char *)&v->v_un.v_vec.v_vecun.v_intvec[i];
                    572:                break;
                    573:        case STRING:
                    574:                p = (char *)&v->v_un.v_vec.v_vecun.v_strvec[i];
                    575:                break;
                    576:        default:
                    577:                badtype();
                    578:                }
                    579:        return(p);
                    580: }
                    581: 
                    582: 
                    583: /*
                    584:  * mixed --- report mixed data mode error
                    585:  */
                    586: 
                    587: mixed()
                    588: {
                    589: 
                    590:        err("mixed modes");
                    591: }

unix.superglobalmegacorp.com

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