Annotation of 3BSD/cmd/pi/rval.c, revision 1.1.1.1

1.1       root        1: /* Copyright (c) 1979 Regents of the University of California */
                      2: #
                      3: /*
                      4:  * pi - Pascal interpreter code translator
                      5:  *
                      6:  * Charles Haley, Bill Joy UCB
                      7:  * Version 1.2 Novmeber 1978
                      8:  */
                      9: 
                     10: #include "whoami"
                     11: #include "0.h"
                     12: #include "tree.h"
                     13: #include "opcode.h"
                     14: 
                     15: extern char *opnames[];
                     16: /*
                     17:  * Rvalue - an expression.
                     18:  *
                     19:  * Contype is the type that the caller would prefer, nand is important
                     20:  * if constant sets or constant strings are involved, the latter
                     21:  * because of string padding.
                     22:  */
                     23: struct nl *
                     24: rvalue(r, contype)
                     25:        int *r;
                     26:        struct nl *contype;
                     27: {
                     28:        register struct nl *p, *p1;
                     29:        register struct nl *q;
                     30:        int c, c1, *rt, w, g;
                     31:        char *cp, *cp1, *opname;
                     32:        long l;
                     33:        double f;
                     34: 
                     35:        if (r == NIL)
                     36:                return (NIL);
                     37:        if (nowexp(r))
                     38:                return (NIL);
                     39:        /*
                     40:         * Pick up the name of the operation
                     41:         * for future error messages.
                     42:         */
                     43:        if (r[0] <= T_IN)
                     44:                opname = opnames[r[0]];
                     45: 
                     46:        /*
                     47:         * The root of the tree tells us what sort of expression we have.
                     48:         */
                     49:        switch (r[0]) {
                     50: 
                     51:        /*
                     52:         * The constant nil
                     53:         */
                     54:        case T_NIL:
                     55:                put2(O_CON2, 0);
                     56:                return (nl+TNIL);
                     57: 
                     58:        /*
                     59:         * Function call with arguments.
                     60:         */
                     61:        case T_FCALL:
                     62:                return (funccod(r));
                     63: 
                     64:        case T_VAR:
                     65:                p = lookup(r[2]);
                     66:                if (p == NIL || p->class == BADUSE)
                     67:                        return (NIL);
                     68:                switch (p->class) {
                     69:                    case VAR:
                     70:                            /*
                     71:                             * If a variable is
                     72:                             * qualified then get
                     73:                             * the rvalue by a
                     74:                             * lvalue and an ind.
                     75:                             */
                     76:                            if (r[3] != NIL)
                     77:                                    goto ind;
                     78:                            q = p->type;
                     79:                            if (q == NIL)
                     80:                                    return (NIL);
                     81:                            w = width(q);
                     82:                            switch (w) {
                     83:                                case 8:
                     84:                                    w = 6;
                     85:                                case 4:
                     86:                                case 2:
                     87:                                case 1:
                     88:                                    put2(O_RV1 + (w >> 1) | bn << 9
                     89:                                        , p->value[0]);
                     90:                                    break;
                     91:                                default:
                     92:                                    put3(O_RV | bn << 9, p->value[0], w);
                     93:                            }
                     94:                            return (q);
                     95: 
                     96:                    case WITHPTR:
                     97:                    case REF:
                     98:                            /*
                     99:                             * A lvalue for these
                    100:                             * is actually what one
                    101:                             * might consider a rvalue.
                    102:                             */
                    103: ind:
                    104:                            q = lvalue(r, NOMOD);
                    105:                            if (q == NIL)
                    106:                                    return (NIL);
                    107:                            w = width(q);
                    108:                            switch (w) {
                    109:                                case 8:
                    110:                                        w = 6;
                    111:                                case 4:
                    112:                                case 2:
                    113:                                case 1:
                    114:                                        put1(O_IND1 + (w >> 1));
                    115:                                        break;
                    116:                                default:
                    117:                                        put2(O_IND, w);
                    118:                            }
                    119:                            return (q);
                    120: 
                    121:                    case CONST:
                    122:                            if (r[3] != NIL) {
                    123:                                    error("%s is a constant and cannot be qualified", r[2]);
                    124:                                    return (NIL);
                    125:                            }
                    126:                            q = p->type;
                    127:                            if (q == NIL)
                    128:                                    return (NIL);
                    129:                            if (q == nl+TSTR) {
                    130:                                    /*
                    131:                                     * Find the size of the string
                    132:                                     * constant if needed.
                    133:                                     */
                    134:                                    cp = p->ptr[0];
                    135: cstrng:
                    136:                                    cp1 = cp;
                    137:                                    for (c = 0; *cp++; c++)
                    138:                                            continue;
                    139:                                    if (contype != NIL && !opt('s')) {
                    140:                                            if (width(contype) < c && classify(contype) == TSTR) {
                    141:                                                    error("Constant string too long");
                    142:                                                    return (NIL);
                    143:                                            }
                    144:                                            c = width(contype);
                    145:                                    }
                    146:                                    put( 2 + (sizeof ( char * )/sizeof ( short )) , O_CONG, c, cp1);
                    147:                                    /*
                    148:                                     * Define the string temporarily
                    149:                                     * so later people can know its
                    150:                                     * width.
                    151:                                     * cleaned out by stat.
                    152:                                     */
                    153:                                    q = defnl(0, STR, 0, c);
                    154:                                    q->type = q;
                    155:                                    return (q);
                    156:                            }
                    157:                            if (q == nl+T1CHAR) {
                    158:                                    put2(O_CONC, p->value[0]);
                    159:                                    return (q);
                    160:                            }
                    161:                            /*
                    162:                             * Every other kind of constant here
                    163:                             */
                    164:                            switch (width(q)) {
                    165:                            case 8:
                    166: #ifndef DEBUG
                    167:                                    put(5, O_CON8, p->real);
                    168: #else
                    169:                                    if (hp21mx) {
                    170:                                            f = p->real;
                    171:                                            conv(&f);
                    172:                                            l = f.plong;
                    173:                                            put( 3 , O_CON4, l);
                    174:                                    } else
                    175:                                            put(5, O_CON8, p->real);
                    176: #endif
                    177:                                    break;
                    178:                            case 4:
                    179:                                    put( 3 , O_CON4, p->range[0]);
                    180:                                    break;
                    181:                            case 2:
                    182:                                    put2(O_CON2, ( short ) p->range[0]);
                    183:                                    break;
                    184:                            case 1:
                    185:                                    put2(O_CON1, p->value[0]);
                    186:                                    break;
                    187:                            default:
                    188:                                    panic("rval");
                    189:                            }
                    190:                            return (q);
                    191: 
                    192:                    case FUNC:
                    193:                            /*
                    194:                             * Function call with no arguments.
                    195:                             */
                    196:                            if (r[3]) {
                    197:                                    error("Can't qualify a function result value");
                    198:                                    return (NIL);
                    199:                            }
                    200:                            return (funccod((int *) r));
                    201: 
                    202:                    case TYPE:
                    203:                            error("Type names (e.g. %s) allowed only in declarations", p->symbol);
                    204:                            return (NIL);
                    205: 
                    206:                    case PROC:
                    207:                            error("Procedure %s found where expression required", p->symbol);
                    208:                            return (NIL);
                    209:                    default:
                    210:                            panic("rvid");
                    211:                }
                    212:        /*
                    213:         * Constant sets
                    214:         */
                    215:        case T_CSET:
                    216:                return (cset(r, contype, NIL));
                    217: 
                    218:        /*
                    219:         * Unary plus and minus
                    220:         */
                    221:        case T_PLUS:
                    222:        case T_MINUS:
                    223:                q = rvalue(r[2], NIL);
                    224:                if (q == NIL)
                    225:                        return (NIL);
                    226:                if (isnta(q, "id")) {
                    227:                        error("Operand of %s must be integer or real, not %s", opname, nameof(q));
                    228:                        return (NIL);
                    229:                }
                    230:                if (r[0] == T_MINUS) {
                    231:                        put1(O_NEG2 + (width(q) >> 2));
                    232:                        return (isa(q, "d") ? q : nl+T4INT);
                    233:                }
                    234:                return (q);
                    235: 
                    236:        case T_NOT:
                    237:                q = rvalue(r[2], NIL);
                    238:                if (q == NIL)
                    239:                        return (NIL);
                    240:                if (isnta(q, "b")) {
                    241:                        error("not must operate on a Boolean, not %s", nameof(q));
                    242:                        return (NIL);
                    243:                }
                    244:                put1(O_NOT);
                    245:                return (nl+T1BOOL);
                    246: 
                    247:        case T_AND:
                    248:        case T_OR:
                    249:                p = rvalue(r[2], NIL);
                    250:                p1 = rvalue(r[3], NIL);
                    251:                if (p == NIL || p1 == NIL)
                    252:                        return (NIL);
                    253:                if (isnta(p, "b")) {
                    254:                        error("Left operand of %s must be Boolean, not %s", opname, nameof(p));
                    255:                        return (NIL);
                    256:                }
                    257:                if (isnta(p1, "b")) {
                    258:                        error("Right operand of %s must be Boolean, not %s", opname, nameof(p1));
                    259:                        return (NIL);
                    260:                }
                    261:                put1(r[0] == T_AND ? O_AND : O_OR);
                    262:                return (nl+T1BOOL);
                    263: 
                    264:        case T_DIVD:
                    265:                p = rvalue(r[2], NIL);
                    266:                p1 = rvalue(r[3], NIL);
                    267:                if (p == NIL || p1 == NIL)
                    268:                        return (NIL);
                    269:                if (isnta(p, "id")) {
                    270:                        error("Left operand of / must be integer or real, not %s", nameof(p));
                    271:                        return (NIL);
                    272:                }
                    273:                if (isnta(p1, "id")) {
                    274:                        error("Right operand of / must be integer or real, not %s", nameof(p1));
                    275:                        return (NIL);
                    276:                }
                    277:                return (gen(NIL, r[0], width(p), width(p1)));
                    278: 
                    279:        case T_MULT:
                    280:        case T_SUB:
                    281:        case T_ADD:
                    282:                /*
                    283:                 * If the context hasn't told us
                    284:                 * the type and a constant set is
                    285:                 * present on the left we need to infer
                    286:                 * the type from the right if possible
                    287:                 * before generating left side code.
                    288:                 */
                    289:                if (contype == NIL && (rt = r[2]) != NIL && rt[1] == SAWCON) {
                    290:                        codeoff();
                    291:                        contype = rvalue(r[3], NIL);
                    292:                        codeon();
                    293:                        if (contype == NIL)
                    294:                                return (NIL);
                    295:                }
                    296:                p = rvalue(r[2], contype);
                    297:                p1 = rvalue(r[3], p);
                    298:                if (p == NIL || p1 == NIL)
                    299:                        return (NIL);
                    300:                if (isa(p, "id") && isa(p1, "id"))
                    301:                        return (gen(NIL, r[0], width(p), width(p1)));
                    302:                if (isa(p, "t") && isa(p1, "t")) {
                    303:                        if (p != p1) {
                    304:                                error("Set types of operands of %s must be identical", opname);
                    305:                                return (NIL);
                    306:                        }
                    307:                        gen(TSET, r[0], width(p), 0);
                    308:                        /*
                    309:                         * Note that set was filled in by the call
                    310:                         * to width above.
                    311:                         */
                    312:                        if (r[0] == T_SUB)
                    313:                                put2(NIL, 0177777 << ((set.uprbp & 017) + 1));
                    314:                        return (p);
                    315:                }
                    316:                if (isnta(p, "idt")) {
                    317:                        error("Left operand of %s must be integer, real or set, not %s", opname, nameof(p));
                    318:                        return (NIL);
                    319:                }
                    320:                if (isnta(p1, "idt")) {
                    321:                        error("Right operand of %s must be integer, real or set, not %s", opname, nameof(p1));
                    322:                        return (NIL);
                    323:                }
                    324:                error("Cannot mix sets with integers and reals as operands of %s", opname);
                    325:                return (NIL);
                    326: 
                    327:        case T_MOD:
                    328:        case T_DIV:
                    329:                p = rvalue(r[2], NIL);
                    330:                p1 = rvalue(r[3], NIL);
                    331:                if (p == NIL || p1 == NIL)
                    332:                        return (NIL);
                    333:                if (isnta(p, "i")) {
                    334:                        error("Left operand of %s must be integer, not %s", opname, nameof(p));
                    335:                        return (NIL);
                    336:                }
                    337:                if (isnta(p1, "i")) {
                    338:                        error("Right operand of %s must be integer, not %s", opname, nameof(p1));
                    339:                        return (NIL);
                    340:                }
                    341:                return (gen(NIL, r[0], width(p), width(p1)));
                    342: 
                    343:        case T_EQ:
                    344:        case T_NE:
                    345:        case T_GE:
                    346:        case T_LE:
                    347:        case T_GT:
                    348:        case T_LT:
                    349:                /*
                    350:                 * Since there can be no, a priori, knowledge
                    351:                 * of the context type should a constant string
                    352:                 * or set arise, we must poke around to find such
                    353:                 * a type if possible.  Since constant strings can
                    354:                 * always masquerade as identifiers, this is always
                    355:                 * necessary.
                    356:                 */
                    357:                codeoff();
                    358:                p1 = rvalue(r[3], NIL);
                    359:                codeon();
                    360:                if (p1 == NIL)
                    361:                        return (NIL);
                    362:                contype = p1;
                    363:                if (p1 == nl+TSET || p1->class == STR) {
                    364:                        /*
                    365:                         * For constant strings we want
                    366:                         * the longest type so as to be
                    367:                         * able to do padding (more importantly
                    368:                         * avoiding truncation). For clarity,
                    369:                         * we get this length here.
                    370:                         */
                    371:                        codeoff();
                    372:                        p = rvalue(r[2], NIL);
                    373:                        codeon();
                    374:                        if (p == NIL)
                    375:                                return (NIL);
                    376:                        if (p1 == nl+TSET || width(p) > width(p1))
                    377:                                contype = p;
                    378:                }
                    379:                /*
                    380:                 * Now we generate code for
                    381:                 * the operands of the relational
                    382:                 * operation.
                    383:                 */
                    384:                p = rvalue(r[2], contype);
                    385:                if (p == NIL)
                    386:                        return (NIL);
                    387:                p1 = rvalue(r[3], p);
                    388:                if (p1 == NIL)
                    389:                        return (NIL);
                    390:                c = classify(p);
                    391:                c1 = classify(p1);
                    392:                if (nocomp(c) || nocomp(c1))
                    393:                        return (NIL);
                    394:                g = NIL;
                    395:                switch (c) {
                    396:                        case TBOOL:
                    397:                        case TCHAR:
                    398:                                if (c != c1)
                    399:                                        goto clash;
                    400:                                break;
                    401:                        case TINT:
                    402:                        case TDOUBLE:
                    403:                                if (c1 != TINT && c1 != TDOUBLE)
                    404:                                        goto clash;
                    405:                                break;
                    406:                        case TSCAL:
                    407:                                if (c1 != TSCAL)
                    408:                                        goto clash;
                    409:                                if (scalar(p) != scalar(p1))
                    410:                                        goto nonident;
                    411:                                break;
                    412:                        case TSET:
                    413:                                if (c1 != TSET)
                    414:                                        goto clash;
                    415:                                if (p != p1)
                    416:                                        goto nonident;
                    417:                                g = TSET;
                    418:                                break;
                    419:                        case TPTR:
                    420:                        case TNIL:
                    421:                                if (c1 != TPTR && c1 != TNIL)
                    422:                                        goto clash;
                    423:                                if (r[0] != T_EQ && r[0] != T_NE) {
                    424:                                        error("%s not allowed on pointers - only allow = and <>");
                    425:                                        return (NIL);
                    426:                                }
                    427:                                break;
                    428:                        case TSTR:
                    429:                                if (c1 != TSTR)
                    430:                                        goto clash;
                    431:                                if (width(p) != width(p1)) {
                    432:                                        error("Strings not same length in %s comparison", opname);
                    433:                                        return (NIL);
                    434:                                }
                    435:                                g = TSTR;
                    436:                                break;
                    437:                        default:
                    438:                                panic("rval2");
                    439:                }
                    440:                return (gen(g, r[0], width(p), width(p1)));
                    441: clash:
                    442:                error("%ss and %ss cannot be compared - operator was %s", clnames[c], clnames[c1], opname);
                    443:                return (NIL);
                    444: nonident:
                    445:                error("%s types must be identical in comparisons - operator was %s", clnames[c1], opname);
                    446:                return (NIL);
                    447: 
                    448:        case T_IN:
                    449:                rt = r[3];
                    450:                if (rt != NIL && rt[0] == T_CSET)
                    451:                        p1 = cset(rt, NLNIL, 1);
                    452:                else {
                    453:                        p1 = rvalue(r[3], NIL);
                    454:                        rt = NIL;
                    455:                }
                    456:                if (p1 == nl+TSET) {
                    457:                        warning();
                    458:                        error("... in [] makes little sense, since it is always false!");
                    459:                        put1(O_CON1, 0);
                    460:                        return (nl+T1BOOL);
                    461:                }
                    462:                p = rvalue(r[2], NIL);
                    463:                if (p == NIL || p1 == NIL)
                    464:                        return (NIL);
                    465:                if (p1->class != SET) {
                    466:                        error("Right operand of 'in' must be a set, not %s", nameof(p1));
                    467:                        return (NIL);
                    468:                }
                    469:                if (incompat(p, p1->type, r[2])) {
                    470:                        cerror("Index type clashed with set component type for 'in'");
                    471:                        return (NIL);
                    472:                }
                    473:                convert(p, nl+T2INT);
                    474:                setran(p1->type);
                    475:                if (rt == NIL)
                    476:                        put4(O_IN, width(p1), set.lwrb, set.uprbp);
                    477:                else
                    478:                        put1(O_INCT);
                    479:                return (nl+T1BOOL);
                    480: 
                    481:        default:
                    482:                if (r[2] == NIL)
                    483:                        return (NIL);
                    484:                switch (r[0]) {
                    485:                default:
                    486:                        panic("rval3");
                    487: 
                    488: 
                    489:                /*
                    490:                 * An octal number
                    491:                 */
                    492:                case T_BINT:
                    493:                        f = a8tol(r[2]);
                    494:                        goto conint;
                    495:        
                    496:                /*
                    497:                 * A decimal number
                    498:                 */
                    499:                case T_INT:
                    500:                        f = atof(r[2]);
                    501: conint:
                    502:                        if (f > MAXINT || f < MININT) {
                    503:                                error("Constant too large for this implementation");
                    504:                                return (NIL);
                    505:                        }
                    506:                        l = f;
                    507:                        if (bytes(l, l) <= 2) {
                    508:                                put2(O_CON2, ( short ) l);
                    509:                                return (nl+T2INT);
                    510:                        }
                    511:                        put( 3 , O_CON4, l); 
                    512:                        return (nl+T4INT);
                    513:        
                    514:                /*
                    515:                 * A floating point number
                    516:                 */
                    517:                case T_FINT:
                    518:                        put(5, O_CON8, atof(r[2]));
                    519:                        return (nl+TDOUBLE);
                    520:        
                    521:                /*
                    522:                 * Constant strings.  Note that constant characters
                    523:                 * are constant strings of length one; there is
                    524:                 * no constant string of length one.
                    525:                 */
                    526:                case T_STRNG:
                    527:                        cp = r[2];
                    528:                        if (cp[1] == 0) {
                    529:                                put2(O_CONC, cp[0]);
                    530:                                return (nl+T1CHAR);
                    531:                        }
                    532:                        goto cstrng;
                    533:                }
                    534:        
                    535:        }
                    536: }
                    537: 
                    538: /*
                    539:  * Can a class appear
                    540:  * in a comparison ?
                    541:  */
                    542: nocomp(c)
                    543:        int c;
                    544: {
                    545: 
                    546:        switch (c) {
                    547:                case TFILE:
                    548:                case TARY:
                    549:                case TREC:
                    550:                        error("%ss may not participate in comparisons", clnames[c]);
                    551:                        return (1);
                    552:        }
                    553:        return (NIL);
                    554: }

unix.superglobalmegacorp.com

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