Annotation of 43BSDTahoe/ucb/pascal/src/forop.c, revision 1.1.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.