Annotation of researchv10no/cmd/lcc/c/eval.c, revision 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.