Annotation of 43BSDReno/pgrm/pascal/src/rval.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1980 Regents of the University of California.
        !             3:  * All rights reserved.  The Berkeley software License Agreement
        !             4:  * specifies the terms and conditions for redistribution.
        !             5:  */
        !             6: 
        !             7: #ifndef lint
        !             8: static char sccsid[] = "@(#)rval.c     5.2 (Berkeley) 4/7/87";
        !             9: #endif not lint
        !            10: 
        !            11: #include "whoami.h"
        !            12: #include "0.h"
        !            13: #include "tree.h"
        !            14: #include "opcode.h"
        !            15: #include "objfmt.h"
        !            16: #ifdef PC
        !            17: #   include    "pc.h"
        !            18: #   include <pcc.h>
        !            19: #endif PC
        !            20: #include "tmps.h"
        !            21: #include "tree_ty.h"
        !            22: 
        !            23: extern char *opnames[];
        !            24: 
        !            25:     /* line number of the last record comparison warning */
        !            26: short reccompline = 0;
        !            27:     /* line number of the last non-standard set comparison */
        !            28: short nssetline = 0;
        !            29: 
        !            30: #ifdef PC
        !            31:     char       *relts[] =  {
        !            32:                                "_RELEQ" , "_RELNE" ,
        !            33:                                "_RELTLT" , "_RELTGT" ,
        !            34:                                "_RELTLE" , "_RELTGE"
        !            35:                            };
        !            36:     char       *relss[] =  {
        !            37:                                "_RELEQ" , "_RELNE" ,
        !            38:                                "_RELSLT" , "_RELSGT" ,
        !            39:                                "_RELSLE" , "_RELSGE"
        !            40:                            };
        !            41:     long       relops[] =  {   
        !            42:                                PCC_EQ , PCC_NE ,
        !            43:                                PCC_LT , PCC_GT ,
        !            44:                                PCC_LE , PCC_GE 
        !            45:                            };
        !            46:     long       mathop[] =  {   PCC_MUL , PCC_PLUS , PCC_MINUS };
        !            47:     char       *setop[] =  {   "_MULT" , "_ADDT" , "_SUBT" };
        !            48: #endif PC
        !            49: /*
        !            50:  * Rvalue - an expression.
        !            51:  *
        !            52:  * Contype is the type that the caller would prefer, nand is important
        !            53:  * if constant strings are involved, because of string padding.
        !            54:  * required is a flag whether an lvalue or an rvalue is required.
        !            55:  * only VARs and structured things can have gt their lvalue this way.
        !            56:  */
        !            57: /*ARGSUSED*/
        !            58: struct nl *
        !            59: rvalue(r, contype , required )
        !            60:        struct tnode *r;
        !            61:        struct nl *contype;
        !            62:        int     required;
        !            63: {
        !            64:        register struct nl *p, *p1;
        !            65:        register struct nl *q;
        !            66:        int c, c1, w;
        !            67: #ifdef OBJ
        !            68:        int g;
        !            69: #endif
        !            70:        struct tnode *rt;
        !            71:        char *cp, *cp1, *opname;
        !            72:        long l;
        !            73:        union
        !            74:        {
        !            75:            long plong[2];
        !            76:            double pdouble;
        !            77:        }f;
        !            78:        extern int      flagwas;
        !            79:        struct csetstr  csetd;
        !            80: #      ifdef PC
        !            81:            struct nl   *rettype;
        !            82:            long        ctype;
        !            83:            struct nl   *tempnlp;
        !            84: #      endif PC
        !            85: 
        !            86:        if (r == TR_NIL)
        !            87:                return (NLNIL);
        !            88:        if (nowexp(r))
        !            89:                return (NLNIL);
        !            90:        /*
        !            91:         * Pick up the name of the operation
        !            92:         * for future error messages.
        !            93:         */
        !            94:        if (r->tag <= T_IN)
        !            95:                opname = opnames[r->tag];
        !            96: 
        !            97:        /*
        !            98:         * The root of the tree tells us what sort of expression we have.
        !            99:         */
        !           100:        switch (r->tag) {
        !           101: 
        !           102:        /*
        !           103:         * The constant nil
        !           104:         */
        !           105:        case T_NIL:
        !           106: #              ifdef OBJ
        !           107:                    (void) put(2, O_CON2, 0);
        !           108: #              endif OBJ
        !           109: #              ifdef PC
        !           110:                    putleaf( PCC_ICON , 0 , 0 , PCCTM_PTR|PCCT_UNDEF , (char *) 0 );
        !           111: #              endif PC
        !           112:                return (nl+TNIL);
        !           113: 
        !           114:        /*
        !           115:         * Function call with arguments.
        !           116:         */
        !           117:        case T_FCALL:
        !           118: #          ifdef OBJ
        !           119:                return (funccod(r));
        !           120: #          endif OBJ
        !           121: #          ifdef PC
        !           122:                return (pcfunccod( r ));
        !           123: #          endif PC
        !           124: 
        !           125:        case T_VAR:
        !           126:                p = lookup(r->var_node.cptr);
        !           127:                if (p == NLNIL || p->class == BADUSE)
        !           128:                        return (NLNIL);
        !           129:                switch (p->class) {
        !           130:                    case VAR:
        !           131:                            /*
        !           132:                             * If a variable is
        !           133:                             * qualified then get
        !           134:                             * the rvalue by a
        !           135:                             * lvalue and an ind.
        !           136:                             */
        !           137:                            if (r->var_node.qual != TR_NIL)
        !           138:                                    goto ind;
        !           139:                            q = p->type;
        !           140:                            if (q == NIL)
        !           141:                                    return (NLNIL);
        !           142: #                          ifdef OBJ
        !           143:                                w = width(q);
        !           144:                                switch (w) {
        !           145:                                    case 8:
        !           146:                                        (void) put(2, O_RV8 | bn << 8+INDX,
        !           147:                                                (int)p->value[0]);
        !           148:                                        break;
        !           149:                                    case 4:
        !           150:                                        (void) put(2, O_RV4 | bn << 8+INDX,
        !           151:                                                (int)p->value[0]);
        !           152:                                        break;
        !           153:                                    case 2:
        !           154:                                        (void) put(2, O_RV2 | bn << 8+INDX,
        !           155:                                                (int)p->value[0]);
        !           156:                                        break;
        !           157:                                    case 1:
        !           158:                                        (void) put(2, O_RV1 | bn << 8+INDX,
        !           159:                                                (int)p->value[0]);
        !           160:                                        break;
        !           161:                                    default:
        !           162:                                        (void) put(3, O_RV | bn << 8+INDX,
        !           163:                                                (int)p->value[0], w);
        !           164:                                }
        !           165: #                         endif OBJ
        !           166: #                         ifdef PC
        !           167:                                if ( required == RREQ ) {
        !           168:                                    putRV( p -> symbol , bn , p -> value[0] ,
        !           169:                                            p -> extra_flags , p2type( q ) );
        !           170:                                } else {
        !           171:                                    putLV( p -> symbol , bn , p -> value[0] ,
        !           172:                                            p -> extra_flags , p2type( q ) );
        !           173:                                }
        !           174: #                         endif PC
        !           175:                           return (q);
        !           176: 
        !           177:                    case WITHPTR:
        !           178:                    case REF:
        !           179:                            /*
        !           180:                             * A lvalue for these
        !           181:                             * is actually what one
        !           182:                             * might consider a rvalue.
        !           183:                             */
        !           184: ind:
        !           185:                            q = lvalue(r, NOFLAGS , LREQ );
        !           186:                            if (q == NIL)
        !           187:                                    return (NLNIL);
        !           188: #                          ifdef OBJ
        !           189:                                w = width(q);
        !           190:                                switch (w) {
        !           191:                                    case 8:
        !           192:                                            (void) put(1, O_IND8);
        !           193:                                            break;
        !           194:                                    case 4:
        !           195:                                            (void) put(1, O_IND4);
        !           196:                                            break;
        !           197:                                    case 2:
        !           198:                                            (void) put(1, O_IND2);
        !           199:                                            break;
        !           200:                                    case 1:
        !           201:                                            (void) put(1, O_IND1);
        !           202:                                            break;
        !           203:                                    default:
        !           204:                                            (void) put(2, O_IND, w);
        !           205:                                }
        !           206: #                          endif OBJ
        !           207: #                          ifdef PC
        !           208:                                if ( required == RREQ ) {
        !           209:                                    putop( PCCOM_UNARY PCC_MUL , p2type( q ) );
        !           210:                                }
        !           211: #                          endif PC
        !           212:                            return (q);
        !           213: 
        !           214:                    case CONST:
        !           215:                            if (r->var_node.qual != TR_NIL) {
        !           216:                                error("%s is a constant and cannot be qualified", r->var_node.cptr);
        !           217:                                return (NLNIL);
        !           218:                            }
        !           219:                            q = p->type;
        !           220:                            if (q == NLNIL)
        !           221:                                    return (NLNIL);
        !           222:                            if (q == nl+TSTR) {
        !           223:                                    /*
        !           224:                                     * Find the size of the string
        !           225:                                     * constant if needed.
        !           226:                                     */
        !           227:                                    cp = (char *) p->ptr[0];
        !           228: cstrng:
        !           229:                                    cp1 = cp;
        !           230:                                    for (c = 0; *cp++; c++)
        !           231:                                            continue;
        !           232:                                    w = c;
        !           233:                                    if (contype != NIL && !opt('s')) {
        !           234:                                            if (width(contype) < c && classify(contype) == TSTR) {
        !           235:                                                    error("Constant string too long");
        !           236:                                                    return (NLNIL);
        !           237:                                            }
        !           238:                                            w = width(contype);
        !           239:                                    }
        !           240: #                                  ifdef OBJ
        !           241:                                        (void) put(2, O_CONG, w);
        !           242:                                        putstr(cp1, w - c);
        !           243: #                                  endif OBJ
        !           244: #                                  ifdef PC
        !           245:                                        putCONG( cp1 , w , required );
        !           246: #                                  endif PC
        !           247:                                    /*
        !           248:                                     * Define the string temporarily
        !           249:                                     * so later people can know its
        !           250:                                     * width.
        !           251:                                     * cleaned out by stat.
        !           252:                                     */
        !           253:                                    q = defnl((char *) 0, STR, NLNIL, w);
        !           254:                                    q->type = q;
        !           255:                                    return (q);
        !           256:                            }
        !           257:                            if (q == nl+T1CHAR) {
        !           258: #                                  ifdef OBJ
        !           259:                                        (void) put(2, O_CONC, (int)p->value[0]);
        !           260: #                                  endif OBJ
        !           261: #                                  ifdef PC
        !           262:                                        putleaf( PCC_ICON , p -> value[0] , 0
        !           263:                                                , PCCT_CHAR , (char *) 0 );
        !           264: #                                  endif PC
        !           265:                                    return (q);
        !           266:                            }
        !           267:                            /*
        !           268:                             * Every other kind of constant here
        !           269:                             */
        !           270:                            switch (width(q)) {
        !           271:                            case 8:
        !           272: #ifndef DEBUG
        !           273: #                                  ifdef OBJ
        !           274:                                        (void) put(2, O_CON8, p->real);
        !           275: #                                  endif OBJ
        !           276: #                                  ifdef PC
        !           277:                                        putCON8( p -> real );
        !           278: #                                  endif PC
        !           279: #else
        !           280:                                    if (hp21mx) {
        !           281:                                            f.pdouble = p->real;
        !           282:                                            conv((int *) (&f.pdouble));
        !           283:                                            l = f.plong[1];
        !           284:                                            (void) put(2, O_CON4, l);
        !           285:                                    } else
        !           286: #                                          ifdef OBJ
        !           287:                                                (void) put(2, O_CON8, p->real);
        !           288: #                                          endif OBJ
        !           289: #                                          ifdef PC
        !           290:                                                putCON8( p -> real );
        !           291: #                                          endif PC
        !           292: #endif
        !           293:                                    break;
        !           294:                            case 4:
        !           295: #                                  ifdef OBJ
        !           296:                                        (void) put(2, O_CON4, p->range[0]);
        !           297: #                                  endif OBJ
        !           298: #                                  ifdef PC
        !           299:                                        putleaf( PCC_ICON , (int) p->range[0] , 0
        !           300:                                                , PCCT_INT , (char *) 0 );
        !           301: #                                  endif PC
        !           302:                                    break;
        !           303:                            case 2:
        !           304: #                                  ifdef OBJ
        !           305:                                        (void) put(2, O_CON2, (short)p->range[0]);
        !           306: #                                  endif OBJ
        !           307: #                                  ifdef PC
        !           308:                                        putleaf( PCC_ICON , (short) p -> range[0]
        !           309:                                                , 0 , PCCT_SHORT , (char *) 0 );
        !           310: #                                  endif PC
        !           311:                                    break;
        !           312:                            case 1:
        !           313: #                                  ifdef OBJ
        !           314:                                        (void) put(2, O_CON1, p->value[0]);
        !           315: #                                  endif OBJ
        !           316: #                                  ifdef PC
        !           317:                                        putleaf( PCC_ICON , p -> value[0] , 0
        !           318:                                                , PCCT_CHAR , (char *) 0 );
        !           319: #                                  endif PC
        !           320:                                    break;
        !           321:                            default:
        !           322:                                    panic("rval");
        !           323:                            }
        !           324:                            return (q);
        !           325: 
        !           326:                    case FUNC:
        !           327:                    case FFUNC:
        !           328:                            /*
        !           329:                             * Function call with no arguments.
        !           330:                             */
        !           331:                            if (r->var_node.qual != TR_NIL) {
        !           332:                                    error("Can't qualify a function result value");
        !           333:                                    return (NLNIL);
        !           334:                            }
        !           335: #                          ifdef OBJ
        !           336:                                return (funccod(r));
        !           337: #                          endif OBJ
        !           338: #                          ifdef PC
        !           339:                                return (pcfunccod( r ));
        !           340: #                          endif PC
        !           341: 
        !           342:                    case TYPE:
        !           343:                            error("Type names (e.g. %s) allowed only in declarations", p->symbol);
        !           344:                            return (NLNIL);
        !           345: 
        !           346:                    case PROC:
        !           347:                    case FPROC:
        !           348:                            error("Procedure %s found where expression required", p->symbol);
        !           349:                            return (NLNIL);
        !           350:                    default:
        !           351:                            panic("rvid");
        !           352:                }
        !           353:        /*
        !           354:         * Constant sets
        !           355:         */
        !           356:        case T_CSET:
        !           357: #              ifdef OBJ
        !           358:                    if ( precset( r , contype , &csetd ) ) {
        !           359:                        if ( csetd.csettype == NIL ) {
        !           360:                            return (NLNIL);
        !           361:                        }
        !           362:                        postcset( r , &csetd );
        !           363:                    } else {
        !           364:                        (void) put( 2, O_PUSH, -lwidth(csetd.csettype));
        !           365:                        postcset( r , &csetd );
        !           366:                        setran( ( csetd.csettype ) -> type );
        !           367:                        (void) put( 2, O_CON24, set.uprbp);
        !           368:                        (void) put( 2, O_CON24, set.lwrb);
        !           369:                        (void) put( 2, O_CTTOT,
        !           370:                                (int)(4 + csetd.singcnt + 2 * csetd.paircnt));
        !           371:                    }
        !           372:                    return csetd.csettype;
        !           373: #              endif OBJ
        !           374: #              ifdef PC
        !           375:                    if ( precset( r , contype , &csetd ) ) {
        !           376:                        if ( csetd.csettype == NIL ) {
        !           377:                            return (NLNIL);
        !           378:                        }
        !           379:                        postcset( r , &csetd );
        !           380:                    } else {
        !           381:                        putleaf( PCC_ICON , 0 , 0
        !           382:                                , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
        !           383:                                , "_CTTOT" );
        !           384:                        /*
        !           385:                         *      allocate a temporary and use it
        !           386:                         */
        !           387:                        tempnlp = tmpalloc(lwidth(csetd.csettype),
        !           388:                                csetd.csettype, NOREG);
        !           389:                        putLV( (char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] ,
        !           390:                                tempnlp -> extra_flags , PCCTM_PTR|PCCT_STRTY );
        !           391:                        setran( ( csetd.csettype ) -> type );
        !           392:                        putleaf( PCC_ICON , set.lwrb , 0 , PCCT_INT , (char *) 0 );
        !           393:                        putop( PCC_CM , PCCT_INT );
        !           394:                        putleaf( PCC_ICON , set.uprbp , 0 , PCCT_INT , (char *) 0 );
        !           395:                        putop( PCC_CM , PCCT_INT );
        !           396:                        postcset( r , &csetd );
        !           397:                        putop( PCC_CALL , PCCT_INT );
        !           398:                    }
        !           399:                    return csetd.csettype;
        !           400: #              endif PC
        !           401: 
        !           402:        /*
        !           403:         * Unary plus and minus
        !           404:         */
        !           405:        case T_PLUS:
        !           406:        case T_MINUS:
        !           407:                q = rvalue(r->un_expr.expr, NLNIL , RREQ );
        !           408:                if (q == NLNIL)
        !           409:                        return (NLNIL);
        !           410:                if (isnta(q, "id")) {
        !           411:                        error("Operand of %s must be integer or real, not %s", opname, nameof(q));
        !           412:                        return (NLNIL);
        !           413:                }
        !           414:                if (r->tag == T_MINUS) {
        !           415: #                  ifdef OBJ
        !           416:                        (void) put(1, O_NEG2 + (width(q) >> 2));
        !           417:                        return (isa(q, "d") ? q : nl+T4INT);
        !           418: #                  endif OBJ
        !           419: #                  ifdef PC
        !           420:                        if (isa(q, "i")) {
        !           421:                            sconv(p2type(q), PCCT_INT);
        !           422:                            putop( PCCOM_UNARY PCC_MINUS, PCCT_INT);
        !           423:                            return nl+T4INT;
        !           424:                        }
        !           425:                        putop( PCCOM_UNARY PCC_MINUS, PCCT_DOUBLE);
        !           426:                        return nl+TDOUBLE;
        !           427: #                  endif PC
        !           428:                }
        !           429:                return (q);
        !           430: 
        !           431:        case T_NOT:
        !           432:                q = rvalue(r->un_expr.expr, NLNIL , RREQ );
        !           433:                if (q == NLNIL)
        !           434:                        return (NLNIL);
        !           435:                if (isnta(q, "b")) {
        !           436:                        error("not must operate on a Boolean, not %s", nameof(q));
        !           437:                        return (NLNIL);
        !           438:                }
        !           439: #              ifdef OBJ
        !           440:                    (void) put(1, O_NOT);
        !           441: #              endif OBJ
        !           442: #              ifdef PC
        !           443:                    sconv(p2type(q), PCCT_INT);
        !           444:                    putop( PCC_NOT , PCCT_INT);
        !           445:                    sconv(PCCT_INT, p2type(q));
        !           446: #              endif PC
        !           447:                return (nl+T1BOOL);
        !           448: 
        !           449:        case T_AND:
        !           450:        case T_OR:
        !           451:                p = rvalue(r->expr_node.lhs, NLNIL , RREQ );
        !           452: #              ifdef PC
        !           453:                    sconv(p2type(p),PCCT_INT);
        !           454: #              endif PC
        !           455:                p1 = rvalue(r->expr_node.rhs, NLNIL , RREQ );
        !           456: #              ifdef PC
        !           457:                    sconv(p2type(p1),PCCT_INT);
        !           458: #              endif PC
        !           459:                if (p == NLNIL || p1 == NLNIL)
        !           460:                        return (NLNIL);
        !           461:                if (isnta(p, "b")) {
        !           462:                        error("Left operand of %s must be Boolean, not %s", opname, nameof(p));
        !           463:                        return (NLNIL);
        !           464:                }
        !           465:                if (isnta(p1, "b")) {
        !           466:                        error("Right operand of %s must be Boolean, not %s", opname, nameof(p1));
        !           467:                        return (NLNIL);
        !           468:                }
        !           469: #              ifdef OBJ
        !           470:                    (void) put(1, r->tag == T_AND ? O_AND : O_OR);
        !           471: #              endif OBJ
        !           472: #              ifdef PC
        !           473:                        /*
        !           474:                         * note the use of & and | rather than && and ||
        !           475:                         * to force evaluation of all the expressions.
        !           476:                         */
        !           477:                    putop( r->tag == T_AND ? PCC_AND : PCC_OR , PCCT_INT );
        !           478:                    sconv(PCCT_INT, p2type(p));
        !           479: #              endif PC
        !           480:                return (nl+T1BOOL);
        !           481: 
        !           482:        case T_DIVD:
        !           483: #              ifdef OBJ
        !           484:                    p = rvalue(r->expr_node.lhs, NLNIL , RREQ );
        !           485:                    p1 = rvalue(r->expr_node.rhs, NLNIL , RREQ );
        !           486: #              endif OBJ
        !           487: #              ifdef PC
        !           488:                        /*
        !           489:                         *      force these to be doubles for the divide
        !           490:                         */
        !           491:                    p = rvalue( r->expr_node.lhs , NLNIL , RREQ );
        !           492:                    sconv(p2type(p), PCCT_DOUBLE);
        !           493:                    p1 = rvalue( r->expr_node.rhs , NLNIL , RREQ );
        !           494:                    sconv(p2type(p1), PCCT_DOUBLE);
        !           495: #              endif PC
        !           496:                if (p == NLNIL || p1 == NLNIL)
        !           497:                        return (NLNIL);
        !           498:                if (isnta(p, "id")) {
        !           499:                        error("Left operand of / must be integer or real, not %s", nameof(p));
        !           500:                        return (NLNIL);
        !           501:                }
        !           502:                if (isnta(p1, "id")) {
        !           503:                        error("Right operand of / must be integer or real, not %s", nameof(p1));
        !           504:                        return (NLNIL);
        !           505:                }
        !           506: #              ifdef OBJ
        !           507:                    return gen(NIL, r->tag, width(p), width(p1));
        !           508: #              endif OBJ
        !           509: #              ifdef PC
        !           510:                    putop( PCC_DIV , PCCT_DOUBLE );
        !           511:                    return nl + TDOUBLE;
        !           512: #              endif PC
        !           513: 
        !           514:        case T_MULT:
        !           515:        case T_ADD:
        !           516:        case T_SUB:
        !           517: #              ifdef OBJ
        !           518:                    /*
        !           519:                     * get the type of the right hand side.
        !           520:                     * if it turns out to be a set,
        !           521:                     * use that type when getting
        !           522:                     * the type of the left hand side.
        !           523:                     * and then use the type of the left hand side
        !           524:                     * when generating code.
        !           525:                     * this will correctly decide the type of any
        !           526:                     * empty sets in the tree, since if the empty set 
        !           527:                     * is on the left hand side it will inherit
        !           528:                     * the type of the right hand side,
        !           529:                     * and if it's on the right hand side, its type (intset)
        !           530:                     * will be overridden by the type of the left hand side.
        !           531:                     * this is an awful lot of tree traversing, 
        !           532:                     * but it works.
        !           533:                     */
        !           534:                    codeoff();
        !           535:                    p1 = rvalue( r->expr_node.rhs , NLNIL , RREQ );
        !           536:                    codeon();
        !           537:                    if ( p1 == NLNIL ) {
        !           538:                        return NLNIL;
        !           539:                    }
        !           540:                    if (isa(p1, "t")) {
        !           541:                        codeoff();
        !           542:                        contype = rvalue(r->expr_node.lhs, p1, RREQ);
        !           543:                        codeon();
        !           544:                        if (contype == NLNIL) {
        !           545:                            return NLNIL;
        !           546:                        }
        !           547:                    }
        !           548:                    p = rvalue( r->expr_node.lhs , contype , RREQ );
        !           549:                    p1 = rvalue( r->expr_node.rhs , p , RREQ );
        !           550:                    if ( p == NLNIL || p1 == NLNIL )
        !           551:                            return NLNIL;
        !           552:                    if (isa(p, "id") && isa(p1, "id"))
        !           553:                        return (gen(NIL, r->tag, width(p), width(p1)));
        !           554:                    if (isa(p, "t") && isa(p1, "t")) {
        !           555:                            if (p != p1) {
        !           556:                                    error("Set types of operands of %s must be identical", opname);
        !           557:                                    return (NLNIL);
        !           558:                            }
        !           559:                            (void) gen(TSET, r->tag, width(p), 0);
        !           560:                            return (p);
        !           561:                    }
        !           562: #              endif OBJ
        !           563: #              ifdef PC
        !           564:                        /*
        !           565:                         * the second pass can't do
        !           566:                         *      long op double  or  double op long
        !           567:                         * so we have to know the type of both operands.
        !           568:                         * also, see the note for obj above on determining
        !           569:                         * the type of empty sets.
        !           570:                         */
        !           571:                    codeoff();
        !           572:                    p1 = rvalue(r->expr_node.rhs, NLNIL, RREQ);
        !           573:                    codeon();
        !           574:                    if ( isa( p1 , "id" ) ) {
        !           575:                        p = rvalue( r->expr_node.lhs , contype , RREQ );
        !           576:                        if ( ( p == NLNIL ) || ( p1 == NLNIL ) ) {
        !           577:                            return NLNIL;
        !           578:                        }
        !           579:                        tuac(p, p1, &rettype, (int *) (&ctype));
        !           580:                        p1 = rvalue( r->expr_node.rhs , contype , RREQ );
        !           581:                        tuac(p1, p, &rettype, (int *) (&ctype));
        !           582:                        if ( isa( p , "id" ) ) {
        !           583:                            putop( (int) mathop[r->tag - T_MULT], (int) ctype);
        !           584:                            return rettype;
        !           585:                        }
        !           586:                    }
        !           587:                    if ( isa( p1 , "t" ) ) {
        !           588:                        putleaf( PCC_ICON , 0 , 0
        !           589:                            , PCCM_ADDTYPE( PCCM_ADDTYPE( PCCTM_PTR | PCCT_STRTY , PCCTM_FTN )
        !           590:                                        , PCCTM_PTR )
        !           591:                            , setop[ r->tag - T_MULT ] );
        !           592:                        codeoff();
        !           593:                        contype = rvalue( r->expr_node.lhs, p1 , LREQ );
        !           594:                        codeon();
        !           595:                        if ( contype == NLNIL ) {
        !           596:                            return NLNIL;
        !           597:                        }
        !           598:                            /*
        !           599:                             *  allocate a temporary and use it
        !           600:                             */
        !           601:                        tempnlp = tmpalloc(lwidth(contype), contype, NOREG);
        !           602:                        putLV((char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] ,
        !           603:                                tempnlp -> extra_flags , PCCTM_PTR|PCCT_STRTY );
        !           604:                        p = rvalue( r->expr_node.lhs , contype , LREQ );
        !           605:                        if ( isa( p , "t" ) ) {
        !           606:                            putop( PCC_CM , PCCT_INT );
        !           607:                            if ( p == NLNIL || p1 == NLNIL ) {
        !           608:                                return NLNIL;
        !           609:                            }
        !           610:                            p1 = rvalue( r->expr_node.rhs , p , LREQ );
        !           611:                            if ( p != p1 ) {
        !           612:                                error("Set types of operands of %s must be identical", opname);
        !           613:                                return NLNIL;
        !           614:                            }
        !           615:                            putop( PCC_CM , PCCT_INT );
        !           616:                            putleaf( PCC_ICON , (int) (lwidth(p1)) / sizeof( long ) , 0
        !           617:                                    , PCCT_INT , (char *) 0 );
        !           618:                            putop( PCC_CM , PCCT_INT );
        !           619:                            putop( PCC_CALL , PCCTM_PTR | PCCT_STRTY );
        !           620:                            return p;
        !           621:                        }
        !           622:                    }
        !           623:                    if ( isnta( p1 , "idt" ) ) {
        !           624:                            /*
        !           625:                             *  find type of left operand for error message.
        !           626:                             */
        !           627:                        p = rvalue( r->expr_node.lhs , contype , RREQ );
        !           628:                    }
        !           629:                        /*
        !           630:                         *      don't give spurious error messages.
        !           631:                         */
        !           632:                    if ( p == NLNIL || p1 == NLNIL ) {
        !           633:                        return NLNIL;
        !           634:                    }
        !           635: #              endif PC
        !           636:                if (isnta(p, "idt")) {
        !           637:                        error("Left operand of %s must be integer, real or set, not %s", opname, nameof(p));
        !           638:                        return (NLNIL);
        !           639:                }
        !           640:                if (isnta(p1, "idt")) {
        !           641:                        error("Right operand of %s must be integer, real or set, not %s", opname, nameof(p1));
        !           642:                        return (NLNIL);
        !           643:                }
        !           644:                error("Cannot mix sets with integers and reals as operands of %s", opname);
        !           645:                return (NLNIL);
        !           646: 
        !           647:        case T_MOD:
        !           648:        case T_DIV:
        !           649:                p = rvalue(r->expr_node.lhs, NLNIL , RREQ );
        !           650: #              ifdef PC
        !           651:                    sconv(p2type(p), PCCT_INT);
        !           652: #              ifdef tahoe
        !           653:                    /* prepare for ediv workaround, see below. */
        !           654:                    if (r->tag == T_MOD) {
        !           655:                        (void) rvalue(r->expr_node.lhs, NLNIL, RREQ);
        !           656:                        sconv(p2type(p), PCCT_INT);
        !           657:                    }
        !           658: #              endif tahoe
        !           659: #              endif PC
        !           660:                p1 = rvalue(r->expr_node.rhs, NLNIL , RREQ );
        !           661: #              ifdef PC
        !           662:                    sconv(p2type(p1), PCCT_INT);
        !           663: #              endif PC
        !           664:                if (p == NLNIL || p1 == NLNIL)
        !           665:                        return (NLNIL);
        !           666:                if (isnta(p, "i")) {
        !           667:                        error("Left operand of %s must be integer, not %s", opname, nameof(p));
        !           668:                        return (NLNIL);
        !           669:                }
        !           670:                if (isnta(p1, "i")) {
        !           671:                        error("Right operand of %s must be integer, not %s", opname, nameof(p1));
        !           672:                        return (NLNIL);
        !           673:                }
        !           674: #              ifdef OBJ
        !           675:                    return (gen(NIL, r->tag, width(p), width(p1)));
        !           676: #              endif OBJ
        !           677: #              ifdef PC
        !           678: #              ifndef tahoe
        !           679:                    putop( r->tag == T_DIV ? PCC_DIV : PCC_MOD , PCCT_INT );
        !           680:                    return ( nl + T4INT );
        !           681: #              else tahoe
        !           682:                    putop( PCC_DIV , PCCT_INT );
        !           683:                    if (r->tag == T_MOD) {
        !           684:                    /*
        !           685:                     * avoid f1 bug: PCC_MOD would generate an 'ediv',
        !           686:                     * which would reuire too many registers to evaluate
        !           687:                     * things like
        !           688:                     * var i:boolean;j:integer; i := (j+1) = (j mod 2);
        !           689:                     * so, instead of
        !           690:                     *                PCC_MOD
        !           691:                     *                  / \
        !           692:                     *                 p   p1
        !           693:                     * we put
        !           694:                     *                  PCC_MINUS
        !           695:                     *                    /   \
        !           696:                     *                   p   PCC_MUL               
        !           697:                     *                        /   \
        !           698:                     *                    PCC_DIV  p1
        !           699:                     *                      / \
        !           700:                     *                     p  p1
        !           701:                     *
        !           702:                     * we already have put p, p, p1, PCC_DIV. and now...
        !           703:                     */
        !           704:                            rvalue(r->expr_node.rhs, NLNIL , RREQ );
        !           705:                            sconv(p2type(p1), PCCT_INT);
        !           706:                            putop( PCC_MUL, PCCT_INT );
        !           707:                            putop( PCC_MINUS, PCCT_INT );
        !           708:                    }
        !           709:                    return ( nl + T4INT );
        !           710: #              endif tahoe
        !           711: #              endif PC
        !           712: 
        !           713:        case T_EQ:
        !           714:        case T_NE:
        !           715:        case T_LT:
        !           716:        case T_GT:
        !           717:        case T_LE:
        !           718:        case T_GE:
        !           719:                /*
        !           720:                 * Since there can be no, a priori, knowledge
        !           721:                 * of the context type should a constant string
        !           722:                 * or set arise, we must poke around to find such
        !           723:                 * a type if possible.  Since constant strings can
        !           724:                 * always masquerade as identifiers, this is always
        !           725:                 * necessary.
        !           726:                 * see the note in the obj section of case T_MULT above
        !           727:                 * for the determination of the base type of empty sets.
        !           728:                 */
        !           729:                codeoff();
        !           730:                p1 = rvalue(r->expr_node.rhs, NLNIL , RREQ );
        !           731:                codeon();
        !           732:                if (p1 == NLNIL)
        !           733:                        return (NLNIL);
        !           734:                contype = p1;
        !           735: #              ifdef OBJ
        !           736:                    if (p1->class == STR) {
        !           737:                            /*
        !           738:                             * For constant strings we want
        !           739:                             * the longest type so as to be
        !           740:                             * able to do padding (more importantly
        !           741:                             * avoiding truncation). For clarity,
        !           742:                             * we get this length here.
        !           743:                             */
        !           744:                            codeoff();
        !           745:                            p = rvalue(r->expr_node.lhs, NLNIL , RREQ );
        !           746:                            codeon();
        !           747:                            if (p == NLNIL)
        !           748:                                    return (NLNIL);
        !           749:                            if (width(p) > width(p1))
        !           750:                                    contype = p;
        !           751:                    }
        !           752:                    if (isa(p1, "t")) {
        !           753:                        codeoff();
        !           754:                        contype = rvalue(r->expr_node.lhs, p1, RREQ);
        !           755:                        codeon();
        !           756:                        if (contype == NLNIL) {
        !           757:                            return NLNIL;
        !           758:                        }
        !           759:                    }
        !           760:                    /*
        !           761:                     * Now we generate code for
        !           762:                     * the operands of the relational
        !           763:                     * operation.
        !           764:                     */
        !           765:                    p = rvalue(r->expr_node.lhs, contype , RREQ );
        !           766:                    if (p == NLNIL)
        !           767:                            return (NLNIL);
        !           768:                    p1 = rvalue(r->expr_node.rhs, p , RREQ );
        !           769:                    if (p1 == NLNIL)
        !           770:                            return (NLNIL);
        !           771: #              endif OBJ
        !           772: #              ifdef PC
        !           773:                    c1 = classify( p1 );
        !           774:                    if ( c1 == TSET || c1 == TSTR || c1 == TREC ) {
        !           775:                        putleaf( PCC_ICON , 0 , 0
        !           776:                                , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
        !           777:                                , c1 == TSET  ? relts[ r->tag - T_EQ ]
        !           778:                                              : relss[ r->tag - T_EQ ] );
        !           779:                            /*
        !           780:                             *  for [] and strings, comparisons are done on
        !           781:                             *  the maximum width of the two sides.
        !           782:                             *  for other sets, we have to ask the left side
        !           783:                             *  what type it is based on the type of the right.
        !           784:                             *  (this matters for intsets).
        !           785:                             */
        !           786:                        if ( c1 == TSTR ) {
        !           787:                            codeoff();
        !           788:                            p = rvalue( r->expr_node.lhs , NLNIL , LREQ );
        !           789:                            codeon();
        !           790:                            if ( p == NLNIL ) {
        !           791:                                return NLNIL;
        !           792:                            }
        !           793:                            if ( lwidth( p ) > lwidth( p1 ) ) {
        !           794:                                contype = p;
        !           795:                            }
        !           796:                        } else if ( c1 == TSET ) {
        !           797:                            codeoff();
        !           798:                            contype = rvalue(r->expr_node.lhs, p1, LREQ);
        !           799:                            codeon();
        !           800:                            if (contype == NLNIL) {
        !           801:                                return NLNIL;
        !           802:                            }
        !           803:                        } 
        !           804:                            /*
        !           805:                             *  put out the width of the comparison.
        !           806:                             */
        !           807:                        putleaf(PCC_ICON, (int) lwidth(contype), 0, PCCT_INT, (char *) 0);
        !           808:                            /*
        !           809:                             *  and the left hand side,
        !           810:                             *  for sets, strings, records
        !           811:                             */
        !           812:                        p = rvalue( r->expr_node.lhs , contype , LREQ );
        !           813:                        if ( p == NLNIL ) {
        !           814:                            return NLNIL;
        !           815:                        }
        !           816:                        putop( PCC_CM , PCCT_INT );
        !           817:                        p1 = rvalue( r->expr_node.rhs , p , LREQ );
        !           818:                        if ( p1 == NLNIL ) {
        !           819:                            return NLNIL;
        !           820:                        }
        !           821:                        putop( PCC_CM , PCCT_INT );
        !           822:                        putop( PCC_CALL , PCCT_INT );
        !           823:                    } else {
        !           824:                            /*
        !           825:                             *  the easy (scalar or error) case
        !           826:                             */
        !           827:                        p = rvalue( r->expr_node.lhs , contype , RREQ );
        !           828:                        if ( p == NLNIL ) {
        !           829:                            return NLNIL;
        !           830:                        }
        !           831:                            /*
        !           832:                             * since the second pass can't do
        !           833:                             *  long op double  or  double op long
        !           834:                             * we may have to do some coercing.
        !           835:                             */
        !           836:                        tuac(p, p1, &rettype, (int *) (&ctype));
        !           837:                        p1 = rvalue( r->expr_node.rhs , p , RREQ );
        !           838:                        if ( p1 == NLNIL ) {
        !           839:                            return NLNIL;
        !           840:                        }
        !           841:                        tuac(p1, p, &rettype, (int *) (&ctype));
        !           842:                        putop((int) relops[ r->tag - T_EQ ] , PCCT_INT );
        !           843:                        sconv(PCCT_INT, PCCT_CHAR);
        !           844:                    }
        !           845: #              endif PC
        !           846:                c = classify(p);
        !           847:                c1 = classify(p1);
        !           848:                if (nocomp(c) || nocomp(c1))
        !           849:                        return (NLNIL);
        !           850: #              ifdef OBJ
        !           851:                    g = NIL;
        !           852: #              endif
        !           853:                switch (c) {
        !           854:                        case TBOOL:
        !           855:                        case TCHAR:
        !           856:                                if (c != c1)
        !           857:                                        goto clash;
        !           858:                                break;
        !           859:                        case TINT:
        !           860:                        case TDOUBLE:
        !           861:                                if (c1 != TINT && c1 != TDOUBLE)
        !           862:                                        goto clash;
        !           863:                                break;
        !           864:                        case TSCAL:
        !           865:                                if (c1 != TSCAL)
        !           866:                                        goto clash;
        !           867:                                if (scalar(p) != scalar(p1))
        !           868:                                        goto nonident;
        !           869:                                break;
        !           870:                        case TSET:
        !           871:                                if (c1 != TSET)
        !           872:                                        goto clash;
        !           873:                                if ( opt( 's' ) &&
        !           874:                                    ( ( r->tag == T_LT) || (r->tag == T_GT) ) &&
        !           875:                                    ( line != nssetline ) ) {
        !           876:                                    nssetline = line;
        !           877:                                    standard();
        !           878:                                    error("%s comparison on sets is non-standard" , opname );
        !           879:                                }
        !           880:                                if (p != p1)
        !           881:                                        goto nonident;
        !           882: #                              ifdef OBJ
        !           883:                                    g = TSET;
        !           884: #                              endif
        !           885:                                break;
        !           886:                        case TREC:
        !           887:                                if ( c1 != TREC ) {
        !           888:                                    goto clash;
        !           889:                                }
        !           890:                                if ( p != p1 ) {
        !           891:                                    goto nonident;
        !           892:                                }
        !           893:                                if (r->tag != T_EQ && r->tag != T_NE) {
        !           894:                                        error("%s not allowed on records - only allow = and <>" , opname );
        !           895:                                        return (NLNIL);
        !           896:                                }
        !           897: #                              ifdef OBJ
        !           898:                                    g = TREC;
        !           899: #                              endif
        !           900:                                break;
        !           901:                        case TPTR:
        !           902:                        case TNIL:
        !           903:                                if (c1 != TPTR && c1 != TNIL)
        !           904:                                        goto clash;
        !           905:                                if (r->tag != T_EQ && r->tag != T_NE) {
        !           906:                                        error("%s not allowed on pointers - only allow = and <>" , opname );
        !           907:                                        return (NLNIL);
        !           908:                                }
        !           909:                                if (p != nl+TNIL && p1 != nl+TNIL && p != p1)
        !           910:                                        goto nonident;
        !           911:                                break;
        !           912:                        case TSTR:
        !           913:                                if (c1 != TSTR)
        !           914:                                        goto clash;
        !           915:                                if (width(p) != width(p1)) {
        !           916:                                        error("Strings not same length in %s comparison", opname);
        !           917:                                        return (NLNIL);
        !           918:                                }
        !           919: #                              ifdef OBJ
        !           920:                                    g = TSTR;
        !           921: #                              endif OBJ
        !           922:                                break;
        !           923:                        default:
        !           924:                                panic("rval2");
        !           925:                }
        !           926: #              ifdef OBJ
        !           927:                    return (gen(g, r->tag, width(p), width(p1)));
        !           928: #              endif OBJ
        !           929: #              ifdef PC
        !           930:                    return nl + TBOOL;
        !           931: #              endif PC
        !           932: clash:
        !           933:                error("%ss and %ss cannot be compared - operator was %s", clnames[c], clnames[c1], opname);
        !           934:                return (NLNIL);
        !           935: nonident:
        !           936:                error("%s types must be identical in comparisons - operator was %s", clnames[c1], opname);
        !           937:                return (NLNIL);
        !           938: 
        !           939:        case T_IN:
        !           940:            rt = r->expr_node.rhs;
        !           941: #          ifdef OBJ
        !           942:                if (rt != TR_NIL && rt->tag == T_CSET) {
        !           943:                        (void) precset( rt , NLNIL , &csetd );
        !           944:                        p1 = csetd.csettype;
        !           945:                        if (p1 == NLNIL)
        !           946:                            return NLNIL;
        !           947:                        postcset( rt, &csetd);
        !           948:                    } else {
        !           949:                        p1 = stkrval(r->expr_node.rhs, NLNIL , (long) RREQ );
        !           950:                        rt = TR_NIL;
        !           951:                    }
        !           952: #              endif OBJ
        !           953: #              ifdef PC
        !           954:                    if (rt != TR_NIL && rt->tag == T_CSET) {
        !           955:                        if ( precset( rt , NLNIL , &csetd ) ) {
        !           956:                            putleaf( PCC_ICON , 0 , 0
        !           957:                                    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
        !           958:                                    , "_IN" );
        !           959:                        } else {
        !           960:                            putleaf( PCC_ICON , 0 , 0
        !           961:                                    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
        !           962:                                    , "_INCT" );
        !           963:                        }
        !           964:                        p1 = csetd.csettype;
        !           965:                        if (p1 == NIL)
        !           966:                            return NLNIL;
        !           967:                    } else {
        !           968:                        putleaf( PCC_ICON , 0 , 0
        !           969:                                , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
        !           970:                                , "_IN" );
        !           971:                        codeoff();
        !           972:                        p1 = rvalue(r->expr_node.rhs, NLNIL , LREQ );
        !           973:                        codeon();
        !           974:                    }
        !           975: #              endif PC
        !           976:                p = stkrval(r->expr_node.lhs, NLNIL , (long) RREQ );
        !           977:                if (p == NIL || p1 == NIL)
        !           978:                        return (NLNIL);
        !           979:                if (p1->class != (char) SET) {
        !           980:                        error("Right operand of 'in' must be a set, not %s", nameof(p1));
        !           981:                        return (NLNIL);
        !           982:                }
        !           983:                if (incompat(p, p1->type, r->expr_node.lhs)) {
        !           984:                        cerror("Index type clashed with set component type for 'in'");
        !           985:                        return (NLNIL);
        !           986:                }
        !           987:                setran(p1->type);
        !           988: #              ifdef OBJ
        !           989:                    if (rt == TR_NIL || csetd.comptime)
        !           990:                            (void) put(4, O_IN, width(p1), set.lwrb, set.uprbp);
        !           991:                    else
        !           992:                            (void) put(2, O_INCT,
        !           993:                                (int)(3 + csetd.singcnt + 2*csetd.paircnt));
        !           994: #              endif OBJ
        !           995: #              ifdef PC
        !           996:                    if ( rt == TR_NIL || rt->tag != T_CSET ) {
        !           997:                        putleaf( PCC_ICON , set.lwrb , 0 , PCCT_INT , (char *) 0 );
        !           998:                        putop( PCC_CM , PCCT_INT );
        !           999:                        putleaf( PCC_ICON , set.uprbp , 0 , PCCT_INT , (char *) 0 );
        !          1000:                        putop( PCC_CM , PCCT_INT );
        !          1001:                        p1 = rvalue( r->expr_node.rhs , NLNIL , LREQ );
        !          1002:                        if ( p1 == NLNIL ) {
        !          1003:                            return NLNIL;
        !          1004:                        }
        !          1005:                        putop( PCC_CM , PCCT_INT );
        !          1006:                    } else if ( csetd.comptime ) {
        !          1007:                        putleaf( PCC_ICON , set.lwrb , 0 , PCCT_INT , (char *) 0 );
        !          1008:                        putop( PCC_CM , PCCT_INT );
        !          1009:                        putleaf( PCC_ICON , set.uprbp , 0 , PCCT_INT , (char *) 0 );
        !          1010:                        putop( PCC_CM , PCCT_INT );
        !          1011:                        postcset( r->expr_node.rhs , &csetd );
        !          1012:                        putop( PCC_CM , PCCT_INT );
        !          1013:                    } else {
        !          1014:                        postcset( r->expr_node.rhs , &csetd );
        !          1015:                    }
        !          1016:                    putop( PCC_CALL , PCCT_INT );
        !          1017:                    sconv(PCCT_INT, PCCT_CHAR);
        !          1018: #              endif PC
        !          1019:                return (nl+T1BOOL);
        !          1020:        default:
        !          1021:                if (r->expr_node.lhs == TR_NIL)
        !          1022:                        return (NLNIL);
        !          1023:                switch (r->tag) {
        !          1024:                default:
        !          1025:                        panic("rval3");
        !          1026: 
        !          1027: 
        !          1028:                /*
        !          1029:                 * An octal number
        !          1030:                 */
        !          1031:                case T_BINT:
        !          1032:                        f.pdouble = a8tol(r->const_node.cptr);
        !          1033:                        goto conint;
        !          1034:        
        !          1035:                /*
        !          1036:                 * A decimal number
        !          1037:                 */
        !          1038:                case T_INT:
        !          1039:                        f.pdouble = atof(r->const_node.cptr);
        !          1040: conint:
        !          1041:                        if (f.pdouble > MAXINT || f.pdouble < MININT) {
        !          1042:                                error("Constant too large for this implementation");
        !          1043:                                return (NLNIL);
        !          1044:                        }
        !          1045:                        l = f.pdouble;
        !          1046: #                      ifdef OBJ
        !          1047:                            if (bytes(l, l) <= 2) {
        !          1048:                                    (void) put(2, O_CON2, ( short ) l);
        !          1049:                                    return (nl+T2INT);
        !          1050:                            }
        !          1051:                            (void) put(2, O_CON4, l); 
        !          1052:                            return (nl+T4INT);
        !          1053: #                      endif OBJ
        !          1054: #                      ifdef PC
        !          1055:                            switch (bytes(l, l)) {
        !          1056:                                case 1:
        !          1057:                                    putleaf(PCC_ICON, (int) l, 0, PCCT_CHAR, 
        !          1058:                                                (char *) 0);
        !          1059:                                    return nl+T1INT;
        !          1060:                                case 2:
        !          1061:                                    putleaf(PCC_ICON, (int) l, 0, PCCT_SHORT, 
        !          1062:                                                (char *) 0);
        !          1063:                                    return nl+T2INT;
        !          1064:                                case 4:
        !          1065:                                    putleaf(PCC_ICON, (int) l, 0, PCCT_INT,
        !          1066:                                                (char *) 0);
        !          1067:                                    return nl+T4INT;
        !          1068:                            }
        !          1069: #                      endif PC
        !          1070:        
        !          1071:                /*
        !          1072:                 * A floating point number
        !          1073:                 */
        !          1074:                case T_FINT:
        !          1075: #                      ifdef OBJ
        !          1076:                            (void) put(2, O_CON8, atof(r->const_node.cptr));
        !          1077: #                      endif OBJ
        !          1078: #                      ifdef PC
        !          1079:                            putCON8( atof( r->const_node.cptr ) );
        !          1080: #                      endif PC
        !          1081:                        return (nl+TDOUBLE);
        !          1082:        
        !          1083:                /*
        !          1084:                 * Constant strings.  Note that constant characters
        !          1085:                 * are constant strings of length one; there is
        !          1086:                 * no constant string of length one.
        !          1087:                 */
        !          1088:                case T_STRNG:
        !          1089:                        cp = r->const_node.cptr;
        !          1090:                        if (cp[1] == 0) {
        !          1091: #                              ifdef OBJ
        !          1092:                                    (void) put(2, O_CONC, cp[0]);
        !          1093: #                              endif OBJ
        !          1094: #                              ifdef PC
        !          1095:                                    putleaf( PCC_ICON , cp[0] , 0 , PCCT_CHAR ,
        !          1096:                                                (char *) 0 );
        !          1097: #                              endif PC
        !          1098:                                return (nl+T1CHAR);
        !          1099:                        }
        !          1100:                        goto cstrng;
        !          1101:                }
        !          1102:        
        !          1103:        }
        !          1104: }
        !          1105: 
        !          1106: /*
        !          1107:  * Can a class appear
        !          1108:  * in a comparison ?
        !          1109:  */
        !          1110: nocomp(c)
        !          1111:        int c;
        !          1112: {
        !          1113: 
        !          1114:        switch (c) {
        !          1115:                case TREC:
        !          1116:                        if ( line != reccompline ) {
        !          1117:                            reccompline = line;
        !          1118:                            warning();
        !          1119:                            if ( opt( 's' ) ) {
        !          1120:                                standard();
        !          1121:                            }
        !          1122:                            error("record comparison is non-standard");
        !          1123:                        }
        !          1124:                        break;
        !          1125:                case TFILE:
        !          1126:                case TARY:
        !          1127:                        error("%ss may not participate in comparisons", clnames[c]);
        !          1128:                        return (1);
        !          1129:        }
        !          1130:        return (NIL);
        !          1131: }
        !          1132: 
        !          1133:     /*
        !          1134:      * this is sort of like gconst, except it works on expression trees
        !          1135:      * rather than declaration trees, and doesn't give error messages for
        !          1136:      * non-constant things.
        !          1137:      * as a side effect this fills in the con structure that gconst uses.
        !          1138:      * this returns TRUE or FALSE.
        !          1139:      */
        !          1140: 
        !          1141: bool 
        !          1142: constval(r)
        !          1143:        register struct tnode *r;
        !          1144: {
        !          1145:        register struct nl *np;
        !          1146:        register struct tnode *cn;
        !          1147:        char *cp;
        !          1148:        int negd, sgnd;
        !          1149:        long ci;
        !          1150: 
        !          1151:        con.ctype = NIL;
        !          1152:        cn = r;
        !          1153:        negd = sgnd = 0;
        !          1154: loop:
        !          1155:            /*
        !          1156:             *  cn[2] is nil if error recovery generated a T_STRNG
        !          1157:             */
        !          1158:        if (cn == TR_NIL || cn->expr_node.lhs == TR_NIL)
        !          1159:                return FALSE;
        !          1160:        switch (cn->tag) {
        !          1161:                default:
        !          1162:                        return FALSE;
        !          1163:                case T_MINUS:
        !          1164:                        negd = 1 - negd;
        !          1165:                        /* and fall through */
        !          1166:                case T_PLUS:
        !          1167:                        sgnd++;
        !          1168:                        cn = cn->un_expr.expr;
        !          1169:                        goto loop;
        !          1170:                case T_NIL:
        !          1171:                        con.cpval = NIL;
        !          1172:                        con.cival = 0;
        !          1173:                        con.crval = con.cival;
        !          1174:                        con.ctype = nl + TNIL;
        !          1175:                        break;
        !          1176:                case T_VAR:
        !          1177:                        np = lookup(cn->var_node.cptr);
        !          1178:                        if (np == NLNIL || np->class != CONST) {
        !          1179:                                return FALSE;
        !          1180:                        }
        !          1181:                        if ( cn->var_node.qual != TR_NIL ) {
        !          1182:                                return FALSE;
        !          1183:                        }
        !          1184:                        con.ctype = np->type;
        !          1185:                        switch (classify(np->type)) {
        !          1186:                                case TINT:
        !          1187:                                        con.crval = np->range[0];
        !          1188:                                        break;
        !          1189:                                case TDOUBLE:
        !          1190:                                        con.crval = np->real;
        !          1191:                                        break;
        !          1192:                                case TBOOL:
        !          1193:                                case TCHAR:
        !          1194:                                case TSCAL:
        !          1195:                                        con.cival = np->value[0];
        !          1196:                                        con.crval = con.cival;
        !          1197:                                        break;
        !          1198:                                case TSTR:
        !          1199:                                        con.cpval = (char *) np->ptr[0];
        !          1200:                                        break;
        !          1201:                                default:
        !          1202:                                        con.ctype = NIL;
        !          1203:                                        return FALSE;
        !          1204:                        }
        !          1205:                        break;
        !          1206:                case T_BINT:
        !          1207:                        con.crval = a8tol(cn->const_node.cptr);
        !          1208:                        goto restcon;
        !          1209:                case T_INT:
        !          1210:                        con.crval = atof(cn->const_node.cptr);
        !          1211:                        if (con.crval > MAXINT || con.crval < MININT) {
        !          1212:                                derror("Constant too large for this implementation");
        !          1213:                                con.crval = 0;
        !          1214:                        }
        !          1215: restcon:
        !          1216:                        ci = con.crval;
        !          1217: #ifndef PI0
        !          1218:                        if (bytes(ci, ci) <= 2)
        !          1219:                                con.ctype = nl+T2INT;
        !          1220:                        else    
        !          1221: #endif
        !          1222:                                con.ctype = nl+T4INT;
        !          1223:                        break;
        !          1224:                case T_FINT:
        !          1225:                        con.ctype = nl+TDOUBLE;
        !          1226:                        con.crval = atof(cn->const_node.cptr);
        !          1227:                        break;
        !          1228:                case T_STRNG:
        !          1229:                        cp = cn->const_node.cptr;
        !          1230:                        if (cp[1] == 0) {
        !          1231:                                con.ctype = nl+T1CHAR;
        !          1232:                                con.cival = cp[0];
        !          1233:                                con.crval = con.cival;
        !          1234:                                break;
        !          1235:                        }
        !          1236:                        con.ctype = nl+TSTR;
        !          1237:                        con.cpval = cp;
        !          1238:                        break;
        !          1239:        }
        !          1240:        if (sgnd) {
        !          1241:                if (isnta(con.ctype, "id")) {
        !          1242:                        derror("%s constants cannot be signed", nameof(con.ctype));
        !          1243:                        return FALSE;
        !          1244:                } else if (negd)
        !          1245:                        con.crval = -con.crval;
        !          1246:        }
        !          1247:        return TRUE;
        !          1248: }

unix.superglobalmegacorp.com

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