📄 forop.c
字号:
/*- * Copyright (c) 1980, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char sccsid[] = "@(#)forop.c 8.1 (Berkeley) 6/6/93";#endif /* not lint */#include "whoami.h"#include "0.h"#include "opcode.h"#include "tree.h"#include "objfmt.h"#ifdef PC# include "pc.h"# include <pcc.h>#endif PC#include "tmps.h"#include "tree_ty.h" /* * for-statements. * * the relevant quote from the standard: 6.8.3.9: * ``The control-variable shall be an entire-variable whose identifier * is declared in the variable-declaration-part of the block closest- * containing the for-statement. The control-variable shall possess * an ordinal-type, and the initial-value and the final-value shall be * of a type compatible with this type. The statement of a for-statement * shall not contain an assigning-reference to the control-variable * of the for-statement. The value of the final-value shall be * assignment-compatible with the control-variable when the initial-value * is assigned to the control-variable. After a for-statement is * executed (other than being left by a goto-statement leading out of it) * the control-variable shall be undefined. Apart from the restrictions * imposed by these requirements, the for-statement * for v := e1 to e2 do body * shall be equivalent to * begin * temp1 := e1; * temp2 := e2; * if temp1 <= temp2 then begin * v := temp1; * body; * while v <> temp2 do begin * v := succ(v); * body; * end * end * end * where temp1 and temp2 denote auxiliary variables that the program * does not otherwise contain, and that possess the type possessed by * the variable v if that type is not a subrange-type; otherwise the * host type possessed by the variable v.'' * * The Berkeley Pascal systems try to do all that without duplicating * the body, and shadowing the control-variable in (possibly) a * register variable. * * arg here looks like: * arg[0] T_FORU or T_FORD * [1] lineof "for" * [2] [0] T_ASGN * [1] lineof ":=" * [2] [0] T_VAR * [1] lineof id * [2] char * to id * [3] qualifications * [3] initial expression * [3] termination expression * [4] statement */forop( tree_node) struct tnode *tree_node; { struct tnode *lhs; VAR_NODE *lhs_node; FOR_NODE *f_node; struct nl *forvar; struct nl *fortype;#ifdef PC int forp2type;#endif PC int forwidth; struct tnode *init_node; struct nl *inittype; struct nl *initnlp; /* initial value namelist entry */ struct tnode *term_node; struct nl *termtype; struct nl *termnlp; /* termination value namelist entry */ struct nl *shadownlp; /* namelist entry for the shadow */ struct tnode *stat_node; int goc; /* saved gocnt */ int again; /* label at the top of the loop */ int after; /* label after the end of the loop */ struct nl saved_nl; /* saved namelist entry for loop var */ goc = gocnt; forvar = NLNIL; if ( tree_node == TR_NIL ) { goto byebye; } f_node = &(tree_node->for_node); if ( f_node->init_asg == TR_NIL ) { goto byebye; } line = f_node->line_no; putline(); lhs = f_node->init_asg->asg_node.lhs_var; init_node = f_node->init_asg->asg_node.rhs_expr; term_node = f_node->term_expr; stat_node = f_node->for_stmnt; if (lhs == TR_NIL) {nogood: if (forvar != NIL) { forvar->value[ NL_FORV ] = FORVAR; } (void) rvalue( init_node , NLNIL , RREQ ); (void) rvalue( term_node , NLNIL , RREQ ); statement( stat_node ); goto byebye; } else lhs_node = &(lhs->var_node); /* * and this marks the variable as used!!! */ forvar = lookup( lhs_node->cptr ); if ( forvar == NIL ) { goto nogood; } saved_nl = *forvar; if ( lhs_node->qual != TR_NIL ) { error("For variable %s must be unqualified", forvar->symbol); goto nogood; } if (forvar->class == WITHPTR) { error("For variable %s cannot be an element of a record", lhs_node->cptr); goto nogood; } if ( opt('s') && ( ( bn != cbn ) ||#ifdef OBJ (whereis(forvar->value[NL_OFFS], 0) == PARAMVAR)#endif OBJ#ifdef PC (whereis(forvar->value[NL_OFFS], forvar->extra_flags) == PARAMVAR )#endif PC ) ) { standard(); error("For variable %s must be declared in the block in which it is used", forvar->symbol); } /* * find out the type of the loop variable */ codeoff(); fortype = lvalue( lhs , MOD , RREQ ); codeon(); if ( fortype == NLNIL ) { goto nogood; } if ( isnta( fortype , "bcis" ) ) { error("For variable %s cannot be %ss", forvar->symbol, nameof( fortype ) ); goto nogood; } if ( forvar->value[ NL_FORV ] & FORVAR ) { error("Can't modify the for variable %s in the range of the loop", forvar->symbol); forvar = NLNIL; goto nogood; } forwidth = lwidth(fortype);# ifdef PC forp2type = p2type(fortype);# endif PC /* * allocate temporaries for the initial and final expressions * and maybe a register to shadow the for variable. */ initnlp = tmpalloc((long) sizeof(long), nl+T4INT, NOREG); termnlp = tmpalloc((long) sizeof(long), nl+T4INT, NOREG); shadownlp = tmpalloc((long) forwidth, fortype, REGOK);# ifdef PC /* * compute and save the initial expression */ putRV((char *) 0 , cbn , initnlp -> value[ NL_OFFS ] , initnlp -> extra_flags , PCCT_INT );# endif PC# ifdef OBJ (void) put(2, O_LV | cbn<<8+INDX, initnlp -> value[ NL_OFFS ] );# endif OBJ inittype = rvalue( init_node , fortype , RREQ ); if ( incompat( inittype , fortype , init_node ) ) { cerror("Type of initial expression clashed with index type in 'for' statement"); if (forvar != NLNIL) { forvar->value[ NL_FORV ] = FORVAR; } (void) rvalue( term_node , NLNIL , RREQ ); statement( stat_node ); goto byebye; }# ifdef PC sconv(p2type(inittype), PCCT_INT); putop( PCC_ASSIGN , PCCT_INT );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -