Annotation of 43BSD/ucb/pascal/src/forop.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[] = "@(#)forop.c    5.1 (Berkeley) 6/5/85";
        !             9: #endif not lint
        !            10: 
        !            11: 
        !            12: #include       "whoami.h"
        !            13: #include       "0.h"
        !            14: #include       "opcode.h"
        !            15: #include       "tree.h"
        !            16: #include       "objfmt.h"
        !            17: #ifdef PC
        !            18: #    include   "pc.h"
        !            19: #    include   <pcc.h>
        !            20: #endif PC
        !            21: #include       "tmps.h"
        !            22: #include       "tree_ty.h"
        !            23: 
        !            24:     /*
        !            25:      * for-statements.
        !            26:      *
        !            27:      * the relevant quote from the standard:  6.8.3.9:
        !            28:      * ``The control-variable shall be an entire-variable whose identifier
        !            29:      * is declared in the variable-declaration-part of the block closest-
        !            30:      * containing the for-statement.  The control-variable shall possess
        !            31:      * an ordinal-type, and the initial-value and the final-value shall be
        !            32:      * of a type compatible with this type.  The statement of a for-statement
        !            33:      * shall not contain an assigning-reference to the control-variable
        !            34:      * of the for-statement.  The value of the final-value shall be 
        !            35:      * assignment-compatible with the control-variable when the initial-value
        !            36:      * is assigned to the control-variable.  After a for-statement is
        !            37:      * executed (other than being left by a goto-statement leading out of it)
        !            38:      * the control-variable shall be undefined.  Apart from the restrictions
        !            39:      * imposed by these requirements, the for-statement
        !            40:      *         for v := e1 to e2 do body
        !            41:      * shall be equivalent to
        !            42:      *         begin
        !            43:      *             temp1 := e1;
        !            44:      *             temp2 := e2;
        !            45:      *             if temp1 <= temp2 then begin
        !            46:      *                 v := temp1;
        !            47:      *                 body;
        !            48:      *                 while v <> temp2 do begin
        !            49:      *                     v := succ(v);
        !            50:      *                     body;
        !            51:      *                 end
        !            52:      *             end
        !            53:      *         end
        !            54:      * where temp1 and temp2 denote auxiliary variables that the program
        !            55:      * does not otherwise contain, and that possess the type possessed by
        !            56:      * the variable v if that type is not a subrange-type;  otherwise the
        !            57:      * host type possessed by the variable v.''
        !            58:      *
        !            59:      * The Berkeley Pascal systems try to do all that without duplicating
        !            60:      * the body, and shadowing the control-variable in (possibly) a
        !            61:      * register variable.
        !            62:      *
        !            63:      * arg here looks like:
        !            64:      * arg[0]  T_FORU or T_FORD
        !            65:      *    [1]  lineof "for"
        !            66:      *    [2]  [0]     T_ASGN
        !            67:      *         [1]     lineof ":="
        !            68:      *         [2]     [0]     T_VAR
        !            69:      *                 [1]     lineof id
        !            70:      *                 [2]     char * to id
        !            71:      *                 [3]     qualifications
        !            72:      *         [3]     initial expression
        !            73:      *   [3]   termination expression
        !            74:      *   [4]   statement
        !            75:      */
        !            76: forop( tree_node)
        !            77:     struct tnode       *tree_node;
        !            78:     {
        !            79:        struct tnode    *lhs;
        !            80:        VAR_NODE        *lhs_node;
        !            81:        FOR_NODE        *f_node;
        !            82:        struct nl       *forvar;
        !            83:        struct nl       *fortype;
        !            84: #ifdef PC
        !            85:        int             forp2type;
        !            86: #endif PC
        !            87:        int             forwidth;
        !            88:        struct tnode    *init_node;
        !            89:        struct nl       *inittype;
        !            90:        struct nl       *initnlp;       /* initial value namelist entry */
        !            91:        struct tnode    *term_node;
        !            92:        struct nl       *termtype;
        !            93:        struct nl       *termnlp;       /* termination value namelist entry */
        !            94:        struct nl       *shadownlp;     /* namelist entry for the shadow */
        !            95:        struct tnode    *stat_node;
        !            96:        int             goc;            /* saved gocnt */
        !            97:        int             again;          /* label at the top of the loop */
        !            98:        int             after;          /* label after the end of the loop */
        !            99:        struct nl       saved_nl;       /* saved namelist entry for loop var */
        !           100: 
        !           101:        goc = gocnt;
        !           102:        forvar = NLNIL;
        !           103:        if ( tree_node == TR_NIL ) { 
        !           104:            goto byebye;
        !           105:        }
        !           106:        f_node = &(tree_node->for_node);
        !           107:        if ( f_node->init_asg == TR_NIL ) {
        !           108:            goto byebye;
        !           109:        }
        !           110:        line = f_node->line_no;
        !           111:        putline();
        !           112:        lhs = f_node->init_asg->asg_node.lhs_var;
        !           113:        init_node = f_node->init_asg->asg_node.rhs_expr;
        !           114:        term_node = f_node->term_expr;
        !           115:        stat_node = f_node->for_stmnt;
        !           116:        if (lhs == TR_NIL) {
        !           117: nogood:
        !           118:            if (forvar != NIL) {
        !           119:                forvar->value[ NL_FORV ] = FORVAR;
        !           120:            }
        !           121:            (void) rvalue( init_node , NLNIL , RREQ ); 
        !           122:            (void) rvalue( term_node , NLNIL , RREQ );
        !           123:            statement( stat_node );
        !           124:            goto byebye;
        !           125:        }
        !           126:        else lhs_node = &(lhs->var_node);
        !           127:            /*
        !           128:             * and this marks the variable as used!!!
        !           129:             */
        !           130:        forvar = lookup( lhs_node->cptr );
        !           131:        if ( forvar == NIL ) {
        !           132:            goto nogood;
        !           133:        }
        !           134:        saved_nl = *forvar;
        !           135:        if ( lhs_node->qual != TR_NIL ) {
        !           136:            error("For variable %s must be unqualified", forvar->symbol);
        !           137:            goto nogood;
        !           138:        }
        !           139:        if (forvar->class == WITHPTR) {
        !           140:            error("For variable %s cannot be an element of a record", 
        !           141:                        lhs_node->cptr);
        !           142:            goto nogood;
        !           143:        }
        !           144:        if ( opt('s') &&
        !           145:            ( ( bn != cbn ) ||
        !           146: #ifdef OBJ
        !           147:                (whereis(forvar->value[NL_OFFS], 0) == PARAMVAR)
        !           148: #endif OBJ
        !           149: #ifdef PC
        !           150:                (whereis(forvar->value[NL_OFFS], forvar->extra_flags)
        !           151:                    == PARAMVAR )
        !           152: #endif PC
        !           153:            ) ) {
        !           154:            standard();
        !           155:            error("For variable %s must be declared in the block in which it is used", forvar->symbol);
        !           156:        }
        !           157:            /*
        !           158:             * find out the type of the loop variable
        !           159:             */
        !           160:        codeoff();
        !           161:        fortype = lvalue( lhs , MOD , RREQ );
        !           162:        codeon();
        !           163:        if ( fortype == NLNIL ) {
        !           164:            goto nogood;
        !           165:        }
        !           166:        if ( isnta( fortype , "bcis" ) ) {
        !           167:            error("For variable %s cannot be %ss", forvar->symbol, nameof( fortype ) );
        !           168:            goto nogood;
        !           169:        }
        !           170:        if ( forvar->value[ NL_FORV ] & FORVAR ) {
        !           171:            error("Can't modify the for variable %s in the range of the loop", forvar->symbol);
        !           172:            forvar = NLNIL;
        !           173:            goto nogood;
        !           174:        }
        !           175:        forwidth = lwidth(fortype);
        !           176: #      ifdef PC
        !           177:            forp2type = p2type(fortype);
        !           178: #      endif PC
        !           179:            /*
        !           180:             *  allocate temporaries for the initial and final expressions
        !           181:             *  and maybe a register to shadow the for variable.
        !           182:             */
        !           183:        initnlp = tmpalloc((long) sizeof(long), nl+T4INT, NOREG);
        !           184:        termnlp = tmpalloc((long) sizeof(long), nl+T4INT, NOREG);
        !           185:        shadownlp = tmpalloc((long) forwidth, fortype, REGOK);
        !           186: #      ifdef PC
        !           187:                /*
        !           188:                 * compute and save the initial expression
        !           189:                 */
        !           190:            putRV((char *) 0 , cbn , initnlp -> value[ NL_OFFS ] ,
        !           191:                    initnlp -> extra_flags , PCCT_INT );
        !           192: #      endif PC
        !           193: #      ifdef OBJ
        !           194:            (void) put(2, O_LV | cbn<<8+INDX, initnlp -> value[ NL_OFFS ] );
        !           195: #      endif OBJ
        !           196:        inittype = rvalue( init_node , fortype , RREQ );
        !           197:        if ( incompat( inittype , fortype , init_node ) ) {
        !           198:            cerror("Type of initial expression clashed with index type in 'for' statement");
        !           199:            if (forvar != NLNIL) {
        !           200:                forvar->value[ NL_FORV ] = FORVAR;
        !           201:            }
        !           202:            (void) rvalue( term_node , NLNIL , RREQ );
        !           203:            statement( stat_node );
        !           204:            goto byebye;
        !           205:        }
        !           206: #      ifdef PC
        !           207:            sconv(p2type(inittype), PCCT_INT);
        !           208:            putop( PCC_ASSIGN , PCCT_INT );
        !           209:            putdot( filename , line );
        !           210:                /*
        !           211:                 * compute and save the termination expression
        !           212:                 */
        !           213:            putRV((char *) 0 , cbn , termnlp -> value[ NL_OFFS ] ,
        !           214:                    termnlp -> extra_flags , PCCT_INT );
        !           215: #      endif PC
        !           216: #      ifdef OBJ
        !           217:            (void) gen(O_AS2, O_AS2, sizeof(long), width(inittype));
        !           218:                /*
        !           219:                 * compute and save the termination expression
        !           220:                 */
        !           221:            (void) put(2, O_LV | cbn<<8+INDX, termnlp -> value[ NL_OFFS ] );
        !           222: #      endif OBJ
        !           223:        termtype = rvalue( term_node , fortype , RREQ );
        !           224:        if ( incompat( termtype , fortype , term_node ) ) {
        !           225:            cerror("Type of limit expression clashed with index type in 'for' statement");
        !           226:            if (forvar != NLNIL) {
        !           227:                forvar->value[ NL_FORV ] = FORVAR;
        !           228:            }
        !           229:            statement( stat_node );
        !           230:            goto byebye;
        !           231:        }
        !           232: #      ifdef PC
        !           233:            sconv(p2type(termtype), PCCT_INT);
        !           234:            putop( PCC_ASSIGN , PCCT_INT );
        !           235:            putdot( filename , line );
        !           236:                /*
        !           237:                 * we can skip the loop altogether if !( init <= term )
        !           238:                 */
        !           239:            after = (int) getlab();
        !           240:            putRV((char *) 0 , cbn , initnlp -> value[ NL_OFFS ] ,
        !           241:                    initnlp -> extra_flags , PCCT_INT );
        !           242:            putRV((char *) 0 , cbn , termnlp -> value[ NL_OFFS ] ,
        !           243:                    termnlp -> extra_flags , PCCT_INT );
        !           244:            putop( ( tree_node->tag == T_FORU ? PCC_LE : PCC_GE ) , PCCT_INT );
        !           245:            putleaf( PCC_ICON , after , 0 , PCCT_INT, (char *) 0 );
        !           246:            putop( PCC_CBRANCH , PCCT_INT );
        !           247:            putdot( filename , line );
        !           248:                /*
        !           249:                 * okay, so we have to execute the loop body,
        !           250:                 * but first, if checking is on,
        !           251:                 * check that the termination expression
        !           252:                 * is assignment compatible with the control-variable.
        !           253:                 */
        !           254:            if (opt('t')) {
        !           255:                precheck(fortype, "_RANG4", "_RSNG4");
        !           256:                putRV((char *) 0, cbn, termnlp -> value[NL_OFFS],
        !           257:                    termnlp -> extra_flags, PCCT_INT);
        !           258:                postcheck(fortype, nl+T4INT);
        !           259:                putdot(filename, line);
        !           260:            }
        !           261:                /*
        !           262:                 * assign the initial expression to the shadow
        !           263:                 * checking the assignment if necessary.
        !           264:                 */
        !           265:            putRV((char *) 0, cbn, shadownlp -> value[NL_OFFS],
        !           266:                shadownlp -> extra_flags, forp2type);
        !           267:            if (opt('t')) {
        !           268:                precheck(fortype, "_RANG4", "_RSNG4");
        !           269:                putRV((char *) 0, cbn, initnlp -> value[NL_OFFS],
        !           270:                    initnlp -> extra_flags, PCCT_INT);
        !           271:                postcheck(fortype, nl+T4INT);
        !           272:            } else {
        !           273:                putRV((char *) 0, cbn, initnlp -> value[NL_OFFS],
        !           274:                    initnlp -> extra_flags, PCCT_INT);
        !           275:            }
        !           276:            sconv(PCCT_INT, forp2type);
        !           277:            putop(PCC_ASSIGN, forp2type);
        !           278:            putdot(filename, line);
        !           279:                /*
        !           280:                 * put down the label at the top of the loop
        !           281:                 */
        !           282:            again = (int) getlab();
        !           283:            (void) putlab((char *) again );
        !           284:                /*
        !           285:                 * each time through the loop
        !           286:                 * assign the shadow to the for variable.
        !           287:                 */
        !           288:            (void) lvalue(lhs, NOUSE, RREQ);
        !           289:            putRV((char *) 0, cbn, shadownlp -> value[NL_OFFS],
        !           290:                    shadownlp -> extra_flags, forp2type);
        !           291:            putop(PCC_ASSIGN, forp2type);
        !           292:            putdot(filename, line);
        !           293: #      endif PC
        !           294: #      ifdef OBJ
        !           295:            (void) gen(O_AS2, O_AS2, sizeof(long), width(termtype));
        !           296:                /*
        !           297:                 * we can skip the loop altogether if !( init <= term )
        !           298:                 */
        !           299:            (void) put(2, O_RV4 | cbn<<8+INDX, initnlp -> value[ NL_OFFS ] );
        !           300:            (void) put(2, O_RV4 | cbn<<8+INDX, termnlp -> value[ NL_OFFS ] );
        !           301:            (void) gen(NIL, tree_node->tag == T_FORU ? T_LE : T_GE, sizeof(long),
        !           302:                        sizeof(long));
        !           303:            after = (int) getlab();
        !           304:            (void) put(2, O_IF, after);
        !           305:                /*
        !           306:                 * okay, so we have to execute the loop body,
        !           307:                 * but first, if checking is on,
        !           308:                 * check that the termination expression
        !           309:                 * is assignment compatible with the control-variable.
        !           310:                 */
        !           311:            if (opt('t')) {
        !           312:                (void) put(2, O_LV | cbn<<8+INDX, shadownlp -> value[ NL_OFFS ] );
        !           313:                (void) put(2, O_RV4 | cbn<<8+INDX, termnlp -> value[ NL_OFFS ] );
        !           314:                rangechk(fortype, nl+T4INT);
        !           315:                (void) gen(O_AS2, O_AS2, forwidth, sizeof(long));
        !           316:            }
        !           317:                /*
        !           318:                 * assign the initial expression to the shadow
        !           319:                 * checking the assignment if necessary.
        !           320:                 */
        !           321:            (void) put(2, O_LV | cbn<<8+INDX, shadownlp -> value[ NL_OFFS ] );
        !           322:            (void) put(2, O_RV4 | cbn<<8+INDX, initnlp -> value[ NL_OFFS ] );
        !           323:            rangechk(fortype, nl+T4INT);
        !           324:            (void) gen(O_AS2, O_AS2, forwidth, sizeof(long));
        !           325:                /*
        !           326:                 * put down the label at the top of the loop
        !           327:                 */
        !           328:            again = (int) getlab();
        !           329:            (void) putlab( (char *) again );
        !           330:                /*
        !           331:                 * each time through the loop
        !           332:                 * assign the shadow to the for variable.
        !           333:                 */
        !           334:            (void) lvalue(lhs, NOUSE, RREQ);
        !           335:            (void) stackRV(shadownlp);
        !           336:            (void) gen(O_AS2, O_AS2, forwidth, sizeof(long));
        !           337: #      endif OBJ
        !           338:            /*
        !           339:             *  shadowing the real for variable
        !           340:             *  with the shadow temporary:
        !           341:             *  save the real for variable flags (including nl_block).
        !           342:             *  replace them with the shadow's offset,
        !           343:             *  and mark the for variable as being a for variable.
        !           344:             */
        !           345:        shadownlp -> nl_flags |= NLFLAGS(forvar -> nl_flags);
        !           346:        *forvar = *shadownlp;
        !           347:        forvar -> symbol = saved_nl.symbol;
        !           348:        forvar -> nl_next = saved_nl.nl_next;
        !           349:        forvar -> type = saved_nl.type;
        !           350:        forvar -> value[ NL_FORV ] = FORVAR;
        !           351:            /*
        !           352:             * and don't forget ...
        !           353:             */
        !           354:        putcnt();
        !           355:        statement( stat_node );
        !           356:            /*
        !           357:             * wasn't that fun?  do we get to do it again?
        !           358:             *  we don't do it again if ( !( forvar < limit ) )
        !           359:             *  pretend we were doing this at the top of the loop
        !           360:             */
        !           361:        line = f_node->line_no;
        !           362: #      ifdef PC
        !           363:            if ( opt( 'p' ) ) {
        !           364:                if ( opt('t') ) {
        !           365:                    putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
        !           366:                            , "_LINO" );
        !           367:                    putop( PCCOM_UNARY PCC_CALL , PCCT_INT );
        !           368:                    putdot( filename , line );
        !           369:                } else {
        !           370:                    putRV( STMTCOUNT , 0 , 0 , NGLOBAL , PCCT_INT );
        !           371:                    putleaf( PCC_ICON , 1 , 0 , PCCT_INT , (char *) 0 );
        !           372:                    putop( PCCOM_ASG PCC_PLUS , PCCT_INT );
        !           373:                    putdot( filename , line );
        !           374:                }
        !           375:            }
        !           376:            /*rvalue( lhs_node , NIL , RREQ );*/
        !           377:            putRV( (char *) 0 , cbn , shadownlp -> value[ NL_OFFS ] ,
        !           378:                    shadownlp -> extra_flags , forp2type );
        !           379:            sconv(forp2type, PCCT_INT);
        !           380:            putRV( (char *) 0 , cbn , termnlp -> value[ NL_OFFS ] ,
        !           381:                    termnlp -> extra_flags , PCCT_INT );
        !           382:            putop( ( tree_node->tag == T_FORU ? PCC_LT : PCC_GT ) , PCCT_INT );
        !           383:            putleaf( PCC_ICON , after , 0 , PCCT_INT , (char *) 0 );
        !           384:            putop( PCC_CBRANCH , PCCT_INT );
        !           385:            putdot( filename , line );
        !           386:                /*
        !           387:                 * okay, so we have to do it again,
        !           388:                 * but first, increment the for variable.
        !           389:                 * no need to rangecheck it, since we checked the
        !           390:                 * termination value before we started.
        !           391:                 */
        !           392:            /*lvalue( lhs , MOD , RREQ );*/
        !           393:            putRV( (char *) 0 , cbn , shadownlp -> value[ NL_OFFS ] ,
        !           394:                    shadownlp -> extra_flags , forp2type );
        !           395:            /*rvalue( lhs_node , NIL , RREQ );*/
        !           396:            putRV( (char *) 0 , cbn , shadownlp -> value[ NL_OFFS ] ,
        !           397:                    shadownlp -> extra_flags , forp2type );
        !           398:            sconv(forp2type, PCCT_INT);
        !           399:            putleaf( PCC_ICON , 1 , 0 , PCCT_INT , (char *) 0 );
        !           400:            putop( ( tree_node->tag == T_FORU ? PCC_PLUS : PCC_MINUS ) , PCCT_INT );
        !           401:            sconv(PCCT_INT, forp2type);
        !           402:            putop( PCC_ASSIGN , forp2type );
        !           403:            putdot( filename , line );
        !           404:                /*
        !           405:                 * and do it all again
        !           406:                 */
        !           407:            putjbr( (long) again );
        !           408:                /*
        !           409:                 * and here we are
        !           410:                 */
        !           411:            (void) putlab( (char *) after );
        !           412: #      endif PC
        !           413: #      ifdef OBJ
        !           414:                /*
        !           415:                 * okay, so we have to do it again.
        !           416:                 * Luckily we have a magic opcode which increments the
        !           417:                 * index variable, checks the limit falling through if
        !           418:                 * it has been reached, else updating the index variable,
        !           419:                 * and returning to the top of the loop.
        !           420:                 */
        !           421:            putline();
        !           422:            (void) put(2, O_RV4 | cbn<<8+INDX, termnlp -> value[ NL_OFFS ] );
        !           423:            (void) put(2, O_LV | cbn<<8+INDX, shadownlp -> value[ NL_OFFS ] );
        !           424:            (void) put(2, (tree_node->tag == T_FORU ? O_FOR1U : O_FOR1D) + (forwidth >> 1),
        !           425:                    again);
        !           426:                /*
        !           427:                 * and here we are
        !           428:                 */
        !           429:            patch( (PTR_DCL) after );
        !           430: #      endif OBJ
        !           431: byebye:
        !           432:        noreach = FALSE;
        !           433:        if (forvar != NLNIL) {
        !           434:            saved_nl.nl_flags |= NLFLAGS(forvar -> nl_flags) & (NUSED|NMOD);
        !           435:            *forvar = saved_nl;
        !           436:        }
        !           437:        if ( goc != gocnt ) {
        !           438:            putcnt();
        !           439:        }
        !           440:     }

unix.superglobalmegacorp.com

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