1*22192Sdist /* 2*22192Sdist * Copyright (c) 1980 Regents of the University of California. 3*22192Sdist * All rights reserved. The Berkeley software License Agreement 4*22192Sdist * specifies the terms and conditions for redistribution. 5*22192Sdist */ 6773Speter 715941Smckusick #ifndef lint 8*22192Sdist static char sccsid[] = "@(#)stat.c 5.1 (Berkeley) 06/05/85"; 9*22192Sdist #endif not lint 10773Speter 11773Speter #include "whoami.h" 12773Speter #include "0.h" 13773Speter #include "tree.h" 14773Speter #include "objfmt.h" 15773Speter #ifdef PC 1618470Sralph # include <pcc.h> 17773Speter # include "pc.h" 18773Speter #endif PC 1911330Speter #include "tmps.h" 20773Speter 21773Speter int cntstat; 22773Speter short cnts = 3; 23773Speter #include "opcode.h" 2415941Smckusick #include "tree_ty.h" 25773Speter 26773Speter /* 27773Speter * Statement list 28773Speter */ 29773Speter statlist(r) 3015941Smckusick struct tnode *r; 31773Speter { 3215941Smckusick register struct tnode *sl; 33773Speter 3415941Smckusick for (sl=r; sl != TR_NIL; sl=sl->list_node.next) 3515941Smckusick statement(sl->list_node.list); 36773Speter } 37773Speter 38773Speter /* 39773Speter * Statement 40773Speter */ 41773Speter statement(r) 4215941Smckusick struct tnode *r; 43773Speter { 4415941Smckusick register struct tnode *tree_node; 45773Speter register struct nl *snlp; 463228Smckusic struct tmps soffset; 47773Speter 4815941Smckusick tree_node = r; 49773Speter snlp = nlp; 503228Smckusic soffset = sizes[cbn].curtmps; 51773Speter top: 52773Speter if (cntstat) { 53773Speter cntstat = 0; 54773Speter putcnt(); 55773Speter } 5615941Smckusick if (tree_node == TR_NIL) 57773Speter return; 5815941Smckusick line = tree_node->lined.line_no; 5915941Smckusick if (tree_node->tag == T_LABEL) { 6015941Smckusick labeled(tree_node->label_node.lbl_ptr); 6115941Smckusick tree_node = tree_node->label_node.stmnt; 6215941Smckusick noreach = FALSE; 63773Speter cntstat = 1; 64773Speter goto top; 65773Speter } 66773Speter if (noreach) { 6715941Smckusick noreach = FALSE; 68773Speter warning(); 69773Speter error("Unreachable statement"); 70773Speter } 7115941Smckusick switch (tree_node->tag) { 72773Speter case T_PCALL: 73773Speter putline(); 74773Speter # ifdef OBJ 7515941Smckusick proc(tree_node); 76773Speter # endif OBJ 77773Speter # ifdef PC 7815941Smckusick pcproc( tree_node ); 79773Speter # endif PC 80773Speter break; 81773Speter case T_ASGN: 82773Speter putline(); 8315941Smckusick asgnop(&(tree_node->asg_node)); 84773Speter break; 85773Speter case T_GOTO: 86773Speter putline(); 8715941Smckusick gotoop(tree_node->goto_node.lbl_ptr); 8815941Smckusick noreach = TRUE; 89773Speter cntstat = 1; 90773Speter break; 91773Speter default: 92773Speter level++; 9315941Smckusick switch (tree_node->tag) { 94773Speter default: 95773Speter panic("stat"); 96773Speter case T_IF: 97773Speter case T_IFEL: 9815941Smckusick ifop(&(tree_node->if_node)); 99773Speter break; 100773Speter case T_WHILE: 10115941Smckusick whilop(&(tree_node->whi_cas)); 10215941Smckusick noreach = FALSE; 103773Speter break; 104773Speter case T_REPEAT: 10515941Smckusick repop(&(tree_node->repeat)); 106773Speter break; 107773Speter case T_FORU: 108773Speter case T_FORD: 10915941Smckusick forop(tree_node); 11015941Smckusick noreach = FALSE; 111773Speter break; 112773Speter case T_BLOCK: 11315941Smckusick statlist(tree_node->stmnt_blck.stmnt_list); 114773Speter break; 115773Speter case T_CASE: 116773Speter putline(); 117773Speter # ifdef OBJ 11815941Smckusick caseop(&(tree_node->whi_cas)); 119773Speter # endif OBJ 120773Speter # ifdef PC 12115941Smckusick pccaseop(&(tree_node->whi_cas)); 122773Speter # endif PC 123773Speter break; 124773Speter case T_WITH: 12515941Smckusick withop(&(tree_node->with_node)); 126773Speter break; 127773Speter } 128773Speter --level; 129773Speter if (gotos[cbn]) 130773Speter ungoto(); 131773Speter break; 132773Speter } 133773Speter /* 134773Speter * Free the temporary name list entries defined in 135773Speter * expressions, e.g. STRs, and WITHPTRs from withs. 136773Speter */ 137773Speter nlfree(snlp); 138773Speter /* 139773Speter * free any temporaries allocated for this statement 140773Speter * these come from strings and sets. 141773Speter */ 1423228Smckusic tmpfree(&soffset); 143773Speter } 144773Speter 145773Speter ungoto() 146773Speter { 147773Speter register struct nl *p; 148773Speter 14915941Smckusick for (p = gotos[cbn]; p != NLNIL; p = p->chain) 150773Speter if ((p->nl_flags & NFORWD) != 0) { 151773Speter if (p->value[NL_GOLEV] != NOTYET) 152773Speter if (p->value[NL_GOLEV] > level) 153773Speter p->value[NL_GOLEV] = level; 154773Speter } else 155773Speter if (p->value[NL_GOLEV] != DEAD) 156773Speter if (p->value[NL_GOLEV] > level) 157773Speter p->value[NL_GOLEV] = DEAD; 158773Speter } 159773Speter 160773Speter putcnt() 161773Speter { 162773Speter 16315941Smckusick if (monflg == FALSE) { 164773Speter return; 165773Speter } 166773Speter inccnt( getcnt() ); 167773Speter } 168773Speter 169773Speter int 170773Speter getcnt() 171773Speter { 172773Speter 173773Speter return ++cnts; 174773Speter } 175773Speter 176773Speter inccnt( counter ) 177773Speter int counter; 178773Speter { 179773Speter 180773Speter # ifdef OBJ 18115941Smckusick (void) put(2, O_COUNT, counter ); 182773Speter # endif OBJ 183773Speter # ifdef PC 18418470Sralph putRV( PCPCOUNT , 0 , counter * sizeof (long) , NGLOBAL , PCCT_INT ); 18518470Sralph putleaf( PCC_ICON , 1 , 0 , PCCT_INT , (char *) 0 ); 18618470Sralph putop( PCCOM_ASG PCC_PLUS , PCCT_INT ); 187773Speter putdot( filename , line ); 188773Speter # endif PC 189773Speter } 190773Speter 191773Speter putline() 192773Speter { 193773Speter 194773Speter # ifdef OBJ 195773Speter if (opt('p') != 0) 19615941Smckusick (void) put(2, O_LINO, line); 1975654Slinton 1985654Slinton /* 1995654Slinton * put out line number information for pdx 2005654Slinton */ 2015654Slinton lineno(line); 2025654Slinton 203773Speter # endif OBJ 204773Speter # ifdef PC 205773Speter static lastline; 206773Speter 207773Speter if ( line != lastline ) { 208773Speter stabline( line ); 209773Speter lastline = line; 210773Speter } 211773Speter if ( opt( 'p' ) ) { 212773Speter if ( opt('t') ) { 21318470Sralph putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 214773Speter , "_LINO" ); 21518470Sralph putop( PCCOM_UNARY PCC_CALL , PCCT_INT ); 216773Speter putdot( filename , line ); 217773Speter } else { 21818470Sralph putRV( STMTCOUNT , 0 , 0 , NGLOBAL , PCCT_INT ); 21918470Sralph putleaf( PCC_ICON , 1 , 0 , PCCT_INT , (char *) 0 ); 22018470Sralph putop( PCCOM_ASG PCC_PLUS , PCCT_INT ); 221773Speter putdot( filename , line ); 222773Speter } 223773Speter } 224773Speter # endif PC 225773Speter } 226773Speter 227773Speter /* 228773Speter * With varlist do stat 229773Speter * 230773Speter * With statement requires an extra word 231773Speter * in automatic storage for each level of withing. 232773Speter * These indirect pointers are initialized here, and 233773Speter * the scoping effect of the with statement occurs 234773Speter * because lookup examines the field names of the records 235773Speter * associated with the WITHPTRs on the withlist. 236773Speter */ 237773Speter withop(s) 23815941Smckusick WITH_NODE *s; 239773Speter { 24015941Smckusick register struct tnode *p; 241773Speter register struct nl *r; 2423835Speter struct nl *tempnlp; 24315941Smckusick struct nl *swl; 244773Speter 245773Speter putline(); 246773Speter swl = withlist; 24715941Smckusick for (p = s->var_list; p != TR_NIL; p = p->list_node.next) { 24815951Smckusick tempnlp = tmpalloc((long) (sizeof(int *)), nl+TPTR, REGOK); 24915951Smckusick /* 25015951Smckusick * no one uses the allocated temporary namelist entry, 25115951Smckusick * since we have to use it before we know its type; 25215951Smckusick * but we use its runtime location for the with pointer. 25315951Smckusick */ 254773Speter # ifdef OBJ 25515941Smckusick (void) put(2, O_LV | cbn <<8+INDX, tempnlp -> value[ NL_OFFS ] ); 256773Speter # endif OBJ 257773Speter # ifdef PC 25815941Smckusick putRV( (char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] , 25918470Sralph tempnlp -> extra_flags , PCCTM_PTR|PCCT_STRTY ); 260773Speter # endif PC 26115941Smckusick r = lvalue(p->list_node.list, MOD , LREQ ); 26215941Smckusick if (r == NLNIL) 263773Speter continue; 264773Speter if (r->class != RECORD) { 265773Speter error("Variable in with statement refers to %s, not to a record", nameof(r)); 266773Speter continue; 267773Speter } 26815941Smckusick r = defnl((char *) 0, WITHPTR, r, tempnlp -> value[ NL_OFFS ] ); 2693835Speter # ifdef PC 2703835Speter r -> extra_flags |= tempnlp -> extra_flags; 2713835Speter # endif PC 272773Speter r->nl_next = withlist; 273773Speter withlist = r; 274773Speter # ifdef OBJ 27515941Smckusick (void) put(1, PTR_AS); 276773Speter # endif OBJ 277773Speter # ifdef PC 27818470Sralph putop( PCC_ASSIGN , PCCTM_PTR|PCCT_STRTY ); 279773Speter putdot( filename , line ); 280773Speter # endif PC 281773Speter } 28215941Smckusick statement(s->stmnt); 283773Speter withlist = swl; 284773Speter } 285773Speter 286773Speter extern flagwas; 287773Speter /* 288773Speter * var := expr 289773Speter */ 290773Speter asgnop(r) 29115941Smckusick ASG_NODE *r; 292773Speter { 293773Speter register struct nl *p; 29415941Smckusick register struct tnode *av; 295773Speter 296773Speter /* 297773Speter * Asgnop's only function is 298773Speter * to handle function variable 299773Speter * assignments. All other assignment 300773Speter * stuff is handled by asgnop1. 301773Speter * the if below checks for unqualified lefthandside: 302773Speter * necessary for fvars. 303773Speter */ 30415941Smckusick av = r->lhs_var; 30515941Smckusick if (av != TR_NIL && av->tag == T_VAR && av->var_node.qual == TR_NIL) { 30615941Smckusick p = lookup1(av->var_node.cptr); 30715941Smckusick if (p != NLNIL) 308773Speter p->nl_flags = flagwas; 30915941Smckusick if (p != NLNIL && p->class == FVAR) { 310773Speter /* 311773Speter * Give asgnop1 the func 312773Speter * which is the chain of 313773Speter * the FVAR. 314773Speter */ 315773Speter p->nl_flags |= NUSED|NMOD; 316773Speter p = p->chain; 31715941Smckusick if (p == NLNIL) { 31815941Smckusick p = rvalue(r->rhs_expr, NLNIL , RREQ ); 319773Speter return; 320773Speter } 321773Speter # ifdef OBJ 32215941Smckusick (void) put(2, O_LV | bn << 8+INDX, (int)p->value[NL_OFFS]); 323773Speter if (isa(p->type, "i") && width(p->type) == 1) 32415941Smckusick (void) asgnop1(r, nl+T2INT); 325773Speter else 32615941Smckusick (void) asgnop1(r, p->type); 327773Speter # endif OBJ 328773Speter # ifdef PC 329773Speter /* 330773Speter * this should be the lvalue of the fvar, 331773Speter * but since the second pass knows to use 332773Speter * the address of the left operand of an 333773Speter * assignment, what i want here is an rvalue. 334773Speter * see note in funchdr about fvar allocation. 335773Speter */ 336773Speter p = p -> ptr[ NL_FVAR ]; 3373835Speter putRV( p -> symbol , bn , p -> value[ NL_OFFS ] , 3383835Speter p -> extra_flags , p2type( p -> type ) ); 33915941Smckusick (void) asgnop1( r , p -> type ); 340773Speter # endif PC 341773Speter return; 342773Speter } 343773Speter } 34415941Smckusick (void) asgnop1(r, NLNIL); 345773Speter } 346773Speter 347773Speter /* 348773Speter * Asgnop1 handles all assignments. 349773Speter * If p is not nil then we are assigning 350773Speter * to a function variable, otherwise 351773Speter * we look the variable up ourselves. 352773Speter */ 353773Speter struct nl * 354773Speter asgnop1(r, p) 35515941Smckusick ASG_NODE *r; 356773Speter register struct nl *p; 357773Speter { 358773Speter register struct nl *p1; 35915985Saoki int clas; 36015941Smckusick #ifdef OBJ 3613079Smckusic int w; 36215985Saoki #endif OBJ 363773Speter 36415985Saoki #ifdef OBJ 36515941Smckusick if (p == NLNIL) { 36615985Saoki p = lvalue(r->lhs_var, MOD|ASGN|NOUSE , LREQ ); 36715941Smckusick if ( p == NLNIL ) { 36815941Smckusick (void) rvalue( r->rhs_expr , NLNIL , RREQ ); 36915941Smckusick return NLNIL; 370773Speter } 37115985Saoki w = width(p); 37215985Saoki } else { 3733079Smckusic /* 3743079Smckusic * assigning to the return value, which is at least 3753079Smckusic * of width two since it resides on the stack 3763079Smckusic */ 37715985Saoki w = width(p); 37815985Saoki if (w < 2) 37915985Saoki w = 2; 38015985Saoki } 38115985Saoki clas = classify(p); 38215985Saoki if ((clas == TARY || clas == TSTR) && p->chain->class == CRANGE) { 38315985Saoki p1 = lvalue(r->rhs_expr, p , LREQ ); /* SHOULD THIS BE rvalue? */ 38415985Saoki } else { 38515985Saoki p1 = rvalue(r->rhs_expr, p , RREQ ); 38615985Saoki } 38715985Saoki # endif OBJ 38815985Saoki # ifdef PC 38915985Saoki if (p == NLNIL) { 39015985Saoki /* check for conformant array type */ 39115985Saoki codeoff(); 39215985Saoki p = rvalue(r->lhs_var, MOD|ASGN|NOUSE, LREQ); 39315985Saoki codeon(); 39415985Saoki if (p == NLNIL) { 39515985Saoki (void) rvalue(r->rhs_expr, NLNIL, RREQ); 39615985Saoki return NLNIL; 3973079Smckusic } 39815985Saoki clas = classify(p); 39915985Saoki if ((clas == TARY || clas == TSTR) && p->chain->class == CRANGE) { 40015985Saoki return pcasgconf(r, p); 40115970Smckusick } else { 402773Speter /* 40315985Saoki * since the second pass knows that it should reference 40415985Saoki * the lefthandside of asignments, what i need here is 40515985Saoki * an rvalue. 406773Speter */ 40715985Saoki p = lvalue( r->lhs_var , MOD|ASGN|NOUSE , RREQ ); 408773Speter } 40915985Saoki if ( p == NLNIL ) { 41015985Saoki (void) rvalue( r->rhs_expr , NLNIL , RREQ ); 41115985Saoki return NLNIL; 41215985Saoki } 41315985Saoki } 41415985Saoki /* 41515985Saoki * if this is a scalar assignment, 41615985Saoki * then i want to rvalue the righthandside. 41715985Saoki * if this is a structure assignment, 41815985Saoki * then i want an lvalue to the righthandside. 41915985Saoki * that's what the intermediate form sez. 42015985Saoki */ 42115985Saoki switch ( classify( p ) ) { 42215985Saoki case TINT: 42315985Saoki case TCHAR: 42415985Saoki case TBOOL: 42515985Saoki case TSCAL: 42615985Saoki precheck( p , "_RANG4" , "_RSNG4" ); 42715985Saoki /* and fall through */ 42815985Saoki case TDOUBLE: 42915985Saoki case TPTR: 43015985Saoki p1 = rvalue( r->rhs_expr , p , RREQ ); 43115985Saoki break; 43215985Saoki default: 43315985Saoki p1 = rvalue( r->rhs_expr , p , LREQ ); 43415985Saoki break; 43515985Saoki } 436773Speter # endif PC 43715941Smckusick if (p1 == NLNIL) 43815941Smckusick return (NLNIL); 43915941Smckusick if (incompat(p1, p, r->rhs_expr)) { 440773Speter cerror("Type of expression clashed with type of variable in assignment"); 44115941Smckusick return (NLNIL); 442773Speter } 4438758Speter # ifdef OBJ 4448758Speter switch (classify(p)) { 4458758Speter case TINT: 4468758Speter case TBOOL: 4478758Speter case TCHAR: 4488758Speter case TSCAL: 449773Speter rangechk(p, p1); 45015941Smckusick (void) gen(O_AS2, O_AS2, w, width(p1)); 4518758Speter break; 4528758Speter case TDOUBLE: 4538758Speter case TPTR: 45415941Smckusick (void) gen(O_AS2, O_AS2, w, width(p1)); 4558758Speter break; 45615970Smckusick case TARY: 45715970Smckusick case TSTR: 45815970Smckusick if (p->chain->class == CRANGE) { 45915970Smckusick /* conformant array assignment */ 46015970Smckusick p1 = p->chain; 46115970Smckusick w = width(p1->type); 46215970Smckusick putcbnds(p1, 1); 46315970Smckusick putcbnds(p1, 0); 46415970Smckusick gen(NIL, T_SUB, w, w); 46515970Smckusick put(2, w > 2? O_CON24: O_CON2, 1); 46615970Smckusick gen(NIL, T_ADD, w, w); 46715970Smckusick putcbnds(p1, 2); 46815970Smckusick gen(NIL, T_MULT, w, w); 46915970Smckusick put(1, O_VAS); 47015970Smckusick break; 47115970Smckusick } 47215970Smckusick /* else fall through */ 4738758Speter default: 47415941Smckusick (void) put(2, O_AS, w); 4758758Speter break; 4768758Speter } 4778758Speter # endif OBJ 4788758Speter # ifdef PC 4798758Speter switch (classify(p)) { 4808758Speter case TINT: 4818758Speter case TBOOL: 4828758Speter case TCHAR: 4838758Speter case TSCAL: 48410362Smckusick postcheck(p, p1); 48510362Smckusick sconv(p2type(p1), p2type(p)); 48618470Sralph putop( PCC_ASSIGN , p2type( p ) ); 487773Speter putdot( filename , line ); 4888758Speter break; 4898758Speter case TPTR: 49018470Sralph putop( PCC_ASSIGN , p2type( p ) ); 4918758Speter putdot( filename , line ); 4928758Speter break; 4938758Speter case TDOUBLE: 49410362Smckusick sconv(p2type(p1), p2type(p)); 49518470Sralph putop( PCC_ASSIGN , p2type( p ) ); 4968758Speter putdot( filename , line ); 4978758Speter break; 4988758Speter default: 49918470Sralph putstrop(PCC_STASG, PCCM_ADDTYPE(p2type(p), PCCTM_PTR), 50015941Smckusick (int) lwidth(p), align(p)); 501773Speter putdot( filename , line ); 5028758Speter break; 5038758Speter } 5048758Speter # endif PC 505773Speter return (p); /* Used by for statement */ 506773Speter } 507773Speter 50815985Saoki #ifdef PC 509773Speter /* 51015985Saoki * assignment to conformant arrays. Since these are variable length, 51115985Saoki * we use blkcpy() to perform the assignment. 51215985Saoki * blkcpy(rhs, lhs, (upper - lower + 1) * width) 51315985Saoki */ 51415985Saoki struct nl * 51515985Saoki pcasgconf(r, p) 51615985Saoki register ASG_NODE *r; 51715985Saoki struct nl *p; 51815985Saoki { 51915985Saoki struct nl *p1; 52015985Saoki 52115985Saoki if (r == (ASG_NODE *) TR_NIL || p == NLNIL) 52215985Saoki return NLNIL; 52318470Sralph putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR) , "_blkcpy" ); 52415985Saoki p1 = rvalue( r->rhs_expr , p , LREQ ); 52515985Saoki if (p1 == NLNIL) 52615985Saoki return NLNIL; 52715985Saoki p = lvalue( r->lhs_var , MOD|ASGN|NOUSE , LREQ ); 52815985Saoki if (p == NLNIL) 52915985Saoki return NLNIL; 53018470Sralph putop(PCC_CM, PCCT_INT); 53115985Saoki /* upper bound */ 53215985Saoki p1 = p->chain->nptr[1]; 53315985Saoki putRV(p1->symbol, (p1->nl_block & 037), p1->value[0], 53415985Saoki p1->extra_flags, p2type( p1 ) ); 53515985Saoki /* minus lower bound */ 53615985Saoki p1 = p->chain->nptr[0]; 53715985Saoki putRV(p1->symbol, (p1->nl_block & 037), p1->value[0], 53815985Saoki p1->extra_flags, p2type( p1 ) ); 53918470Sralph putop( PCC_MINUS, PCCT_INT ); 54015985Saoki /* add one */ 54118470Sralph putleaf(PCC_ICON, 1, 0, PCCT_INT, 0); 54218470Sralph putop( PCC_PLUS, PCCT_INT ); 54315985Saoki /* and multiply by the width */ 54415985Saoki p1 = p->chain->nptr[2]; 54515985Saoki putRV(p1->symbol, (p1->nl_block & 037), p1->value[0], 54615985Saoki p1->extra_flags, p2type( p1 ) ); 54718470Sralph putop( PCC_MUL , PCCT_INT ); 54818470Sralph putop(PCC_CM, PCCT_INT); 54918470Sralph putop(PCC_CALL, PCCT_INT); 55015985Saoki putdot( filename , line); 55115985Saoki return p; 55215985Saoki } 55315985Saoki #endif PC 55415985Saoki 55515985Saoki /* 556773Speter * if expr then stat [ else stat ] 557773Speter */ 55815941Smckusick ifop(if_n) 55915941Smckusick IF_NODE *if_n; 560773Speter { 561773Speter register struct nl *p; 562773Speter register l1, l2; /* l1 is start of else, l2 is end of else */ 5633079Smckusic int goc; 5643079Smckusic bool nr; 565773Speter 566773Speter goc = gocnt; 567773Speter putline(); 56815941Smckusick p = rvalue(if_n->cond_expr, NLNIL , RREQ ); 569773Speter if (p == NIL) { 57015941Smckusick statement(if_n->then_stmnt); 57115941Smckusick noreach = FALSE; 57215941Smckusick statement(if_n->else_stmnt); 57315941Smckusick noreach = FALSE; 574773Speter return; 575773Speter } 576773Speter if (isnta(p, "b")) { 577773Speter error("Type of expression in if statement must be Boolean, not %s", nameof(p)); 57815941Smckusick statement(if_n->then_stmnt); 57915941Smckusick noreach = FALSE; 58015941Smckusick statement(if_n->else_stmnt); 58115941Smckusick noreach = FALSE; 582773Speter return; 583773Speter } 584773Speter # ifdef OBJ 5853079Smckusic l1 = put(2, O_IF, getlab()); 586773Speter # endif OBJ 587773Speter # ifdef PC 58815941Smckusick l1 = (int) getlab(); 58918470Sralph putleaf( PCC_ICON , l1 , 0 , PCCT_INT , (char *) 0 ); 59018470Sralph putop( PCC_CBRANCH , PCCT_INT ); 591773Speter putdot( filename , line ); 592773Speter # endif PC 593773Speter putcnt(); 59415941Smckusick statement(if_n->then_stmnt); 595773Speter nr = noreach; 59615941Smckusick if (if_n->else_stmnt != TR_NIL) { 597773Speter /* 598773Speter * else stat 599773Speter */ 600773Speter --level; 601773Speter ungoto(); 602773Speter ++level; 603773Speter # ifdef OBJ 6043079Smckusic l2 = put(2, O_TRA, getlab()); 605773Speter # endif OBJ 606773Speter # ifdef PC 60715941Smckusick l2 = (int) getlab(); 60815941Smckusick putjbr( (long) l2 ); 609773Speter # endif PC 61015941Smckusick patch((PTR_DCL)l1); 61115941Smckusick noreach = FALSE; 61215941Smckusick statement(if_n->else_stmnt); 61315941Smckusick noreach = (noreach && nr)?TRUE:FALSE; 614773Speter l1 = l2; 615773Speter } else 61615941Smckusick noreach = FALSE; 61715941Smckusick patch((PTR_DCL)l1); 618773Speter if (goc != gocnt) 619773Speter putcnt(); 620773Speter } 621773Speter 622773Speter /* 623773Speter * while expr do stat 624773Speter */ 62515941Smckusick whilop(w_node) 62615941Smckusick WHI_CAS *w_node; 627773Speter { 628773Speter register struct nl *p; 62915941Smckusick register char *l1, *l2; 630773Speter int goc; 631773Speter 632773Speter goc = gocnt; 63315941Smckusick l1 = getlab(); 63415941Smckusick (void) putlab(l1); 635773Speter putline(); 63615941Smckusick p = rvalue(w_node->expr, NLNIL , RREQ ); 63715941Smckusick if (p == NLNIL) { 63815941Smckusick statement(w_node->stmnt_list); 63915941Smckusick noreach = FALSE; 640773Speter return; 641773Speter } 642773Speter if (isnta(p, "b")) { 643773Speter error("Type of expression in while statement must be Boolean, not %s", nameof(p)); 64415941Smckusick statement(w_node->stmnt_list); 64515941Smckusick noreach = FALSE; 646773Speter return; 647773Speter } 648773Speter l2 = getlab(); 649773Speter # ifdef OBJ 65015941Smckusick (void) put(2, O_IF, l2); 651773Speter # endif OBJ 652773Speter # ifdef PC 65318470Sralph putleaf( PCC_ICON , (int) l2 , 0 , PCCT_INT , (char *) 0 ); 65418470Sralph putop( PCC_CBRANCH , PCCT_INT ); 655773Speter putdot( filename , line ); 656773Speter # endif PC 657773Speter putcnt(); 65815941Smckusick statement(w_node->stmnt_list); 659773Speter # ifdef OBJ 66015941Smckusick (void) put(2, O_TRA, l1); 661773Speter # endif OBJ 662773Speter # ifdef PC 66315941Smckusick putjbr( (long) l1 ); 664773Speter # endif PC 66515941Smckusick patch((PTR_DCL) l2); 666773Speter if (goc != gocnt) 667773Speter putcnt(); 668773Speter } 669773Speter 670773Speter /* 671773Speter * repeat stat* until expr 672773Speter */ 673773Speter repop(r) 67415941Smckusick REPEAT *r; 675773Speter { 676773Speter register struct nl *p; 677773Speter register l; 678773Speter int goc; 679773Speter 680773Speter goc = gocnt; 68115941Smckusick l = (int) putlab(getlab()); 682773Speter putcnt(); 68315941Smckusick statlist(r->stmnt_list); 68415941Smckusick line = r->line_no; 68515941Smckusick p = rvalue(r->term_expr, NLNIL , RREQ ); 68615941Smckusick if (p == NLNIL) 687773Speter return; 688773Speter if (isnta(p,"b")) { 689773Speter error("Until expression type must be Boolean, not %s, in repeat statement", nameof(p)); 690773Speter return; 691773Speter } 692773Speter # ifdef OBJ 69315941Smckusick (void) put(2, O_IF, l); 694773Speter # endif OBJ 695773Speter # ifdef PC 69618470Sralph putleaf( PCC_ICON , l , 0 , PCCT_INT , (char *) 0 ); 69718470Sralph putop( PCC_CBRANCH , PCCT_INT ); 698773Speter putdot( filename , line ); 699773Speter # endif PC 700773Speter if (goc != gocnt) 701773Speter putcnt(); 702773Speter } 703