1773Speter /* Copyright (c) 1979 Regents of the University of California */ 2773Speter 315941Smckusick #ifndef lint 4*18470Sralph static char sccsid[] = "@(#)stat.c 2.2 03/20/85"; 515941Smckusick #endif 6773Speter 7773Speter #include "whoami.h" 8773Speter #include "0.h" 9773Speter #include "tree.h" 10773Speter #include "objfmt.h" 11773Speter #ifdef PC 12*18470Sralph # include <pcc.h> 13773Speter # include "pc.h" 14773Speter #endif PC 1511330Speter #include "tmps.h" 16773Speter 17773Speter int cntstat; 18773Speter short cnts = 3; 19773Speter #include "opcode.h" 2015941Smckusick #include "tree_ty.h" 21773Speter 22773Speter /* 23773Speter * Statement list 24773Speter */ 25773Speter statlist(r) 2615941Smckusick struct tnode *r; 27773Speter { 2815941Smckusick register struct tnode *sl; 29773Speter 3015941Smckusick for (sl=r; sl != TR_NIL; sl=sl->list_node.next) 3115941Smckusick statement(sl->list_node.list); 32773Speter } 33773Speter 34773Speter /* 35773Speter * Statement 36773Speter */ 37773Speter statement(r) 3815941Smckusick struct tnode *r; 39773Speter { 4015941Smckusick register struct tnode *tree_node; 41773Speter register struct nl *snlp; 423228Smckusic struct tmps soffset; 43773Speter 4415941Smckusick tree_node = r; 45773Speter snlp = nlp; 463228Smckusic soffset = sizes[cbn].curtmps; 47773Speter top: 48773Speter if (cntstat) { 49773Speter cntstat = 0; 50773Speter putcnt(); 51773Speter } 5215941Smckusick if (tree_node == TR_NIL) 53773Speter return; 5415941Smckusick line = tree_node->lined.line_no; 5515941Smckusick if (tree_node->tag == T_LABEL) { 5615941Smckusick labeled(tree_node->label_node.lbl_ptr); 5715941Smckusick tree_node = tree_node->label_node.stmnt; 5815941Smckusick noreach = FALSE; 59773Speter cntstat = 1; 60773Speter goto top; 61773Speter } 62773Speter if (noreach) { 6315941Smckusick noreach = FALSE; 64773Speter warning(); 65773Speter error("Unreachable statement"); 66773Speter } 6715941Smckusick switch (tree_node->tag) { 68773Speter case T_PCALL: 69773Speter putline(); 70773Speter # ifdef OBJ 7115941Smckusick proc(tree_node); 72773Speter # endif OBJ 73773Speter # ifdef PC 7415941Smckusick pcproc( tree_node ); 75773Speter # endif PC 76773Speter break; 77773Speter case T_ASGN: 78773Speter putline(); 7915941Smckusick asgnop(&(tree_node->asg_node)); 80773Speter break; 81773Speter case T_GOTO: 82773Speter putline(); 8315941Smckusick gotoop(tree_node->goto_node.lbl_ptr); 8415941Smckusick noreach = TRUE; 85773Speter cntstat = 1; 86773Speter break; 87773Speter default: 88773Speter level++; 8915941Smckusick switch (tree_node->tag) { 90773Speter default: 91773Speter panic("stat"); 92773Speter case T_IF: 93773Speter case T_IFEL: 9415941Smckusick ifop(&(tree_node->if_node)); 95773Speter break; 96773Speter case T_WHILE: 9715941Smckusick whilop(&(tree_node->whi_cas)); 9815941Smckusick noreach = FALSE; 99773Speter break; 100773Speter case T_REPEAT: 10115941Smckusick repop(&(tree_node->repeat)); 102773Speter break; 103773Speter case T_FORU: 104773Speter case T_FORD: 10515941Smckusick forop(tree_node); 10615941Smckusick noreach = FALSE; 107773Speter break; 108773Speter case T_BLOCK: 10915941Smckusick statlist(tree_node->stmnt_blck.stmnt_list); 110773Speter break; 111773Speter case T_CASE: 112773Speter putline(); 113773Speter # ifdef OBJ 11415941Smckusick caseop(&(tree_node->whi_cas)); 115773Speter # endif OBJ 116773Speter # ifdef PC 11715941Smckusick pccaseop(&(tree_node->whi_cas)); 118773Speter # endif PC 119773Speter break; 120773Speter case T_WITH: 12115941Smckusick withop(&(tree_node->with_node)); 122773Speter break; 123773Speter } 124773Speter --level; 125773Speter if (gotos[cbn]) 126773Speter ungoto(); 127773Speter break; 128773Speter } 129773Speter /* 130773Speter * Free the temporary name list entries defined in 131773Speter * expressions, e.g. STRs, and WITHPTRs from withs. 132773Speter */ 133773Speter nlfree(snlp); 134773Speter /* 135773Speter * free any temporaries allocated for this statement 136773Speter * these come from strings and sets. 137773Speter */ 1383228Smckusic tmpfree(&soffset); 139773Speter } 140773Speter 141773Speter ungoto() 142773Speter { 143773Speter register struct nl *p; 144773Speter 14515941Smckusick for (p = gotos[cbn]; p != NLNIL; p = p->chain) 146773Speter if ((p->nl_flags & NFORWD) != 0) { 147773Speter if (p->value[NL_GOLEV] != NOTYET) 148773Speter if (p->value[NL_GOLEV] > level) 149773Speter p->value[NL_GOLEV] = level; 150773Speter } else 151773Speter if (p->value[NL_GOLEV] != DEAD) 152773Speter if (p->value[NL_GOLEV] > level) 153773Speter p->value[NL_GOLEV] = DEAD; 154773Speter } 155773Speter 156773Speter putcnt() 157773Speter { 158773Speter 15915941Smckusick if (monflg == FALSE) { 160773Speter return; 161773Speter } 162773Speter inccnt( getcnt() ); 163773Speter } 164773Speter 165773Speter int 166773Speter getcnt() 167773Speter { 168773Speter 169773Speter return ++cnts; 170773Speter } 171773Speter 172773Speter inccnt( counter ) 173773Speter int counter; 174773Speter { 175773Speter 176773Speter # ifdef OBJ 17715941Smckusick (void) put(2, O_COUNT, counter ); 178773Speter # endif OBJ 179773Speter # ifdef PC 180*18470Sralph putRV( PCPCOUNT , 0 , counter * sizeof (long) , NGLOBAL , PCCT_INT ); 181*18470Sralph putleaf( PCC_ICON , 1 , 0 , PCCT_INT , (char *) 0 ); 182*18470Sralph putop( PCCOM_ASG PCC_PLUS , PCCT_INT ); 183773Speter putdot( filename , line ); 184773Speter # endif PC 185773Speter } 186773Speter 187773Speter putline() 188773Speter { 189773Speter 190773Speter # ifdef OBJ 191773Speter if (opt('p') != 0) 19215941Smckusick (void) put(2, O_LINO, line); 1935654Slinton 1945654Slinton /* 1955654Slinton * put out line number information for pdx 1965654Slinton */ 1975654Slinton lineno(line); 1985654Slinton 199773Speter # endif OBJ 200773Speter # ifdef PC 201773Speter static lastline; 202773Speter 203773Speter if ( line != lastline ) { 204773Speter stabline( line ); 205773Speter lastline = line; 206773Speter } 207773Speter if ( opt( 'p' ) ) { 208773Speter if ( opt('t') ) { 209*18470Sralph putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 210773Speter , "_LINO" ); 211*18470Sralph putop( PCCOM_UNARY PCC_CALL , PCCT_INT ); 212773Speter putdot( filename , line ); 213773Speter } else { 214*18470Sralph putRV( STMTCOUNT , 0 , 0 , NGLOBAL , PCCT_INT ); 215*18470Sralph putleaf( PCC_ICON , 1 , 0 , PCCT_INT , (char *) 0 ); 216*18470Sralph putop( PCCOM_ASG PCC_PLUS , PCCT_INT ); 217773Speter putdot( filename , line ); 218773Speter } 219773Speter } 220773Speter # endif PC 221773Speter } 222773Speter 223773Speter /* 224773Speter * With varlist do stat 225773Speter * 226773Speter * With statement requires an extra word 227773Speter * in automatic storage for each level of withing. 228773Speter * These indirect pointers are initialized here, and 229773Speter * the scoping effect of the with statement occurs 230773Speter * because lookup examines the field names of the records 231773Speter * associated with the WITHPTRs on the withlist. 232773Speter */ 233773Speter withop(s) 23415941Smckusick WITH_NODE *s; 235773Speter { 23615941Smckusick register struct tnode *p; 237773Speter register struct nl *r; 2383835Speter struct nl *tempnlp; 23915941Smckusick struct nl *swl; 240773Speter 241773Speter putline(); 242773Speter swl = withlist; 24315941Smckusick for (p = s->var_list; p != TR_NIL; p = p->list_node.next) { 24415951Smckusick tempnlp = tmpalloc((long) (sizeof(int *)), nl+TPTR, REGOK); 24515951Smckusick /* 24615951Smckusick * no one uses the allocated temporary namelist entry, 24715951Smckusick * since we have to use it before we know its type; 24815951Smckusick * but we use its runtime location for the with pointer. 24915951Smckusick */ 250773Speter # ifdef OBJ 25115941Smckusick (void) put(2, O_LV | cbn <<8+INDX, tempnlp -> value[ NL_OFFS ] ); 252773Speter # endif OBJ 253773Speter # ifdef PC 25415941Smckusick putRV( (char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] , 255*18470Sralph tempnlp -> extra_flags , PCCTM_PTR|PCCT_STRTY ); 256773Speter # endif PC 25715941Smckusick r = lvalue(p->list_node.list, MOD , LREQ ); 25815941Smckusick if (r == NLNIL) 259773Speter continue; 260773Speter if (r->class != RECORD) { 261773Speter error("Variable in with statement refers to %s, not to a record", nameof(r)); 262773Speter continue; 263773Speter } 26415941Smckusick r = defnl((char *) 0, WITHPTR, r, tempnlp -> value[ NL_OFFS ] ); 2653835Speter # ifdef PC 2663835Speter r -> extra_flags |= tempnlp -> extra_flags; 2673835Speter # endif PC 268773Speter r->nl_next = withlist; 269773Speter withlist = r; 270773Speter # ifdef OBJ 27115941Smckusick (void) put(1, PTR_AS); 272773Speter # endif OBJ 273773Speter # ifdef PC 274*18470Sralph putop( PCC_ASSIGN , PCCTM_PTR|PCCT_STRTY ); 275773Speter putdot( filename , line ); 276773Speter # endif PC 277773Speter } 27815941Smckusick statement(s->stmnt); 279773Speter withlist = swl; 280773Speter } 281773Speter 282773Speter extern flagwas; 283773Speter /* 284773Speter * var := expr 285773Speter */ 286773Speter asgnop(r) 28715941Smckusick ASG_NODE *r; 288773Speter { 289773Speter register struct nl *p; 29015941Smckusick register struct tnode *av; 291773Speter 292773Speter /* 293773Speter * Asgnop's only function is 294773Speter * to handle function variable 295773Speter * assignments. All other assignment 296773Speter * stuff is handled by asgnop1. 297773Speter * the if below checks for unqualified lefthandside: 298773Speter * necessary for fvars. 299773Speter */ 30015941Smckusick av = r->lhs_var; 30115941Smckusick if (av != TR_NIL && av->tag == T_VAR && av->var_node.qual == TR_NIL) { 30215941Smckusick p = lookup1(av->var_node.cptr); 30315941Smckusick if (p != NLNIL) 304773Speter p->nl_flags = flagwas; 30515941Smckusick if (p != NLNIL && p->class == FVAR) { 306773Speter /* 307773Speter * Give asgnop1 the func 308773Speter * which is the chain of 309773Speter * the FVAR. 310773Speter */ 311773Speter p->nl_flags |= NUSED|NMOD; 312773Speter p = p->chain; 31315941Smckusick if (p == NLNIL) { 31415941Smckusick p = rvalue(r->rhs_expr, NLNIL , RREQ ); 315773Speter return; 316773Speter } 317773Speter # ifdef OBJ 31815941Smckusick (void) put(2, O_LV | bn << 8+INDX, (int)p->value[NL_OFFS]); 319773Speter if (isa(p->type, "i") && width(p->type) == 1) 32015941Smckusick (void) asgnop1(r, nl+T2INT); 321773Speter else 32215941Smckusick (void) asgnop1(r, p->type); 323773Speter # endif OBJ 324773Speter # ifdef PC 325773Speter /* 326773Speter * this should be the lvalue of the fvar, 327773Speter * but since the second pass knows to use 328773Speter * the address of the left operand of an 329773Speter * assignment, what i want here is an rvalue. 330773Speter * see note in funchdr about fvar allocation. 331773Speter */ 332773Speter p = p -> ptr[ NL_FVAR ]; 3333835Speter putRV( p -> symbol , bn , p -> value[ NL_OFFS ] , 3343835Speter p -> extra_flags , p2type( p -> type ) ); 33515941Smckusick (void) asgnop1( r , p -> type ); 336773Speter # endif PC 337773Speter return; 338773Speter } 339773Speter } 34015941Smckusick (void) asgnop1(r, NLNIL); 341773Speter } 342773Speter 343773Speter /* 344773Speter * Asgnop1 handles all assignments. 345773Speter * If p is not nil then we are assigning 346773Speter * to a function variable, otherwise 347773Speter * we look the variable up ourselves. 348773Speter */ 349773Speter struct nl * 350773Speter asgnop1(r, p) 35115941Smckusick ASG_NODE *r; 352773Speter register struct nl *p; 353773Speter { 354773Speter register struct nl *p1; 35515985Saoki int clas; 35615941Smckusick #ifdef OBJ 3573079Smckusic int w; 35815985Saoki #endif OBJ 359773Speter 36015985Saoki #ifdef OBJ 36115941Smckusick if (p == NLNIL) { 36215985Saoki p = lvalue(r->lhs_var, MOD|ASGN|NOUSE , LREQ ); 36315941Smckusick if ( p == NLNIL ) { 36415941Smckusick (void) rvalue( r->rhs_expr , NLNIL , RREQ ); 36515941Smckusick return NLNIL; 366773Speter } 36715985Saoki w = width(p); 36815985Saoki } else { 3693079Smckusic /* 3703079Smckusic * assigning to the return value, which is at least 3713079Smckusic * of width two since it resides on the stack 3723079Smckusic */ 37315985Saoki w = width(p); 37415985Saoki if (w < 2) 37515985Saoki w = 2; 37615985Saoki } 37715985Saoki clas = classify(p); 37815985Saoki if ((clas == TARY || clas == TSTR) && p->chain->class == CRANGE) { 37915985Saoki p1 = lvalue(r->rhs_expr, p , LREQ ); /* SHOULD THIS BE rvalue? */ 38015985Saoki } else { 38115985Saoki p1 = rvalue(r->rhs_expr, p , RREQ ); 38215985Saoki } 38315985Saoki # endif OBJ 38415985Saoki # ifdef PC 38515985Saoki if (p == NLNIL) { 38615985Saoki /* check for conformant array type */ 38715985Saoki codeoff(); 38815985Saoki p = rvalue(r->lhs_var, MOD|ASGN|NOUSE, LREQ); 38915985Saoki codeon(); 39015985Saoki if (p == NLNIL) { 39115985Saoki (void) rvalue(r->rhs_expr, NLNIL, RREQ); 39215985Saoki return NLNIL; 3933079Smckusic } 39415985Saoki clas = classify(p); 39515985Saoki if ((clas == TARY || clas == TSTR) && p->chain->class == CRANGE) { 39615985Saoki return pcasgconf(r, p); 39715970Smckusick } else { 398773Speter /* 39915985Saoki * since the second pass knows that it should reference 40015985Saoki * the lefthandside of asignments, what i need here is 40115985Saoki * an rvalue. 402773Speter */ 40315985Saoki p = lvalue( r->lhs_var , MOD|ASGN|NOUSE , RREQ ); 404773Speter } 40515985Saoki if ( p == NLNIL ) { 40615985Saoki (void) rvalue( r->rhs_expr , NLNIL , RREQ ); 40715985Saoki return NLNIL; 40815985Saoki } 40915985Saoki } 41015985Saoki /* 41115985Saoki * if this is a scalar assignment, 41215985Saoki * then i want to rvalue the righthandside. 41315985Saoki * if this is a structure assignment, 41415985Saoki * then i want an lvalue to the righthandside. 41515985Saoki * that's what the intermediate form sez. 41615985Saoki */ 41715985Saoki switch ( classify( p ) ) { 41815985Saoki case TINT: 41915985Saoki case TCHAR: 42015985Saoki case TBOOL: 42115985Saoki case TSCAL: 42215985Saoki precheck( p , "_RANG4" , "_RSNG4" ); 42315985Saoki /* and fall through */ 42415985Saoki case TDOUBLE: 42515985Saoki case TPTR: 42615985Saoki p1 = rvalue( r->rhs_expr , p , RREQ ); 42715985Saoki break; 42815985Saoki default: 42915985Saoki p1 = rvalue( r->rhs_expr , p , LREQ ); 43015985Saoki break; 43115985Saoki } 432773Speter # endif PC 43315941Smckusick if (p1 == NLNIL) 43415941Smckusick return (NLNIL); 43515941Smckusick if (incompat(p1, p, r->rhs_expr)) { 436773Speter cerror("Type of expression clashed with type of variable in assignment"); 43715941Smckusick return (NLNIL); 438773Speter } 4398758Speter # ifdef OBJ 4408758Speter switch (classify(p)) { 4418758Speter case TINT: 4428758Speter case TBOOL: 4438758Speter case TCHAR: 4448758Speter case TSCAL: 445773Speter rangechk(p, p1); 44615941Smckusick (void) gen(O_AS2, O_AS2, w, width(p1)); 4478758Speter break; 4488758Speter case TDOUBLE: 4498758Speter case TPTR: 45015941Smckusick (void) gen(O_AS2, O_AS2, w, width(p1)); 4518758Speter break; 45215970Smckusick case TARY: 45315970Smckusick case TSTR: 45415970Smckusick if (p->chain->class == CRANGE) { 45515970Smckusick /* conformant array assignment */ 45615970Smckusick p1 = p->chain; 45715970Smckusick w = width(p1->type); 45815970Smckusick putcbnds(p1, 1); 45915970Smckusick putcbnds(p1, 0); 46015970Smckusick gen(NIL, T_SUB, w, w); 46115970Smckusick put(2, w > 2? O_CON24: O_CON2, 1); 46215970Smckusick gen(NIL, T_ADD, w, w); 46315970Smckusick putcbnds(p1, 2); 46415970Smckusick gen(NIL, T_MULT, w, w); 46515970Smckusick put(1, O_VAS); 46615970Smckusick break; 46715970Smckusick } 46815970Smckusick /* else fall through */ 4698758Speter default: 47015941Smckusick (void) put(2, O_AS, w); 4718758Speter break; 4728758Speter } 4738758Speter # endif OBJ 4748758Speter # ifdef PC 4758758Speter switch (classify(p)) { 4768758Speter case TINT: 4778758Speter case TBOOL: 4788758Speter case TCHAR: 4798758Speter case TSCAL: 48010362Smckusick postcheck(p, p1); 48110362Smckusick sconv(p2type(p1), p2type(p)); 482*18470Sralph putop( PCC_ASSIGN , p2type( p ) ); 483773Speter putdot( filename , line ); 4848758Speter break; 4858758Speter case TPTR: 486*18470Sralph putop( PCC_ASSIGN , p2type( p ) ); 4878758Speter putdot( filename , line ); 4888758Speter break; 4898758Speter case TDOUBLE: 49010362Smckusick sconv(p2type(p1), p2type(p)); 491*18470Sralph putop( PCC_ASSIGN , p2type( p ) ); 4928758Speter putdot( filename , line ); 4938758Speter break; 4948758Speter default: 495*18470Sralph putstrop(PCC_STASG, PCCM_ADDTYPE(p2type(p), PCCTM_PTR), 49615941Smckusick (int) lwidth(p), align(p)); 497773Speter putdot( filename , line ); 4988758Speter break; 4998758Speter } 5008758Speter # endif PC 501773Speter return (p); /* Used by for statement */ 502773Speter } 503773Speter 50415985Saoki #ifdef PC 505773Speter /* 50615985Saoki * assignment to conformant arrays. Since these are variable length, 50715985Saoki * we use blkcpy() to perform the assignment. 50815985Saoki * blkcpy(rhs, lhs, (upper - lower + 1) * width) 50915985Saoki */ 51015985Saoki struct nl * 51115985Saoki pcasgconf(r, p) 51215985Saoki register ASG_NODE *r; 51315985Saoki struct nl *p; 51415985Saoki { 51515985Saoki struct nl *p1; 51615985Saoki 51715985Saoki if (r == (ASG_NODE *) TR_NIL || p == NLNIL) 51815985Saoki return NLNIL; 519*18470Sralph putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR) , "_blkcpy" ); 52015985Saoki p1 = rvalue( r->rhs_expr , p , LREQ ); 52115985Saoki if (p1 == NLNIL) 52215985Saoki return NLNIL; 52315985Saoki p = lvalue( r->lhs_var , MOD|ASGN|NOUSE , LREQ ); 52415985Saoki if (p == NLNIL) 52515985Saoki return NLNIL; 526*18470Sralph putop(PCC_CM, PCCT_INT); 52715985Saoki /* upper bound */ 52815985Saoki p1 = p->chain->nptr[1]; 52915985Saoki putRV(p1->symbol, (p1->nl_block & 037), p1->value[0], 53015985Saoki p1->extra_flags, p2type( p1 ) ); 53115985Saoki /* minus lower bound */ 53215985Saoki p1 = p->chain->nptr[0]; 53315985Saoki putRV(p1->symbol, (p1->nl_block & 037), p1->value[0], 53415985Saoki p1->extra_flags, p2type( p1 ) ); 535*18470Sralph putop( PCC_MINUS, PCCT_INT ); 53615985Saoki /* add one */ 537*18470Sralph putleaf(PCC_ICON, 1, 0, PCCT_INT, 0); 538*18470Sralph putop( PCC_PLUS, PCCT_INT ); 53915985Saoki /* and multiply by the width */ 54015985Saoki p1 = p->chain->nptr[2]; 54115985Saoki putRV(p1->symbol, (p1->nl_block & 037), p1->value[0], 54215985Saoki p1->extra_flags, p2type( p1 ) ); 543*18470Sralph putop( PCC_MUL , PCCT_INT ); 544*18470Sralph putop(PCC_CM, PCCT_INT); 545*18470Sralph putop(PCC_CALL, PCCT_INT); 54615985Saoki putdot( filename , line); 54715985Saoki return p; 54815985Saoki } 54915985Saoki #endif PC 55015985Saoki 55115985Saoki /* 552773Speter * if expr then stat [ else stat ] 553773Speter */ 55415941Smckusick ifop(if_n) 55515941Smckusick IF_NODE *if_n; 556773Speter { 557773Speter register struct nl *p; 558773Speter register l1, l2; /* l1 is start of else, l2 is end of else */ 5593079Smckusic int goc; 5603079Smckusic bool nr; 561773Speter 562773Speter goc = gocnt; 563773Speter putline(); 56415941Smckusick p = rvalue(if_n->cond_expr, NLNIL , RREQ ); 565773Speter if (p == NIL) { 56615941Smckusick statement(if_n->then_stmnt); 56715941Smckusick noreach = FALSE; 56815941Smckusick statement(if_n->else_stmnt); 56915941Smckusick noreach = FALSE; 570773Speter return; 571773Speter } 572773Speter if (isnta(p, "b")) { 573773Speter error("Type of expression in if statement must be Boolean, not %s", nameof(p)); 57415941Smckusick statement(if_n->then_stmnt); 57515941Smckusick noreach = FALSE; 57615941Smckusick statement(if_n->else_stmnt); 57715941Smckusick noreach = FALSE; 578773Speter return; 579773Speter } 580773Speter # ifdef OBJ 5813079Smckusic l1 = put(2, O_IF, getlab()); 582773Speter # endif OBJ 583773Speter # ifdef PC 58415941Smckusick l1 = (int) getlab(); 585*18470Sralph putleaf( PCC_ICON , l1 , 0 , PCCT_INT , (char *) 0 ); 586*18470Sralph putop( PCC_CBRANCH , PCCT_INT ); 587773Speter putdot( filename , line ); 588773Speter # endif PC 589773Speter putcnt(); 59015941Smckusick statement(if_n->then_stmnt); 591773Speter nr = noreach; 59215941Smckusick if (if_n->else_stmnt != TR_NIL) { 593773Speter /* 594773Speter * else stat 595773Speter */ 596773Speter --level; 597773Speter ungoto(); 598773Speter ++level; 599773Speter # ifdef OBJ 6003079Smckusic l2 = put(2, O_TRA, getlab()); 601773Speter # endif OBJ 602773Speter # ifdef PC 60315941Smckusick l2 = (int) getlab(); 60415941Smckusick putjbr( (long) l2 ); 605773Speter # endif PC 60615941Smckusick patch((PTR_DCL)l1); 60715941Smckusick noreach = FALSE; 60815941Smckusick statement(if_n->else_stmnt); 60915941Smckusick noreach = (noreach && nr)?TRUE:FALSE; 610773Speter l1 = l2; 611773Speter } else 61215941Smckusick noreach = FALSE; 61315941Smckusick patch((PTR_DCL)l1); 614773Speter if (goc != gocnt) 615773Speter putcnt(); 616773Speter } 617773Speter 618773Speter /* 619773Speter * while expr do stat 620773Speter */ 62115941Smckusick whilop(w_node) 62215941Smckusick WHI_CAS *w_node; 623773Speter { 624773Speter register struct nl *p; 62515941Smckusick register char *l1, *l2; 626773Speter int goc; 627773Speter 628773Speter goc = gocnt; 62915941Smckusick l1 = getlab(); 63015941Smckusick (void) putlab(l1); 631773Speter putline(); 63215941Smckusick p = rvalue(w_node->expr, NLNIL , RREQ ); 63315941Smckusick if (p == NLNIL) { 63415941Smckusick statement(w_node->stmnt_list); 63515941Smckusick noreach = FALSE; 636773Speter return; 637773Speter } 638773Speter if (isnta(p, "b")) { 639773Speter error("Type of expression in while statement must be Boolean, not %s", nameof(p)); 64015941Smckusick statement(w_node->stmnt_list); 64115941Smckusick noreach = FALSE; 642773Speter return; 643773Speter } 644773Speter l2 = getlab(); 645773Speter # ifdef OBJ 64615941Smckusick (void) put(2, O_IF, l2); 647773Speter # endif OBJ 648773Speter # ifdef PC 649*18470Sralph putleaf( PCC_ICON , (int) l2 , 0 , PCCT_INT , (char *) 0 ); 650*18470Sralph putop( PCC_CBRANCH , PCCT_INT ); 651773Speter putdot( filename , line ); 652773Speter # endif PC 653773Speter putcnt(); 65415941Smckusick statement(w_node->stmnt_list); 655773Speter # ifdef OBJ 65615941Smckusick (void) put(2, O_TRA, l1); 657773Speter # endif OBJ 658773Speter # ifdef PC 65915941Smckusick putjbr( (long) l1 ); 660773Speter # endif PC 66115941Smckusick patch((PTR_DCL) l2); 662773Speter if (goc != gocnt) 663773Speter putcnt(); 664773Speter } 665773Speter 666773Speter /* 667773Speter * repeat stat* until expr 668773Speter */ 669773Speter repop(r) 67015941Smckusick REPEAT *r; 671773Speter { 672773Speter register struct nl *p; 673773Speter register l; 674773Speter int goc; 675773Speter 676773Speter goc = gocnt; 67715941Smckusick l = (int) putlab(getlab()); 678773Speter putcnt(); 67915941Smckusick statlist(r->stmnt_list); 68015941Smckusick line = r->line_no; 68115941Smckusick p = rvalue(r->term_expr, NLNIL , RREQ ); 68215941Smckusick if (p == NLNIL) 683773Speter return; 684773Speter if (isnta(p,"b")) { 685773Speter error("Until expression type must be Boolean, not %s, in repeat statement", nameof(p)); 686773Speter return; 687773Speter } 688773Speter # ifdef OBJ 68915941Smckusick (void) put(2, O_IF, l); 690773Speter # endif OBJ 691773Speter # ifdef PC 692*18470Sralph putleaf( PCC_ICON , l , 0 , PCCT_INT , (char *) 0 ); 693*18470Sralph putop( PCC_CBRANCH , PCCT_INT ); 694773Speter putdot( filename , line ); 695773Speter # endif PC 696773Speter if (goc != gocnt) 697773Speter putcnt(); 698773Speter } 699