1*48116Sbostic /*- 2*48116Sbostic * Copyright (c) 1980 The Regents of the University of California. 3*48116Sbostic * All rights reserved. 4*48116Sbostic * 5*48116Sbostic * %sccs.include.redist.c% 622192Sdist */ 7773Speter 815941Smckusick #ifndef lint 9*48116Sbostic static char sccsid[] = "@(#)stat.c 5.2 (Berkeley) 04/16/91"; 10*48116Sbostic #endif /* not lint */ 11773Speter 12773Speter #include "whoami.h" 13773Speter #include "0.h" 14773Speter #include "tree.h" 15773Speter #include "objfmt.h" 16773Speter #ifdef PC 1718470Sralph # include <pcc.h> 18773Speter # include "pc.h" 19773Speter #endif PC 2011330Speter #include "tmps.h" 21773Speter 22773Speter int cntstat; 23773Speter short cnts = 3; 24773Speter #include "opcode.h" 2515941Smckusick #include "tree_ty.h" 26773Speter 27773Speter /* 28773Speter * Statement list 29773Speter */ 30773Speter statlist(r) 3115941Smckusick struct tnode *r; 32773Speter { 3315941Smckusick register struct tnode *sl; 34773Speter 3515941Smckusick for (sl=r; sl != TR_NIL; sl=sl->list_node.next) 3615941Smckusick statement(sl->list_node.list); 37773Speter } 38773Speter 39773Speter /* 40773Speter * Statement 41773Speter */ 42773Speter statement(r) 4315941Smckusick struct tnode *r; 44773Speter { 4515941Smckusick register struct tnode *tree_node; 46773Speter register struct nl *snlp; 473228Smckusic struct tmps soffset; 48773Speter 4915941Smckusick tree_node = r; 50773Speter snlp = nlp; 513228Smckusic soffset = sizes[cbn].curtmps; 52773Speter top: 53773Speter if (cntstat) { 54773Speter cntstat = 0; 55773Speter putcnt(); 56773Speter } 5715941Smckusick if (tree_node == TR_NIL) 58773Speter return; 5915941Smckusick line = tree_node->lined.line_no; 6015941Smckusick if (tree_node->tag == T_LABEL) { 6115941Smckusick labeled(tree_node->label_node.lbl_ptr); 6215941Smckusick tree_node = tree_node->label_node.stmnt; 6315941Smckusick noreach = FALSE; 64773Speter cntstat = 1; 65773Speter goto top; 66773Speter } 67773Speter if (noreach) { 6815941Smckusick noreach = FALSE; 69773Speter warning(); 70773Speter error("Unreachable statement"); 71773Speter } 7215941Smckusick switch (tree_node->tag) { 73773Speter case T_PCALL: 74773Speter putline(); 75773Speter # ifdef OBJ 7615941Smckusick proc(tree_node); 77773Speter # endif OBJ 78773Speter # ifdef PC 7915941Smckusick pcproc( tree_node ); 80773Speter # endif PC 81773Speter break; 82773Speter case T_ASGN: 83773Speter putline(); 8415941Smckusick asgnop(&(tree_node->asg_node)); 85773Speter break; 86773Speter case T_GOTO: 87773Speter putline(); 8815941Smckusick gotoop(tree_node->goto_node.lbl_ptr); 8915941Smckusick noreach = TRUE; 90773Speter cntstat = 1; 91773Speter break; 92773Speter default: 93773Speter level++; 9415941Smckusick switch (tree_node->tag) { 95773Speter default: 96773Speter panic("stat"); 97773Speter case T_IF: 98773Speter case T_IFEL: 9915941Smckusick ifop(&(tree_node->if_node)); 100773Speter break; 101773Speter case T_WHILE: 10215941Smckusick whilop(&(tree_node->whi_cas)); 10315941Smckusick noreach = FALSE; 104773Speter break; 105773Speter case T_REPEAT: 10615941Smckusick repop(&(tree_node->repeat)); 107773Speter break; 108773Speter case T_FORU: 109773Speter case T_FORD: 11015941Smckusick forop(tree_node); 11115941Smckusick noreach = FALSE; 112773Speter break; 113773Speter case T_BLOCK: 11415941Smckusick statlist(tree_node->stmnt_blck.stmnt_list); 115773Speter break; 116773Speter case T_CASE: 117773Speter putline(); 118773Speter # ifdef OBJ 11915941Smckusick caseop(&(tree_node->whi_cas)); 120773Speter # endif OBJ 121773Speter # ifdef PC 12215941Smckusick pccaseop(&(tree_node->whi_cas)); 123773Speter # endif PC 124773Speter break; 125773Speter case T_WITH: 12615941Smckusick withop(&(tree_node->with_node)); 127773Speter break; 128773Speter } 129773Speter --level; 130773Speter if (gotos[cbn]) 131773Speter ungoto(); 132773Speter break; 133773Speter } 134773Speter /* 135773Speter * Free the temporary name list entries defined in 136773Speter * expressions, e.g. STRs, and WITHPTRs from withs. 137773Speter */ 138773Speter nlfree(snlp); 139773Speter /* 140773Speter * free any temporaries allocated for this statement 141773Speter * these come from strings and sets. 142773Speter */ 1433228Smckusic tmpfree(&soffset); 144773Speter } 145773Speter 146773Speter ungoto() 147773Speter { 148773Speter register struct nl *p; 149773Speter 15015941Smckusick for (p = gotos[cbn]; p != NLNIL; p = p->chain) 151773Speter if ((p->nl_flags & NFORWD) != 0) { 152773Speter if (p->value[NL_GOLEV] != NOTYET) 153773Speter if (p->value[NL_GOLEV] > level) 154773Speter p->value[NL_GOLEV] = level; 155773Speter } else 156773Speter if (p->value[NL_GOLEV] != DEAD) 157773Speter if (p->value[NL_GOLEV] > level) 158773Speter p->value[NL_GOLEV] = DEAD; 159773Speter } 160773Speter 161773Speter putcnt() 162773Speter { 163773Speter 16415941Smckusick if (monflg == FALSE) { 165773Speter return; 166773Speter } 167773Speter inccnt( getcnt() ); 168773Speter } 169773Speter 170773Speter int 171773Speter getcnt() 172773Speter { 173773Speter 174773Speter return ++cnts; 175773Speter } 176773Speter 177773Speter inccnt( counter ) 178773Speter int counter; 179773Speter { 180773Speter 181773Speter # ifdef OBJ 18215941Smckusick (void) put(2, O_COUNT, counter ); 183773Speter # endif OBJ 184773Speter # ifdef PC 18518470Sralph putRV( PCPCOUNT , 0 , counter * sizeof (long) , NGLOBAL , PCCT_INT ); 18618470Sralph putleaf( PCC_ICON , 1 , 0 , PCCT_INT , (char *) 0 ); 18718470Sralph putop( PCCOM_ASG PCC_PLUS , PCCT_INT ); 188773Speter putdot( filename , line ); 189773Speter # endif PC 190773Speter } 191773Speter 192773Speter putline() 193773Speter { 194773Speter 195773Speter # ifdef OBJ 196773Speter if (opt('p') != 0) 19715941Smckusick (void) put(2, O_LINO, line); 1985654Slinton 1995654Slinton /* 2005654Slinton * put out line number information for pdx 2015654Slinton */ 2025654Slinton lineno(line); 2035654Slinton 204773Speter # endif OBJ 205773Speter # ifdef PC 206773Speter static lastline; 207773Speter 208773Speter if ( line != lastline ) { 209773Speter stabline( line ); 210773Speter lastline = line; 211773Speter } 212773Speter if ( opt( 'p' ) ) { 213773Speter if ( opt('t') ) { 21418470Sralph putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 215773Speter , "_LINO" ); 21618470Sralph putop( PCCOM_UNARY PCC_CALL , PCCT_INT ); 217773Speter putdot( filename , line ); 218773Speter } else { 21918470Sralph putRV( STMTCOUNT , 0 , 0 , NGLOBAL , PCCT_INT ); 22018470Sralph putleaf( PCC_ICON , 1 , 0 , PCCT_INT , (char *) 0 ); 22118470Sralph putop( PCCOM_ASG PCC_PLUS , PCCT_INT ); 222773Speter putdot( filename , line ); 223773Speter } 224773Speter } 225773Speter # endif PC 226773Speter } 227773Speter 228773Speter /* 229773Speter * With varlist do stat 230773Speter * 231773Speter * With statement requires an extra word 232773Speter * in automatic storage for each level of withing. 233773Speter * These indirect pointers are initialized here, and 234773Speter * the scoping effect of the with statement occurs 235773Speter * because lookup examines the field names of the records 236773Speter * associated with the WITHPTRs on the withlist. 237773Speter */ 238773Speter withop(s) 23915941Smckusick WITH_NODE *s; 240773Speter { 24115941Smckusick register struct tnode *p; 242773Speter register struct nl *r; 2433835Speter struct nl *tempnlp; 24415941Smckusick struct nl *swl; 245773Speter 246773Speter putline(); 247773Speter swl = withlist; 24815941Smckusick for (p = s->var_list; p != TR_NIL; p = p->list_node.next) { 24915951Smckusick tempnlp = tmpalloc((long) (sizeof(int *)), nl+TPTR, REGOK); 25015951Smckusick /* 25115951Smckusick * no one uses the allocated temporary namelist entry, 25215951Smckusick * since we have to use it before we know its type; 25315951Smckusick * but we use its runtime location for the with pointer. 25415951Smckusick */ 255773Speter # ifdef OBJ 25615941Smckusick (void) put(2, O_LV | cbn <<8+INDX, tempnlp -> value[ NL_OFFS ] ); 257773Speter # endif OBJ 258773Speter # ifdef PC 25915941Smckusick putRV( (char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] , 26018470Sralph tempnlp -> extra_flags , PCCTM_PTR|PCCT_STRTY ); 261773Speter # endif PC 26215941Smckusick r = lvalue(p->list_node.list, MOD , LREQ ); 26315941Smckusick if (r == NLNIL) 264773Speter continue; 265773Speter if (r->class != RECORD) { 266773Speter error("Variable in with statement refers to %s, not to a record", nameof(r)); 267773Speter continue; 268773Speter } 26915941Smckusick r = defnl((char *) 0, WITHPTR, r, tempnlp -> value[ NL_OFFS ] ); 2703835Speter # ifdef PC 2713835Speter r -> extra_flags |= tempnlp -> extra_flags; 2723835Speter # endif PC 273773Speter r->nl_next = withlist; 274773Speter withlist = r; 275773Speter # ifdef OBJ 27615941Smckusick (void) put(1, PTR_AS); 277773Speter # endif OBJ 278773Speter # ifdef PC 27918470Sralph putop( PCC_ASSIGN , PCCTM_PTR|PCCT_STRTY ); 280773Speter putdot( filename , line ); 281773Speter # endif PC 282773Speter } 28315941Smckusick statement(s->stmnt); 284773Speter withlist = swl; 285773Speter } 286773Speter 287773Speter extern flagwas; 288773Speter /* 289773Speter * var := expr 290773Speter */ 291773Speter asgnop(r) 29215941Smckusick ASG_NODE *r; 293773Speter { 294773Speter register struct nl *p; 29515941Smckusick register struct tnode *av; 296773Speter 297773Speter /* 298773Speter * Asgnop's only function is 299773Speter * to handle function variable 300773Speter * assignments. All other assignment 301773Speter * stuff is handled by asgnop1. 302773Speter * the if below checks for unqualified lefthandside: 303773Speter * necessary for fvars. 304773Speter */ 30515941Smckusick av = r->lhs_var; 30615941Smckusick if (av != TR_NIL && av->tag == T_VAR && av->var_node.qual == TR_NIL) { 30715941Smckusick p = lookup1(av->var_node.cptr); 30815941Smckusick if (p != NLNIL) 309773Speter p->nl_flags = flagwas; 31015941Smckusick if (p != NLNIL && p->class == FVAR) { 311773Speter /* 312773Speter * Give asgnop1 the func 313773Speter * which is the chain of 314773Speter * the FVAR. 315773Speter */ 316773Speter p->nl_flags |= NUSED|NMOD; 317773Speter p = p->chain; 31815941Smckusick if (p == NLNIL) { 31915941Smckusick p = rvalue(r->rhs_expr, NLNIL , RREQ ); 320773Speter return; 321773Speter } 322773Speter # ifdef OBJ 32315941Smckusick (void) put(2, O_LV | bn << 8+INDX, (int)p->value[NL_OFFS]); 324773Speter if (isa(p->type, "i") && width(p->type) == 1) 32515941Smckusick (void) asgnop1(r, nl+T2INT); 326773Speter else 32715941Smckusick (void) asgnop1(r, p->type); 328773Speter # endif OBJ 329773Speter # ifdef PC 330773Speter /* 331773Speter * this should be the lvalue of the fvar, 332773Speter * but since the second pass knows to use 333773Speter * the address of the left operand of an 334773Speter * assignment, what i want here is an rvalue. 335773Speter * see note in funchdr about fvar allocation. 336773Speter */ 337773Speter p = p -> ptr[ NL_FVAR ]; 3383835Speter putRV( p -> symbol , bn , p -> value[ NL_OFFS ] , 3393835Speter p -> extra_flags , p2type( p -> type ) ); 34015941Smckusick (void) asgnop1( r , p -> type ); 341773Speter # endif PC 342773Speter return; 343773Speter } 344773Speter } 34515941Smckusick (void) asgnop1(r, NLNIL); 346773Speter } 347773Speter 348773Speter /* 349773Speter * Asgnop1 handles all assignments. 350773Speter * If p is not nil then we are assigning 351773Speter * to a function variable, otherwise 352773Speter * we look the variable up ourselves. 353773Speter */ 354773Speter struct nl * 355773Speter asgnop1(r, p) 35615941Smckusick ASG_NODE *r; 357773Speter register struct nl *p; 358773Speter { 359773Speter register struct nl *p1; 36015985Saoki int clas; 36115941Smckusick #ifdef OBJ 3623079Smckusic int w; 36315985Saoki #endif OBJ 364773Speter 36515985Saoki #ifdef OBJ 36615941Smckusick if (p == NLNIL) { 36715985Saoki p = lvalue(r->lhs_var, MOD|ASGN|NOUSE , LREQ ); 36815941Smckusick if ( p == NLNIL ) { 36915941Smckusick (void) rvalue( r->rhs_expr , NLNIL , RREQ ); 37015941Smckusick return NLNIL; 371773Speter } 37215985Saoki w = width(p); 37315985Saoki } else { 3743079Smckusic /* 3753079Smckusic * assigning to the return value, which is at least 3763079Smckusic * of width two since it resides on the stack 3773079Smckusic */ 37815985Saoki w = width(p); 37915985Saoki if (w < 2) 38015985Saoki w = 2; 38115985Saoki } 38215985Saoki clas = classify(p); 38315985Saoki if ((clas == TARY || clas == TSTR) && p->chain->class == CRANGE) { 38415985Saoki p1 = lvalue(r->rhs_expr, p , LREQ ); /* SHOULD THIS BE rvalue? */ 38515985Saoki } else { 38615985Saoki p1 = rvalue(r->rhs_expr, p , RREQ ); 38715985Saoki } 38815985Saoki # endif OBJ 38915985Saoki # ifdef PC 39015985Saoki if (p == NLNIL) { 39115985Saoki /* check for conformant array type */ 39215985Saoki codeoff(); 39315985Saoki p = rvalue(r->lhs_var, MOD|ASGN|NOUSE, LREQ); 39415985Saoki codeon(); 39515985Saoki if (p == NLNIL) { 39615985Saoki (void) rvalue(r->rhs_expr, NLNIL, RREQ); 39715985Saoki return NLNIL; 3983079Smckusic } 39915985Saoki clas = classify(p); 40015985Saoki if ((clas == TARY || clas == TSTR) && p->chain->class == CRANGE) { 40115985Saoki return pcasgconf(r, p); 40215970Smckusick } else { 403773Speter /* 40415985Saoki * since the second pass knows that it should reference 40515985Saoki * the lefthandside of asignments, what i need here is 40615985Saoki * an rvalue. 407773Speter */ 40815985Saoki p = lvalue( r->lhs_var , MOD|ASGN|NOUSE , RREQ ); 409773Speter } 41015985Saoki if ( p == NLNIL ) { 41115985Saoki (void) rvalue( r->rhs_expr , NLNIL , RREQ ); 41215985Saoki return NLNIL; 41315985Saoki } 41415985Saoki } 41515985Saoki /* 41615985Saoki * if this is a scalar assignment, 41715985Saoki * then i want to rvalue the righthandside. 41815985Saoki * if this is a structure assignment, 41915985Saoki * then i want an lvalue to the righthandside. 42015985Saoki * that's what the intermediate form sez. 42115985Saoki */ 42215985Saoki switch ( classify( p ) ) { 42315985Saoki case TINT: 42415985Saoki case TCHAR: 42515985Saoki case TBOOL: 42615985Saoki case TSCAL: 42715985Saoki precheck( p , "_RANG4" , "_RSNG4" ); 42815985Saoki /* and fall through */ 42915985Saoki case TDOUBLE: 43015985Saoki case TPTR: 43115985Saoki p1 = rvalue( r->rhs_expr , p , RREQ ); 43215985Saoki break; 43315985Saoki default: 43415985Saoki p1 = rvalue( r->rhs_expr , p , LREQ ); 43515985Saoki break; 43615985Saoki } 437773Speter # endif PC 43815941Smckusick if (p1 == NLNIL) 43915941Smckusick return (NLNIL); 44015941Smckusick if (incompat(p1, p, r->rhs_expr)) { 441773Speter cerror("Type of expression clashed with type of variable in assignment"); 44215941Smckusick return (NLNIL); 443773Speter } 4448758Speter # ifdef OBJ 4458758Speter switch (classify(p)) { 4468758Speter case TINT: 4478758Speter case TBOOL: 4488758Speter case TCHAR: 4498758Speter case TSCAL: 450773Speter rangechk(p, p1); 45115941Smckusick (void) gen(O_AS2, O_AS2, w, width(p1)); 4528758Speter break; 4538758Speter case TDOUBLE: 4548758Speter case TPTR: 45515941Smckusick (void) gen(O_AS2, O_AS2, w, width(p1)); 4568758Speter break; 45715970Smckusick case TARY: 45815970Smckusick case TSTR: 45915970Smckusick if (p->chain->class == CRANGE) { 46015970Smckusick /* conformant array assignment */ 46115970Smckusick p1 = p->chain; 46215970Smckusick w = width(p1->type); 46315970Smckusick putcbnds(p1, 1); 46415970Smckusick putcbnds(p1, 0); 46515970Smckusick gen(NIL, T_SUB, w, w); 46615970Smckusick put(2, w > 2? O_CON24: O_CON2, 1); 46715970Smckusick gen(NIL, T_ADD, w, w); 46815970Smckusick putcbnds(p1, 2); 46915970Smckusick gen(NIL, T_MULT, w, w); 47015970Smckusick put(1, O_VAS); 47115970Smckusick break; 47215970Smckusick } 47315970Smckusick /* else fall through */ 4748758Speter default: 47515941Smckusick (void) put(2, O_AS, w); 4768758Speter break; 4778758Speter } 4788758Speter # endif OBJ 4798758Speter # ifdef PC 4808758Speter switch (classify(p)) { 4818758Speter case TINT: 4828758Speter case TBOOL: 4838758Speter case TCHAR: 4848758Speter case TSCAL: 48510362Smckusick postcheck(p, p1); 48610362Smckusick sconv(p2type(p1), p2type(p)); 48718470Sralph putop( PCC_ASSIGN , p2type( p ) ); 488773Speter putdot( filename , line ); 4898758Speter break; 4908758Speter case TPTR: 49118470Sralph putop( PCC_ASSIGN , p2type( p ) ); 4928758Speter putdot( filename , line ); 4938758Speter break; 4948758Speter case TDOUBLE: 49510362Smckusick sconv(p2type(p1), p2type(p)); 49618470Sralph putop( PCC_ASSIGN , p2type( p ) ); 4978758Speter putdot( filename , line ); 4988758Speter break; 4998758Speter default: 50018470Sralph putstrop(PCC_STASG, PCCM_ADDTYPE(p2type(p), PCCTM_PTR), 50115941Smckusick (int) lwidth(p), align(p)); 502773Speter putdot( filename , line ); 5038758Speter break; 5048758Speter } 5058758Speter # endif PC 506773Speter return (p); /* Used by for statement */ 507773Speter } 508773Speter 50915985Saoki #ifdef PC 510773Speter /* 51115985Saoki * assignment to conformant arrays. Since these are variable length, 51215985Saoki * we use blkcpy() to perform the assignment. 51315985Saoki * blkcpy(rhs, lhs, (upper - lower + 1) * width) 51415985Saoki */ 51515985Saoki struct nl * 51615985Saoki pcasgconf(r, p) 51715985Saoki register ASG_NODE *r; 51815985Saoki struct nl *p; 51915985Saoki { 52015985Saoki struct nl *p1; 52115985Saoki 52215985Saoki if (r == (ASG_NODE *) TR_NIL || p == NLNIL) 52315985Saoki return NLNIL; 52418470Sralph putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR) , "_blkcpy" ); 52515985Saoki p1 = rvalue( r->rhs_expr , p , LREQ ); 52615985Saoki if (p1 == NLNIL) 52715985Saoki return NLNIL; 52815985Saoki p = lvalue( r->lhs_var , MOD|ASGN|NOUSE , LREQ ); 52915985Saoki if (p == NLNIL) 53015985Saoki return NLNIL; 53118470Sralph putop(PCC_CM, PCCT_INT); 53215985Saoki /* upper bound */ 53315985Saoki p1 = p->chain->nptr[1]; 53415985Saoki putRV(p1->symbol, (p1->nl_block & 037), p1->value[0], 53515985Saoki p1->extra_flags, p2type( p1 ) ); 53615985Saoki /* minus lower bound */ 53715985Saoki p1 = p->chain->nptr[0]; 53815985Saoki putRV(p1->symbol, (p1->nl_block & 037), p1->value[0], 53915985Saoki p1->extra_flags, p2type( p1 ) ); 54018470Sralph putop( PCC_MINUS, PCCT_INT ); 54115985Saoki /* add one */ 54218470Sralph putleaf(PCC_ICON, 1, 0, PCCT_INT, 0); 54318470Sralph putop( PCC_PLUS, PCCT_INT ); 54415985Saoki /* and multiply by the width */ 54515985Saoki p1 = p->chain->nptr[2]; 54615985Saoki putRV(p1->symbol, (p1->nl_block & 037), p1->value[0], 54715985Saoki p1->extra_flags, p2type( p1 ) ); 54818470Sralph putop( PCC_MUL , PCCT_INT ); 54918470Sralph putop(PCC_CM, PCCT_INT); 55018470Sralph putop(PCC_CALL, PCCT_INT); 55115985Saoki putdot( filename , line); 55215985Saoki return p; 55315985Saoki } 55415985Saoki #endif PC 55515985Saoki 55615985Saoki /* 557773Speter * if expr then stat [ else stat ] 558773Speter */ 55915941Smckusick ifop(if_n) 56015941Smckusick IF_NODE *if_n; 561773Speter { 562773Speter register struct nl *p; 563773Speter register l1, l2; /* l1 is start of else, l2 is end of else */ 5643079Smckusic int goc; 5653079Smckusic bool nr; 566773Speter 567773Speter goc = gocnt; 568773Speter putline(); 56915941Smckusick p = rvalue(if_n->cond_expr, NLNIL , RREQ ); 570773Speter if (p == NIL) { 57115941Smckusick statement(if_n->then_stmnt); 57215941Smckusick noreach = FALSE; 57315941Smckusick statement(if_n->else_stmnt); 57415941Smckusick noreach = FALSE; 575773Speter return; 576773Speter } 577773Speter if (isnta(p, "b")) { 578773Speter error("Type of expression in if statement must be Boolean, not %s", nameof(p)); 57915941Smckusick statement(if_n->then_stmnt); 58015941Smckusick noreach = FALSE; 58115941Smckusick statement(if_n->else_stmnt); 58215941Smckusick noreach = FALSE; 583773Speter return; 584773Speter } 585773Speter # ifdef OBJ 5863079Smckusic l1 = put(2, O_IF, getlab()); 587773Speter # endif OBJ 588773Speter # ifdef PC 58915941Smckusick l1 = (int) getlab(); 59018470Sralph putleaf( PCC_ICON , l1 , 0 , PCCT_INT , (char *) 0 ); 59118470Sralph putop( PCC_CBRANCH , PCCT_INT ); 592773Speter putdot( filename , line ); 593773Speter # endif PC 594773Speter putcnt(); 59515941Smckusick statement(if_n->then_stmnt); 596773Speter nr = noreach; 59715941Smckusick if (if_n->else_stmnt != TR_NIL) { 598773Speter /* 599773Speter * else stat 600773Speter */ 601773Speter --level; 602773Speter ungoto(); 603773Speter ++level; 604773Speter # ifdef OBJ 6053079Smckusic l2 = put(2, O_TRA, getlab()); 606773Speter # endif OBJ 607773Speter # ifdef PC 60815941Smckusick l2 = (int) getlab(); 60915941Smckusick putjbr( (long) l2 ); 610773Speter # endif PC 61115941Smckusick patch((PTR_DCL)l1); 61215941Smckusick noreach = FALSE; 61315941Smckusick statement(if_n->else_stmnt); 61415941Smckusick noreach = (noreach && nr)?TRUE:FALSE; 615773Speter l1 = l2; 616773Speter } else 61715941Smckusick noreach = FALSE; 61815941Smckusick patch((PTR_DCL)l1); 619773Speter if (goc != gocnt) 620773Speter putcnt(); 621773Speter } 622773Speter 623773Speter /* 624773Speter * while expr do stat 625773Speter */ 62615941Smckusick whilop(w_node) 62715941Smckusick WHI_CAS *w_node; 628773Speter { 629773Speter register struct nl *p; 63015941Smckusick register char *l1, *l2; 631773Speter int goc; 632773Speter 633773Speter goc = gocnt; 63415941Smckusick l1 = getlab(); 63515941Smckusick (void) putlab(l1); 636773Speter putline(); 63715941Smckusick p = rvalue(w_node->expr, NLNIL , RREQ ); 63815941Smckusick if (p == NLNIL) { 63915941Smckusick statement(w_node->stmnt_list); 64015941Smckusick noreach = FALSE; 641773Speter return; 642773Speter } 643773Speter if (isnta(p, "b")) { 644773Speter error("Type of expression in while statement must be Boolean, not %s", nameof(p)); 64515941Smckusick statement(w_node->stmnt_list); 64615941Smckusick noreach = FALSE; 647773Speter return; 648773Speter } 649773Speter l2 = getlab(); 650773Speter # ifdef OBJ 65115941Smckusick (void) put(2, O_IF, l2); 652773Speter # endif OBJ 653773Speter # ifdef PC 65418470Sralph putleaf( PCC_ICON , (int) l2 , 0 , PCCT_INT , (char *) 0 ); 65518470Sralph putop( PCC_CBRANCH , PCCT_INT ); 656773Speter putdot( filename , line ); 657773Speter # endif PC 658773Speter putcnt(); 65915941Smckusick statement(w_node->stmnt_list); 660773Speter # ifdef OBJ 66115941Smckusick (void) put(2, O_TRA, l1); 662773Speter # endif OBJ 663773Speter # ifdef PC 66415941Smckusick putjbr( (long) l1 ); 665773Speter # endif PC 66615941Smckusick patch((PTR_DCL) l2); 667773Speter if (goc != gocnt) 668773Speter putcnt(); 669773Speter } 670773Speter 671773Speter /* 672773Speter * repeat stat* until expr 673773Speter */ 674773Speter repop(r) 67515941Smckusick REPEAT *r; 676773Speter { 677773Speter register struct nl *p; 678773Speter register l; 679773Speter int goc; 680773Speter 681773Speter goc = gocnt; 68215941Smckusick l = (int) putlab(getlab()); 683773Speter putcnt(); 68415941Smckusick statlist(r->stmnt_list); 68515941Smckusick line = r->line_no; 68615941Smckusick p = rvalue(r->term_expr, NLNIL , RREQ ); 68715941Smckusick if (p == NLNIL) 688773Speter return; 689773Speter if (isnta(p,"b")) { 690773Speter error("Until expression type must be Boolean, not %s, in repeat statement", nameof(p)); 691773Speter return; 692773Speter } 693773Speter # ifdef OBJ 69415941Smckusick (void) put(2, O_IF, l); 695773Speter # endif OBJ 696773Speter # ifdef PC 69718470Sralph putleaf( PCC_ICON , l , 0 , PCCT_INT , (char *) 0 ); 69818470Sralph putop( PCC_CBRANCH , PCCT_INT ); 699773Speter putdot( filename , line ); 700773Speter # endif PC 701773Speter if (goc != gocnt) 702773Speter putcnt(); 703773Speter } 704