Annotation of 3BSD/cmd/pi/rval.c, revision 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.