Annotation of 43BSD/ucb/pascal/src/lval.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[] = "@(#)lval.c     5.2 (Berkeley) 7/26/85";
        !             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: #include "tree_ty.h"
        !            17: #ifdef PC
        !            18: #   include    "pc.h"
        !            19: #   include    <pcc.h>
        !            20: #endif PC
        !            21: 
        !            22: extern int flagwas;
        !            23: /*
        !            24:  * Lvalue computes the address
        !            25:  * of a qualified name and
        !            26:  * leaves it on the stack.
        !            27:  * for pc, it can be asked for either an lvalue or an rvalue.
        !            28:  * the semantics are the same, only the code is different.
        !            29:  */
        !            30: /*ARGSUSED*/
        !            31: struct nl *
        !            32: lvalue(var, modflag , required )
        !            33:        struct tnode *var; 
        !            34:        int     modflag;
        !            35:        int     required;
        !            36: {
        !            37: #ifdef OBJ
        !            38:        register struct nl *p;
        !            39:        struct nl *firstp, *lastp;
        !            40:        register struct tnode *c, *co;
        !            41:        int f, o, s;
        !            42:        /*
        !            43:         * Note that the local optimizations
        !            44:         * done here for offsets would more
        !            45:         * appropriately be done in put.
        !            46:         */
        !            47:        struct tnode    tr;     /* T_FIELD */ 
        !            48:        struct tnode    *tr_ptr;
        !            49:        struct tnode    l_node;
        !            50: #endif
        !            51: 
        !            52:        if (var == TR_NIL) {
        !            53:                return (NLNIL);
        !            54:        }
        !            55:        if (nowexp(var)) {
        !            56:                return (NLNIL);
        !            57:        }
        !            58:        if (var->tag != T_VAR) {
        !            59:                error("Variable required");     /* Pass mesgs down from pt of call ? */
        !            60:                return (NLNIL);
        !            61:        }
        !            62: #      ifdef PC
        !            63:                /*
        !            64:                 *      pc requires a whole different control flow
        !            65:                 */
        !            66:            return pclvalue( var , modflag , required );
        !            67: #      endif PC
        !            68: #      ifdef OBJ
        !            69:                /*
        !            70:                 *      pi uses the rest of the function
        !            71:                 */
        !            72:        firstp = p = lookup(var->var_node.cptr);
        !            73:        if (p == NLNIL) {
        !            74:                return (NLNIL);
        !            75:        }
        !            76:        c = var->var_node.qual;
        !            77:        if ((modflag & NOUSE) && !lptr(c)) {
        !            78:                p->nl_flags = flagwas;
        !            79:        }
        !            80:        if (modflag & MOD) {
        !            81:                p->nl_flags |= NMOD;
        !            82:        }
        !            83:        /*
        !            84:         * Only possibilities for p->class here
        !            85:         * are the named classes, i.e. CONST, TYPE
        !            86:         * VAR, PROC, FUNC, REF, or a WITHPTR.
        !            87:         */
        !            88:        tr_ptr = &l_node;
        !            89:        switch (p->class) {
        !            90:                case WITHPTR:
        !            91:                        /*
        !            92:                         * Construct the tree implied by
        !            93:                         * the with statement
        !            94:                         */
        !            95:                        l_node.tag = T_LISTPP;
        !            96: 
        !            97:                        /* the cast has got to go but until the node is figured
        !            98:                           out it stays */
        !            99: 
        !           100:                        tr_ptr->list_node.list = (&tr);
        !           101:                        tr_ptr->list_node.next = var->var_node.qual;
        !           102:                        tr.tag = T_FIELD;
        !           103:                        tr.field_node.id_ptr = var->var_node.cptr;
        !           104:                        c = tr_ptr; /* c is a ptr to a tnode */
        !           105: #                      ifdef PTREE
        !           106:                            /*
        !           107:                             * mung var->fields to say which field this T_VAR is
        !           108:                             * for VarCopy
        !           109:                             */
        !           110: 
        !           111:                            /* problem! reclook returns struct nl* */
        !           112: 
        !           113:                            var->var_node.fields = reclook( p -> type , 
        !           114:                                            var->var_node.line_no );
        !           115: #                      endif
        !           116:                        /* and fall through */
        !           117:                case REF:
        !           118:                        /*
        !           119:                         * Obtain the indirect word
        !           120:                         * of the WITHPTR or REF
        !           121:                         * as the base of our lvalue
        !           122:                         */
        !           123:                        (void) put(2, PTR_RV | bn << 8+INDX , (int)p->value[0] );
        !           124:                        f = 0;          /* have an lv on stack */
        !           125:                        o = 0;
        !           126:                        break;
        !           127:                case VAR:
        !           128:                        if (p->type->class != CRANGE) {
        !           129:                            f = 1;              /* no lv on stack yet */
        !           130:                            o = p->value[0];
        !           131:                        } else {
        !           132:                            error("Conformant array bound %s found where variable required", p->symbol);
        !           133:                            return(NLNIL);
        !           134:                        }
        !           135:                        break;
        !           136:                default:
        !           137:                        error("%s %s found where variable required", classes[p->class], p->symbol);
        !           138:                        return (NLNIL);
        !           139:        }
        !           140:        /*
        !           141:         * Loop and handle each
        !           142:         * qualification on the name
        !           143:         */
        !           144:        if (c == TR_NIL && (modflag&ASGN) && ( p->value[NL_FORV] & FORVAR ) ) {
        !           145:                error("Can't modify the for variable %s in the range of the loop", p->symbol);
        !           146:                return (NLNIL);
        !           147:        }
        !           148:        s = 0;          /* subscripts seen */
        !           149:        for (; c != TR_NIL; c = c->list_node.next) {
        !           150:                co = c->list_node.list; /* co is a ptr to a tnode */
        !           151:                if (co == TR_NIL) {
        !           152:                        return (NLNIL);
        !           153:                }
        !           154:                lastp = p;
        !           155:                p = p->type;
        !           156:                if (p == NLNIL) {
        !           157:                        return (NLNIL);
        !           158:                }
        !           159:                /*
        !           160:                 * If we haven't seen enough subscripts, and the next
        !           161:                 * qualification isn't array reference, then it's an error.
        !           162:                 */
        !           163:                if (s && co->tag != T_ARY) {
        !           164:                        error("Too few subscripts (%d given, %d required)",
        !           165:                                s, p->value[0]);
        !           166:                }
        !           167:                switch (co->tag) {
        !           168:                        case T_PTR:
        !           169:                                /*
        !           170:                                 * Pointer qualification.
        !           171:                                 */
        !           172:                                lastp->nl_flags |= NUSED;
        !           173:                                if (p->class != PTR && p->class != FILET) {
        !           174:                                        error("^ allowed only on files and pointers, not on %ss", nameof(p));
        !           175:                                        goto bad;
        !           176:                                }
        !           177:                                if (f) {
        !           178:                                    if (p->class == FILET && bn != 0)
        !           179:                                        (void) put(2, O_LV | bn <<8+INDX , o );
        !           180:                                    else
        !           181:                                        /*
        !           182:                                         * this is the indirection from
        !           183:                                         * the address of the pointer 
        !           184:                                         * to the pointer itself.
        !           185:                                         * kirk sez:
        !           186:                                         * fnil doesn't want this.
        !           187:                                         * and does it itself for files
        !           188:                                         * since only it knows where the
        !           189:                                         * actual window is.
        !           190:                                         * but i have to do this for
        !           191:                                         * regular pointers.
        !           192:                                         * This is further complicated by
        !           193:                                         * the fact that global variables
        !           194:                                         * are referenced through pointers
        !           195:                                         * on the stack. Thus an RV on a
        !           196:                                         * global variable is the same as
        !           197:                                         * an LV of a non-global one ?!?
        !           198:                                         */
        !           199:                                        (void) put(2, PTR_RV | bn <<8+INDX , o );
        !           200:                                } else {
        !           201:                                        if (o) {
        !           202:                                            (void) put(2, O_OFF, o);
        !           203:                                        }
        !           204:                                        if (p->class != FILET || bn == 0)
        !           205:                                            (void) put(1, PTR_IND);
        !           206:                                }
        !           207:                                /*
        !           208:                                 * Pointer cannot be
        !           209:                                 * nil and file cannot
        !           210:                                 * be at end-of-file.
        !           211:                                 */
        !           212:                                (void) put(1, p->class == FILET ? O_FNIL : O_NIL);
        !           213:                                f = o = 0;
        !           214:                                continue;
        !           215:                        case T_ARGL:
        !           216:                                if (p->class != ARRAY) {
        !           217:                                        if (lastp == firstp) {
        !           218:                                                error("%s is a %s, not a function", var->var_node.cptr, classes[firstp->class]);
        !           219:                                        } else {
        !           220:                                                error("Illegal function qualificiation");
        !           221:                                        }
        !           222:                                        return (NLNIL);
        !           223:                                }
        !           224:                                recovered();
        !           225:                                error("Pascal uses [] for subscripting, not ()");
        !           226:                        case T_ARY:
        !           227:                                if (p->class != ARRAY) {
        !           228:                                        error("Subscripting allowed only on arrays, not on %ss", nameof(p));
        !           229:                                        goto bad;
        !           230:                                }
        !           231:                                if (f) {
        !           232:                                        if (bn == 0)
        !           233:                                                /*
        !           234:                                                 * global variables are
        !           235:                                                 * referenced through pointers
        !           236:                                                 * on the stack
        !           237:                                                 */
        !           238:                                                (void) put(2, PTR_RV | bn<<8+INDX, o);
        !           239:                                        else
        !           240:                                                (void) put(2, O_LV | bn<<8+INDX, o);
        !           241:                                } else {
        !           242:                                        if (o) {
        !           243:                                            (void) put(2, O_OFF, o);
        !           244:                                        }
        !           245:                                }
        !           246:                                switch(s = arycod(p,co->ary_node.expr_list,s)) {
        !           247:                                        /*
        !           248:                                         * This is the number of subscripts seen
        !           249:                                         */
        !           250:                                        case 0:
        !           251:                                                return (NLNIL);
        !           252:                                        case -1:
        !           253:                                                goto bad;
        !           254:                                }
        !           255:                                if (s == p->value[0]) {
        !           256:                                        s = 0;
        !           257:                                } else {
        !           258:                                        p = lastp;
        !           259:                                }
        !           260:                                f = o = 0;
        !           261:                                continue;
        !           262:                        case T_FIELD:
        !           263:                                /*
        !           264:                                 * Field names are just
        !           265:                                 * an offset with some 
        !           266:                                 * semantic checking.
        !           267:                                 */
        !           268:                                if (p->class != RECORD) {
        !           269:                                        error(". allowed only on records, not on %ss", nameof(p));
        !           270:                                        goto bad;
        !           271:                                }
        !           272:                                /* must define the field node!! */
        !           273:                                if (co->field_node.id_ptr == NIL) {
        !           274:                                        return (NLNIL);
        !           275:                                }
        !           276:                                p = reclook(p, co->field_node.id_ptr);
        !           277:                                if (p == NLNIL) {
        !           278:                                        error("%s is not a field in this record", co->field_node.id_ptr);
        !           279:                                        goto bad;
        !           280:                                }
        !           281: #                              ifdef PTREE
        !           282:                                    /*
        !           283:                                     * mung co[3] to indicate which field
        !           284:                                     * this is for SelCopy
        !           285:                                     */
        !           286:                                    co->field_node.nl_entry = p;
        !           287: #                              endif
        !           288:                                if (modflag & MOD) {
        !           289:                                        p->nl_flags |= NMOD;
        !           290:                                }
        !           291:                                if ((modflag & NOUSE) == 0 ||
        !           292:                                    lptr(c->list_node.next)) {
        !           293:                                /* figure out what kind of node c is !! */
        !           294:                                        p->nl_flags |= NUSED;
        !           295:                                }
        !           296:                                o += p->value[0];
        !           297:                                continue;
        !           298:                        default:
        !           299:                                panic("lval2");
        !           300:                }
        !           301:        }
        !           302:        if (s) {
        !           303:                error("Too few subscripts (%d given, %d required)",
        !           304:                        s, p->type->value[0]);
        !           305:                return NLNIL;
        !           306:        }
        !           307:        if (f) {
        !           308:                if (bn == 0)
        !           309:                        /*
        !           310:                         * global variables are referenced through
        !           311:                         * pointers on the stack
        !           312:                         */
        !           313:                        (void) put(2, PTR_RV | bn<<8+INDX, o);
        !           314:                else
        !           315:                        (void) put(2, O_LV | bn<<8+INDX, o);
        !           316:        } else {
        !           317:                if (o) {
        !           318:                    (void) put(2, O_OFF, o);
        !           319:                }
        !           320:        }
        !           321:        return (p->type);
        !           322: bad:
        !           323:        cerror("Error occurred on qualification of %s", var->var_node.cptr);
        !           324:        return (NLNIL);
        !           325: #      endif OBJ
        !           326: }
        !           327: 
        !           328: int lptr(c)
        !           329:        register struct tnode *c;
        !           330: {
        !           331:        register struct tnode *co;
        !           332: 
        !           333:        for (; c != TR_NIL; c = c->list_node.next) {
        !           334:                co = c->list_node.list;
        !           335:                if (co == TR_NIL) {
        !           336:                        return (NIL);
        !           337:                }
        !           338:                switch (co->tag) {
        !           339: 
        !           340:                case T_PTR:
        !           341:                        return (1);
        !           342:                case T_ARGL:
        !           343:                        return (0);
        !           344:                case T_ARY:
        !           345:                case T_FIELD:
        !           346:                        continue;
        !           347:                default:
        !           348:                        panic("lptr");
        !           349:                }
        !           350:        }
        !           351:        return (0);
        !           352: }
        !           353: 
        !           354: /*
        !           355:  * Arycod does the
        !           356:  * code generation
        !           357:  * for subscripting.
        !           358:  * n is the number of
        !           359:  * subscripts already seen
        !           360:  * (CLN 09/13/83)
        !           361:  */
        !           362: int arycod(np, el, n)
        !           363:        struct nl *np;
        !           364:        struct tnode *el;
        !           365:        int n;
        !           366: {
        !           367:        register struct nl *p, *ap;
        !           368:        long sub;
        !           369:        bool constsub;
        !           370:        extern bool constval();
        !           371:        int i, d;  /* v, v1;  these aren't used */
        !           372:        int w;
        !           373: 
        !           374:        p = np;
        !           375:        if (el == TR_NIL) {
        !           376:                return (0);
        !           377:        }
        !           378:        d = p->value[0];
        !           379:        for (i = 1; i <= n; i++) {
        !           380:                p = p->chain;
        !           381:        }
        !           382:        /*
        !           383:         * Check each subscript
        !           384:         */
        !           385:        for (i = n+1; i <= d; i++) {
        !           386:                if (el == TR_NIL) {
        !           387:                        return (i-1);
        !           388:                }
        !           389:                p = p->chain;
        !           390:                if (p == NLNIL)
        !           391:                        return (0);
        !           392:                if ((p->class != CRANGE) &&
        !           393:                        (constsub = constval(el->list_node.list))) {
        !           394:                    ap = con.ctype;
        !           395:                    sub = con.crval;
        !           396:                    if (sub < p->range[0] || sub > p->range[1]) {
        !           397:                        error("Subscript value of %D is out of range", (char *) sub);
        !           398:                        return (0);
        !           399:                    }
        !           400:                    sub -= p->range[0];
        !           401:                } else {
        !           402: #                  ifdef PC
        !           403:                        precheck( p , "_SUBSC" , "_SUBSCZ" );
        !           404: #                  endif PC
        !           405:                    ap = rvalue(el->list_node.list, NLNIL , RREQ );
        !           406:                    if (ap == NIL) {
        !           407:                            return (0);
        !           408:                    }
        !           409: #                  ifdef PC
        !           410:                        postcheck(p, ap);
        !           411:                        sconv(p2type(ap),PCCT_INT);
        !           412: #                  endif PC
        !           413:                }
        !           414:                if (incompat(ap, p->type, el->list_node.list)) {
        !           415:                        cerror("Array index type incompatible with declared index type");
        !           416:                        if (d != 1) {
        !           417:                                cerror("Error occurred on index number %d", (char *) i);
        !           418:                        }
        !           419:                        return (-1);
        !           420:                }
        !           421:                if (p->class == CRANGE) {
        !           422:                        constsub = FALSE;
        !           423:                } else {
        !           424:                        w = aryconst(np, i);
        !           425:                }
        !           426: #              ifdef OBJ
        !           427:                    if (constsub) {
        !           428:                        sub *= w;
        !           429:                        if (sub != 0) {
        !           430:                            w = bytes(sub, sub);
        !           431:                            (void) put(2, w <= 2 ? O_CON2 : O_CON4, sub);
        !           432:                            (void) gen(NIL, T_ADD, sizeof(char *), w);
        !           433:                        }
        !           434:                        el = el->list_node.next;
        !           435:                        continue;
        !           436:                    }
        !           437:                    if (p->class == CRANGE) {
        !           438:                        putcbnds(p, 0);
        !           439:                        putcbnds(p, 1);
        !           440:                        putcbnds(p, 2);
        !           441:                    } else if (opt('t') == 0) {
        !           442:                            switch (w) {
        !           443:                            case 8:
        !           444:                                    w = 6;
        !           445:                            case 4:
        !           446:                            case 2:
        !           447:                            case 1:
        !           448:                                    (void) put(2, (width(ap) != 4 ? O_INX2P2 : O_INX4P2) | (w & ~1) << 7, ( short ) p->range[0]);
        !           449:                                    el = el->list_node.next;
        !           450:                                    continue;
        !           451:                            }
        !           452:                    }
        !           453:                    if (p->class == CRANGE) {
        !           454:                        if (width(p) == 4) {
        !           455:                            put(1, width(ap) != 4 ? O_VINX42 : O_VINX4);
        !           456:                        } else {
        !           457:                            put(1, width(ap) != 4 ? O_VINX2 : O_VINX24);
        !           458:                        }
        !           459:                    } else {
        !           460:                        put(4, width(ap) != 4 ? O_INX2 : O_INX4, w,
        !           461:                            (short)p->range[0], (short)(p->range[1]));
        !           462:                    }
        !           463:                    el = el->list_node.next;
        !           464:                    continue;
        !           465: #              endif OBJ
        !           466: #              ifdef PC
        !           467:                        /*
        !           468:                         *      subtract off the lower bound
        !           469:                         */
        !           470:                    if (constsub) {
        !           471:                        sub *= w;
        !           472:                        if (sub != 0) {
        !           473:                            putleaf( PCC_ICON , (int) sub , 0 , PCCT_INT , (char *) 0 );
        !           474:                            putop(PCC_PLUS, PCCM_ADDTYPE(p2type(np->type), PCCTM_PTR));
        !           475:                        }
        !           476:                        el = el->list_node.next;
        !           477:                        continue;
        !           478:                    }
        !           479:                    if (p->class == CRANGE) {
        !           480:                        /*
        !           481:                         *      if conformant array, subtract off lower bound
        !           482:                         */
        !           483:                        ap = p->nptr[0];
        !           484:                        putRV(ap->symbol, (ap->nl_block & 037), ap->value[0], 
        !           485:                                ap->extra_flags, p2type( ap ) );
        !           486:                        putop( PCC_MINUS, PCCT_INT );
        !           487:                        /*
        !           488:                         *      and multiply by the width of the elements
        !           489:                         */
        !           490:                        ap = p->nptr[2];
        !           491:                        putRV( 0 , (ap->nl_block & 037), ap->value[0], 
        !           492:                                ap->extra_flags, p2type( ap ) );
        !           493:                        putop( PCC_MUL , PCCT_INT );
        !           494:                    } else {
        !           495:                        if ( p -> range[ 0 ] != 0 ) {
        !           496:                            putleaf( PCC_ICON , (int) p -> range[0] , 0 , PCCT_INT , (char *) 0 );
        !           497:                            putop( PCC_MINUS , PCCT_INT );
        !           498:                        }
        !           499:                            /*
        !           500:                             *  multiply by the width of the elements
        !           501:                             */
        !           502:                        if ( w != 1 ) {
        !           503:                            putleaf( PCC_ICON , w , 0 , PCCT_INT , (char *) 0 );
        !           504:                            putop( PCC_MUL , PCCT_INT );
        !           505:                        }
        !           506:                    }
        !           507:                        /*
        !           508:                         *      and add it to the base address
        !           509:                         */
        !           510:                    putop( PCC_PLUS , PCCM_ADDTYPE( p2type( np -> type ) , PCCTM_PTR ) );
        !           511:                el = el->list_node.next;
        !           512: #              endif PC
        !           513:        }
        !           514:        if (el != TR_NIL) {
        !           515:            if (np->type->class != ARRAY) {
        !           516:                do {
        !           517:                        el = el->list_node.next;
        !           518:                        i++;
        !           519:                } while (el != TR_NIL);
        !           520:                error("Too many subscripts (%d given, %d required)", (char *) (i-1), (char *) d);
        !           521:                return (-1);
        !           522:            } else {
        !           523:                return(arycod(np->type, el, d));
        !           524:            }
        !           525:        }
        !           526:        return (d);
        !           527: }
        !           528: 
        !           529: #ifdef OBJ
        !           530: /*
        !           531:  * Put out the conformant array bounds (lower bound, upper bound or width)
        !           532:  * for conformant array type ctype.
        !           533:  * The value of i determines which is being put
        !           534:  * i = 0: lower bound, i=1: upper bound, i=2: width
        !           535:  */
        !           536: putcbnds(ctype, i)
        !           537: struct nl *ctype;
        !           538: int i;
        !           539: {
        !           540:        switch(width(ctype->type)) {
        !           541:            case 1:
        !           542:                put(2, O_RV1 | (ctype->nl_block & 037) << 8+INDX,
        !           543:                        (int)ctype->nptr[i]->value[0]);
        !           544:                break;
        !           545:            case 2:
        !           546:                put(2, O_RV2 | (ctype->nl_block & 037) << 8+INDX,
        !           547:                        (int)ctype->nptr[i]->value[0]);
        !           548:                break;
        !           549:            case 4:
        !           550:            default:
        !           551:                put(2, O_RV4 | (ctype->nl_block & 037) << 8+INDX,
        !           552:                        (int)ctype->nptr[i]->value[0]);
        !           553:        }
        !           554: }
        !           555: #endif OBJ

unix.superglobalmegacorp.com

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