Annotation of 42BSD/ucb/pascal/src/forop.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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