Annotation of researchv10no/cmd/lcc/c/eval.c, revision 1.1.1.1

1.1       root        1: /* C compiler & debugger: expression evaluation */
                      2: 
                      3: #include "c.h"
                      4: 
                      5: typedef struct {
                      6:        Tree p;                 /* associated tree */
                      7:        Value r;                /* the register */
                      8: } Register;
                      9: static char *errcode;          /* evaluation error string */
                     10: static int nextr;
                     11: static Register regs[30];
                     12: 
                     13: dclproto(static Value *eval,(Tree))
                     14: dclproto(static Value *treereg,(Tree))
                     15: 
                     16: /* evaluate - evaluate tree p */
                     17: Symbol evaluate(p) Tree p; {
                     18:        static struct symbol sym;
                     19: 
                     20:        nextr = 1;
                     21:        errcode = 0;
                     22:        sym.u.c.v = *eval(p);
                     23:        if (errcode)
                     24:                return 0;
                     25:        sym.type = p->type;
                     26:        return &sym;
                     27: }
                     28: 
                     29: /* eval - recursively evaluate tree p, return allocated register */
                     30: static Value *eval(p) Tree p; {
                     31:        Value *r, *r1 = 0, *r2 = 0;
                     32:        Tree left, right;
                     33: 
                     34:        if (r = treereg(p))
                     35:                return r;
                     36:        if (nextr > sizeof regs/sizeof regs[0]) {
                     37:                error("expression too complicated\n");
                     38:                return &regs[0].r;
                     39:        }
                     40:        regs[nextr].p = p;
                     41:        r = &regs[nextr++].r;
                     42:        switch (generic(p->op)) {       /* control flow operators */
                     43:        case AND:
                     44:                r1 = eval(p->kids[0]);
                     45:                if (r1->i)
                     46:                        r1 = eval(p->kids[1]);
                     47:                r->i = r1->i;
                     48:                return r;
                     49:        case COND:
                     50:                r = eval(p->kids[0]);
                     51:                r1 = eval(p->kids[r->i ? 1 : 2]);
                     52:                *r = *r1;
                     53:                return r;
                     54:        case NOT:
                     55:                r1 = eval(p->kids[0]);
                     56:                r->i = !r1->i;
                     57:                return r;
                     58:        case OR:
                     59:                r1 = eval(p->kids[0]);
                     60:                if (r1->i == 0)
                     61:                        r1 = eval(p->kids[1]);
                     62:                r->i = r1->i;
                     63:                return r;
                     64:        }
                     65:        if (left = p->kids[0])
                     66:                r1 = eval(left);
                     67:        if (right = p->kids[1])
                     68:                r2 = eval(right);
                     69:        switch (p->op) {
                     70:        case ADD+D: r->d = r1->d + r2->d; break;
                     71:        case ADD+F: r->f = r1->f + r2->f; break;
                     72:        case ADD+I: r->i = r1->i + r2->i; break;
                     73:        case ADD+P:
                     74:                if (isptr(left->type))
                     75:                        r->s = r1->s + r2->i;
                     76:                else
                     77:                        r->s = r1->i + r2->s;
                     78:                break;
                     79:        case ADD+U: r->u = r1->u + r2->u; break;
                     80:        case ADDRF+P:
                     81:        case ADDRG+P:
                     82:        case ADDRL+P: goto bad;
                     83:        case ARG+B:
                     84:        case ARG+C:
                     85:        case ARG+D:
                     86:        case ARG+F:
                     87:        case ARG+I:
                     88:        case ARG+P:
                     89:        case ARG+S: goto bad;
                     90:        case ASGN+B:
                     91:        case ASGN+C:
                     92:        case ASGN+D:
                     93:        case ASGN+F:
                     94:        case ASGN+I:
                     95:        case ASGN+P:
                     96:        case ASGN+S: goto bad;
                     97:        case BAND+I: r->i = r1->i&r2->i; break;
                     98:        case BAND+U: r->u = r1->u&r2->u; break;
                     99:        case BCOM+U: r->u = ~r1->u; break;
                    100:        case BOR+I:  r->i = r1->i|r2->i; break;
                    101:        case BOR+U:  r->u = r1->u|r2->u; break;
                    102:        case BXOR+I: r->i = r1->i^r2->i; break;
                    103:        case BXOR+U: r->u = r1->u^r2->u; break;
                    104:        case CALL+B:
                    105:        case CALL+D:
                    106:        case CALL+F:
                    107:        case CALL+I:
                    108:        case CALL+V: goto bad;
                    109:        case CNST+C:
                    110:        case CNST+D:
                    111:        case CNST+F:
                    112:        case CNST+I:
                    113:        case CNST+P:
                    114:        case CNST+S:
                    115:        case CNST+U: *r = p->u.v; break;
                    116:        case CVC+I: r->i = r1->sc; break;
                    117:        case CVC+U: r->u = r1->uc; break;
                    118:        case CVD+F: r->f = r1->d; break;
                    119:        case CVD+I: r->i = r1->d; break;
                    120:        case CVD+U: r->u = r1->d; break;
                    121:        case CVF+D: r->d = r1->f; break;
                    122:        case CVI+C: r->sc = r1->i; break;
                    123:        case CVI+D: r->d = r1->i; break;
                    124:        case CVI+S: r->ss = r1->i; break;
                    125:        case CVI+U: r->u = r1->i; break;
                    126:        case CVP+U: r->u = (unsigned)r1->p; break;
                    127:        case CVS+I: r->i = r1->ss; break;
                    128:        case CVS+U: r->u = r1->us; break;
                    129:        case CVU+C: r->uc = r1->u; break;
                    130:        case CVU+D: r->d = r1->u; break;
                    131:        case CVU+I: r->i = r1->u; break;
                    132:        case CVU+P: r->p = (char *)r1->u; break;
                    133:        case CVU+S: r->us = r1->u; break;
                    134:        case DIV+D:
                    135:                if (r2->d == 0.0)
                    136:                        errcode = "division by 0.0";
                    137:                else
                    138:                        r->d = r1->d/r2->d;
                    139:                break;
                    140:        case DIV+F:
                    141:                if (r2->f == 0.0)
                    142:                        errcode = "division by 0";
                    143:                else
                    144:                        r->f = r1->f/r2->f;
                    145:                break;
                    146:        case DIV+I:
                    147:                if (r2->i == 0)
                    148:                        errcode = "division by 0";
                    149:                else
                    150:                        r->i = r1->i/r2->i;
                    151:                break;
                    152:        case DIV+U:             
                    153:                if (r2->u == 0)
                    154:                        errcode = "division by 0";
                    155:                else
                    156:                        r->u = r1->u/r2->u;
                    157:                break;
                    158:        case EQ+D: r->i = r1->d == r2->d; break;
                    159:        case EQ+F: r->i = r1->f == r2->f; break;
                    160:        case EQ+I: r->i = r1->i == r2->i; break;
                    161:        case EQ+U: r->i = r1->u == r2->u; break;
                    162:        case FIELD: goto bad;
                    163:        case GE+D: r->i = r1->d >= r2->d; break;
                    164:        case GE+F: r->i = r1->f >= r2->f; break;
                    165:        case GE+I: r->i = r1->i >= r2->i; break;
                    166:        case GE+U: r->i = r1->u >= r2->u; break;
                    167:        case GT+D: r->i = r1->d >  r2->d; break;
                    168:        case GT+F: r->i = r1->f >  r2->f; break;
                    169:        case GT+I: r->i = r1->i >  r2->i; break;
                    170:        case GT+U: r->i = r1->u >  r2->u; break;
                    171:        case INDIR+B:
                    172:        case INDIR+C:
                    173:        case INDIR+D:
                    174:        case INDIR+F:
                    175:        case INDIR+I:
                    176:        case INDIR+P:
                    177:        case INDIR+S: goto bad;
                    178:        case JUMP+V:
                    179:                fatal("eval", "unexpected %s operator\n", "JUMP+V");
                    180:        case LE+D: r->i = r1->d <= r2->d; break;
                    181:        case LE+F: r->i = r1->f <= r2->f; break;
                    182:        case LE+I: r->i = r1->i <= r2->i; break;
                    183:        case LE+U: r->i = r1->u <= r2->u; break;
                    184:        case LSH+I: r->i = r1->i<<r2->i; break;
                    185:        case LSH+U: r->u = r1->u<<r2->u; break;
                    186:        case LT+D:  r->i = r1->d < r2->d; break;
                    187:        case LT+F:  r->i = r1->f < r2->f; break;
                    188:        case LT+I:  r->i = r1->i < r2->i; break;
                    189:        case LT+U:  r->i = r1->u < r2->u; break;
                    190:        case MOD+I:
                    191:                if (r2->i == 0)
                    192:                        errcode = "division by 0";
                    193:                else
                    194:                        r->i = r1->i%r2->i;
                    195:                break;
                    196:        case MOD+U:             
                    197:                if (r2->u == 0)
                    198:                        errcode = "division by 0";
                    199:                else
                    200:                        r->u = r1->u%r2->u;
                    201:                break;
                    202:        case MUL+D: r->d = r1->d*r2->d; break;
                    203:        case MUL+F: r->f = r1->f*r2->f; break;
                    204:        case MUL+I: r->i = r1->i*r2->i; break;
                    205:        case MUL+U: r->u = r1->u*r2->u; break;
                    206:        case NE+D:  r->i = r1->d != r2->d; break;
                    207:        case NE+F:  r->i = r1->f != r2->f; break;
                    208:        case NE+I:  r->i = r1->i != r2->i; break;
                    209:        case NE+U:  r->i = r1->u != r2->i; break;
                    210:        case NEG+D: r->d = -r1->d; break;
                    211:        case NEG+F: r->f = -r1->f; break;
                    212:        case NEG+I: r->i = -r1->i; break;
                    213:        case RET+B:
                    214:        case RET+D:
                    215:        case RET+F:
                    216:        case RET+I:
                    217:        case RET+V: goto bad;
                    218:        case RIGHT: r->d = r2->d; break;
                    219:        case RSH+I: r->i = r1->i>>r2->i; break;
                    220:        case RSH+U: r->u = r1->u>>r2->u; break;
                    221:        case SUB+D: r->d = r1->d - r2->d; break;
                    222:        case SUB+F: r->f = r1->f - r2->f; break;
                    223:        case SUB+I: r->i = r1->i - r2->i; break;
                    224:        case SUB+P: r->i = r1->s - r2->s; break;
                    225:        case SUB+U: r->u = r1->u - r2->u; break;
                    226:        default: bad:
                    227:                fatal("eval", "unknown operator %d\n", p->op);
                    228:        }
                    229:        return r;
                    230: }
                    231: 
                    232: /* treereg - return register associated with tree p or 0 */
                    233: static Value *treereg(p) Tree p; {
                    234:        int i;
                    235: 
                    236:        for (i = 0; i < nextr; i++)
                    237:                if (regs[i].p == p)
                    238:                        return &regs[i].r;
                    239:        return 0;
                    240: }
                    241: 
                    242: /* vtoa - return string for the constant v of type ty */
                    243: char *vtoa(ty, v) Type ty; Value v; {
                    244:        static char buf[MAXLINE];
                    245: 
                    246:        ty = unqual(ty);
                    247:        switch (ty->op) {
                    248:        case CHAR:
                    249:                sprint(buf, "%d", v.uc);
                    250:                break;
                    251:        case SHORT:
                    252:                sprint(buf, "%d", v.ss);
                    253:                break;
                    254:        case INT:
                    255:                sprint(buf, "%d", v.i);
                    256:                break;
                    257:        case UNSIGNED:
                    258:                if ((v.u&~0x7fff) == 0)
                    259:                        sprint(buf, "%d", v.u);
                    260:                else
                    261:                        sprint(buf, "0x%x", v.u);
                    262:                break;
                    263:        case FLOAT:
                    264:                if (v.f == 0.0)
                    265:                        return "0";
                    266:                sprintf(buf, "%.*g", 8, v.f);
                    267:                break;
                    268:        case DOUBLE:
                    269:                if (v.d == 0.0)
                    270:                        return "0";
                    271:                sprintf(buf, "%.*g", 18, v.d);
                    272:                break;
                    273:        case ARRAY:
                    274:                if (ty->type->op == CHAR)
                    275:                        return v.s;
                    276:                /* else fall thru */
                    277:        case POINTER: case FUNCTION:
                    278:                if (((unsigned)v.p&~0x7fff) == 0)
                    279:                        sprint(buf, "%d", v.p);
                    280:                else
                    281:                        sprint(buf, "0x%x", v.p);
                    282:                break;
                    283:        default:
                    284:                assert(0);
                    285:        }
                    286:        return buf;
                    287: }

unix.superglobalmegacorp.com

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