1*773Speter /* Copyright (c) 1979 Regents of the University of California */ 2*773Speter 3*773Speter static char sccsid[] = "@(#)stat.c 1.1 08/27/80"; 4*773Speter 5*773Speter #include "whoami.h" 6*773Speter #include "0.h" 7*773Speter #include "tree.h" 8*773Speter #include "objfmt.h" 9*773Speter #ifdef PC 10*773Speter # include "pcops.h" 11*773Speter # include "pc.h" 12*773Speter #endif PC 13*773Speter 14*773Speter int cntstat; 15*773Speter short cnts = 3; 16*773Speter #include "opcode.h" 17*773Speter 18*773Speter /* 19*773Speter * Statement list 20*773Speter */ 21*773Speter statlist(r) 22*773Speter int *r; 23*773Speter { 24*773Speter register *sl; 25*773Speter 26*773Speter for (sl=r; sl != NIL; sl=sl[2]) 27*773Speter statement(sl[1]); 28*773Speter } 29*773Speter 30*773Speter /* 31*773Speter * Statement 32*773Speter */ 33*773Speter statement(r) 34*773Speter int *r; 35*773Speter { 36*773Speter register *s; 37*773Speter register struct nl *snlp; 38*773Speter long soffset; 39*773Speter 40*773Speter s = r; 41*773Speter snlp = nlp; 42*773Speter soffset = sizes[ cbn ].om_off; 43*773Speter top: 44*773Speter if (cntstat) { 45*773Speter cntstat = 0; 46*773Speter putcnt(); 47*773Speter } 48*773Speter if (s == NIL) 49*773Speter return; 50*773Speter line = s[1]; 51*773Speter if (s[0] == T_LABEL) { 52*773Speter labeled(s[2]); 53*773Speter s = s[3]; 54*773Speter noreach = 0; 55*773Speter cntstat = 1; 56*773Speter goto top; 57*773Speter } 58*773Speter if (noreach) { 59*773Speter noreach = 0; 60*773Speter warning(); 61*773Speter error("Unreachable statement"); 62*773Speter } 63*773Speter switch (s[0]) { 64*773Speter case T_PCALL: 65*773Speter putline(); 66*773Speter # ifdef OBJ 67*773Speter proc(s); 68*773Speter # endif OBJ 69*773Speter # ifdef PC 70*773Speter pcproc( s ); 71*773Speter # endif PC 72*773Speter break; 73*773Speter case T_ASGN: 74*773Speter putline(); 75*773Speter asgnop(s); 76*773Speter break; 77*773Speter case T_GOTO: 78*773Speter putline(); 79*773Speter gotoop(s[2]); 80*773Speter noreach = 1; 81*773Speter cntstat = 1; 82*773Speter break; 83*773Speter default: 84*773Speter level++; 85*773Speter switch (s[0]) { 86*773Speter default: 87*773Speter panic("stat"); 88*773Speter case T_IF: 89*773Speter case T_IFEL: 90*773Speter ifop(s); 91*773Speter break; 92*773Speter case T_WHILE: 93*773Speter whilop(s); 94*773Speter noreach = 0; 95*773Speter break; 96*773Speter case T_REPEAT: 97*773Speter repop(s); 98*773Speter break; 99*773Speter case T_FORU: 100*773Speter case T_FORD: 101*773Speter # ifdef OBJ 102*773Speter forop(s); 103*773Speter # endif OBJ 104*773Speter # ifdef PC 105*773Speter pcforop( s ); 106*773Speter # endif PC 107*773Speter noreach = 0; 108*773Speter break; 109*773Speter case T_BLOCK: 110*773Speter statlist(s[2]); 111*773Speter break; 112*773Speter case T_CASE: 113*773Speter putline(); 114*773Speter # ifdef OBJ 115*773Speter caseop(s); 116*773Speter # endif OBJ 117*773Speter # ifdef PC 118*773Speter pccaseop( s ); 119*773Speter # endif PC 120*773Speter break; 121*773Speter case T_WITH: 122*773Speter withop(s); 123*773Speter break; 124*773Speter case T_ASRT: 125*773Speter putline(); 126*773Speter asrtop(s); 127*773Speter break; 128*773Speter } 129*773Speter --level; 130*773Speter if (gotos[cbn]) 131*773Speter ungoto(); 132*773Speter break; 133*773Speter } 134*773Speter /* 135*773Speter * Free the temporary name list entries defined in 136*773Speter * expressions, e.g. STRs, and WITHPTRs from withs. 137*773Speter */ 138*773Speter nlfree(snlp); 139*773Speter /* 140*773Speter * free any temporaries allocated for this statement 141*773Speter * these come from strings and sets. 142*773Speter */ 143*773Speter if ( soffset != sizes[ cbn ].om_off ) { 144*773Speter sizes[ cbn ].om_off = soffset; 145*773Speter # ifdef PC 146*773Speter putlbracket( ftnno , -sizes[cbn].om_off ); 147*773Speter # endif PC 148*773Speter } 149*773Speter } 150*773Speter 151*773Speter ungoto() 152*773Speter { 153*773Speter register struct nl *p; 154*773Speter 155*773Speter for (p = gotos[cbn]; p != NIL; p = p->chain) 156*773Speter if ((p->nl_flags & NFORWD) != 0) { 157*773Speter if (p->value[NL_GOLEV] != NOTYET) 158*773Speter if (p->value[NL_GOLEV] > level) 159*773Speter p->value[NL_GOLEV] = level; 160*773Speter } else 161*773Speter if (p->value[NL_GOLEV] != DEAD) 162*773Speter if (p->value[NL_GOLEV] > level) 163*773Speter p->value[NL_GOLEV] = DEAD; 164*773Speter } 165*773Speter 166*773Speter putcnt() 167*773Speter { 168*773Speter 169*773Speter if (monflg == 0) { 170*773Speter return; 171*773Speter } 172*773Speter inccnt( getcnt() ); 173*773Speter } 174*773Speter 175*773Speter int 176*773Speter getcnt() 177*773Speter { 178*773Speter 179*773Speter return ++cnts; 180*773Speter } 181*773Speter 182*773Speter inccnt( counter ) 183*773Speter int counter; 184*773Speter { 185*773Speter 186*773Speter # ifdef OBJ 187*773Speter put2(O_COUNT, counter ); 188*773Speter # endif OBJ 189*773Speter # ifdef PC 190*773Speter putRV( PCPCOUNT , 0 , counter * sizeof (long) , P2INT ); 191*773Speter putleaf( P2ICON , 1 , 0 , P2INT , 0 ); 192*773Speter putop( P2ASG P2PLUS , P2INT ); 193*773Speter putdot( filename , line ); 194*773Speter # endif PC 195*773Speter } 196*773Speter 197*773Speter putline() 198*773Speter { 199*773Speter 200*773Speter # ifdef OBJ 201*773Speter if (opt('p') != 0) 202*773Speter put2(O_LINO, line); 203*773Speter # endif OBJ 204*773Speter # ifdef PC 205*773Speter static lastline; 206*773Speter 207*773Speter if ( line != lastline ) { 208*773Speter stabline( line ); 209*773Speter lastline = line; 210*773Speter } 211*773Speter if ( opt( 'p' ) ) { 212*773Speter if ( opt('t') ) { 213*773Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 214*773Speter , "_LINO" ); 215*773Speter putop( P2UNARY P2CALL , P2INT ); 216*773Speter putdot( filename , line ); 217*773Speter } else { 218*773Speter putRV( STMTCOUNT , 0 , 0 , P2INT ); 219*773Speter putleaf( P2ICON , 1 , 0 , P2INT , 0 ); 220*773Speter putop( P2ASG P2PLUS , P2INT ); 221*773Speter putdot( filename , line ); 222*773Speter } 223*773Speter } 224*773Speter # endif PC 225*773Speter } 226*773Speter 227*773Speter /* 228*773Speter * With varlist do stat 229*773Speter * 230*773Speter * With statement requires an extra word 231*773Speter * in automatic storage for each level of withing. 232*773Speter * These indirect pointers are initialized here, and 233*773Speter * the scoping effect of the with statement occurs 234*773Speter * because lookup examines the field names of the records 235*773Speter * associated with the WITHPTRs on the withlist. 236*773Speter */ 237*773Speter withop(s) 238*773Speter int *s; 239*773Speter { 240*773Speter register *p; 241*773Speter register struct nl *r; 242*773Speter int i; 243*773Speter int *swl; 244*773Speter long soffset; 245*773Speter 246*773Speter putline(); 247*773Speter swl = withlist; 248*773Speter soffset = sizes[cbn].om_off; 249*773Speter for (p = s[2]; p != NIL; p = p[2]) { 250*773Speter i = sizes[cbn].om_off -= sizeof ( int * ); 251*773Speter if (sizes[cbn].om_off < sizes[cbn].om_max) 252*773Speter sizes[cbn].om_max = sizes[cbn].om_off; 253*773Speter # ifdef OBJ 254*773Speter put2(O_LV | cbn <<8+INDX, i ); 255*773Speter # endif OBJ 256*773Speter # ifdef PC 257*773Speter putlbracket( ftnno , -sizes[cbn].om_off ); 258*773Speter putRV( 0 , cbn , i , P2PTR|P2STRTY ); 259*773Speter # endif PC 260*773Speter r = lvalue(p[1], MOD , LREQ ); 261*773Speter if (r == NIL) 262*773Speter continue; 263*773Speter if (r->class != RECORD) { 264*773Speter error("Variable in with statement refers to %s, not to a record", nameof(r)); 265*773Speter continue; 266*773Speter } 267*773Speter r = defnl(0, WITHPTR, r, i); 268*773Speter r->nl_next = withlist; 269*773Speter withlist = r; 270*773Speter # ifdef OBJ 271*773Speter put(1, PTR_AS); 272*773Speter # endif OBJ 273*773Speter # ifdef PC 274*773Speter putop( P2ASSIGN , P2PTR|P2STRTY ); 275*773Speter putdot( filename , line ); 276*773Speter # endif PC 277*773Speter } 278*773Speter statement(s[3]); 279*773Speter sizes[cbn].om_off = soffset; 280*773Speter # ifdef PC 281*773Speter putlbracket( ftnno , -sizes[cbn].om_off ); 282*773Speter # endif PC 283*773Speter withlist = swl; 284*773Speter } 285*773Speter 286*773Speter extern flagwas; 287*773Speter /* 288*773Speter * var := expr 289*773Speter */ 290*773Speter asgnop(r) 291*773Speter int *r; 292*773Speter { 293*773Speter register struct nl *p; 294*773Speter register *av; 295*773Speter 296*773Speter if (r == NIL) 297*773Speter return (NIL); 298*773Speter /* 299*773Speter * Asgnop's only function is 300*773Speter * to handle function variable 301*773Speter * assignments. All other assignment 302*773Speter * stuff is handled by asgnop1. 303*773Speter * the if below checks for unqualified lefthandside: 304*773Speter * necessary for fvars. 305*773Speter */ 306*773Speter av = r[2]; 307*773Speter if (av != NIL && av[0] == T_VAR && av[3] == NIL) { 308*773Speter p = lookup1(av[2]); 309*773Speter if (p != NIL) 310*773Speter p->nl_flags = flagwas; 311*773Speter if (p != NIL && p->class == FVAR) { 312*773Speter /* 313*773Speter * Give asgnop1 the func 314*773Speter * which is the chain of 315*773Speter * the FVAR. 316*773Speter */ 317*773Speter p->nl_flags |= NUSED|NMOD; 318*773Speter p = p->chain; 319*773Speter if (p == NIL) { 320*773Speter rvalue(r[3], NIL , RREQ ); 321*773Speter return; 322*773Speter } 323*773Speter # ifdef OBJ 324*773Speter put2(O_LV | bn << 8+INDX, p->value[NL_OFFS]); 325*773Speter if (isa(p->type, "i") && width(p->type) == 1) 326*773Speter asgnop1(r, nl+T2INT); 327*773Speter else 328*773Speter asgnop1(r, p->type); 329*773Speter # endif OBJ 330*773Speter # ifdef PC 331*773Speter /* 332*773Speter * this should be the lvalue of the fvar, 333*773Speter * but since the second pass knows to use 334*773Speter * the address of the left operand of an 335*773Speter * assignment, what i want here is an rvalue. 336*773Speter * see note in funchdr about fvar allocation. 337*773Speter */ 338*773Speter p = p -> ptr[ NL_FVAR ]; 339*773Speter putRV( p -> symbol , bn , p -> value[ NL_OFFS ] 340*773Speter , p2type( p -> type ) ); 341*773Speter asgnop1( r , p -> type ); 342*773Speter # endif PC 343*773Speter return; 344*773Speter } 345*773Speter } 346*773Speter asgnop1(r, NIL); 347*773Speter } 348*773Speter 349*773Speter /* 350*773Speter * Asgnop1 handles all assignments. 351*773Speter * If p is not nil then we are assigning 352*773Speter * to a function variable, otherwise 353*773Speter * we look the variable up ourselves. 354*773Speter */ 355*773Speter struct nl * 356*773Speter asgnop1(r, p) 357*773Speter int *r; 358*773Speter register struct nl *p; 359*773Speter { 360*773Speter register struct nl *p1; 361*773Speter 362*773Speter if (r == NIL) 363*773Speter return (NIL); 364*773Speter if (p == NIL) { 365*773Speter # ifdef OBJ 366*773Speter p = lvalue(r[2], MOD|ASGN|NOUSE , LREQ ); 367*773Speter # endif OBJ 368*773Speter # ifdef PC 369*773Speter /* 370*773Speter * since the second pass knows that it should reference 371*773Speter * the lefthandside of asignments, what i need here is 372*773Speter * an rvalue. 373*773Speter */ 374*773Speter p = lvalue( r[2] , MOD|ASGN|NOUSE , RREQ ); 375*773Speter # endif PC 376*773Speter if ( p == NIL ) { 377*773Speter rvalue( r[3] , NIL , RREQ ); 378*773Speter return NIL; 379*773Speter } 380*773Speter } 381*773Speter # ifdef OBJ 382*773Speter p1 = rvalue(r[3], p , RREQ ); 383*773Speter # endif OBJ 384*773Speter # ifdef PC 385*773Speter /* 386*773Speter * if this is a scalar assignment, 387*773Speter * then i want to rvalue the righthandside. 388*773Speter * if this is a structure assignment, 389*773Speter * then i want an lvalue to the righthandside. 390*773Speter * that's what the intermediate form sez. 391*773Speter */ 392*773Speter switch ( classify( p ) ) { 393*773Speter case TINT: 394*773Speter case TCHAR: 395*773Speter case TBOOL: 396*773Speter case TSCAL: 397*773Speter precheck( p , "_RANG4" , "_RSNG4" ); 398*773Speter case TDOUBLE: 399*773Speter case TPTR: 400*773Speter p1 = rvalue( r[3] , p , RREQ ); 401*773Speter break; 402*773Speter default: 403*773Speter p1 = rvalue( r[3] , p , LREQ ); 404*773Speter break; 405*773Speter } 406*773Speter # endif PC 407*773Speter if (p1 == NIL) 408*773Speter return (NIL); 409*773Speter if (incompat(p1, p, r[3])) { 410*773Speter cerror("Type of expression clashed with type of variable in assignment"); 411*773Speter return (NIL); 412*773Speter } 413*773Speter switch (classify(p)) { 414*773Speter case TINT: 415*773Speter case TBOOL: 416*773Speter case TCHAR: 417*773Speter case TSCAL: 418*773Speter # ifdef OBJ 419*773Speter rangechk(p, p1); 420*773Speter # endif OBJ 421*773Speter # ifdef PC 422*773Speter postcheck( p ); 423*773Speter # endif PC 424*773Speter case TDOUBLE: 425*773Speter case TPTR: 426*773Speter # ifdef OBJ 427*773Speter gen(O_AS2, O_AS2, width(p), width(p1)); 428*773Speter # endif OBJ 429*773Speter # ifdef PC 430*773Speter putop( P2ASSIGN , p2type( p ) ); 431*773Speter putdot( filename , line ); 432*773Speter # endif PC 433*773Speter break; 434*773Speter default: 435*773Speter # ifdef OBJ 436*773Speter put2(O_AS, width(p)); 437*773Speter # endif OBJ 438*773Speter # ifdef PC 439*773Speter putstrop( P2STASG , p2type( p ) 440*773Speter , lwidth( p ) , align( p ) ); 441*773Speter putdot( filename , line ); 442*773Speter # endif PC 443*773Speter } 444*773Speter return (p); /* Used by for statement */ 445*773Speter } 446*773Speter 447*773Speter #ifdef OBJ 448*773Speter /* 449*773Speter * for var := expr [down]to expr do stat 450*773Speter */ 451*773Speter forop(r) 452*773Speter int *r; 453*773Speter { 454*773Speter register struct nl *t1, *t2; 455*773Speter int l1, l2, l3; 456*773Speter long soffset; 457*773Speter register op; 458*773Speter struct nl *p; 459*773Speter int *rr, goc, i; 460*773Speter 461*773Speter p = NIL; 462*773Speter goc = gocnt; 463*773Speter if (r == NIL) 464*773Speter goto aloha; 465*773Speter putline(); 466*773Speter /* 467*773Speter * Start with assignment 468*773Speter * of initial value to for variable 469*773Speter */ 470*773Speter t1 = asgnop1(r[2], NIL); 471*773Speter if (t1 == NIL) { 472*773Speter rvalue(r[3], NIL , RREQ ); 473*773Speter statement(r[4]); 474*773Speter goto aloha; 475*773Speter } 476*773Speter rr = r[2]; /* Assignment */ 477*773Speter rr = rr[2]; /* Lhs variable */ 478*773Speter if (rr[3] != NIL) { 479*773Speter error("For variable must be unqualified"); 480*773Speter rvalue(r[3], NIL , RREQ ); 481*773Speter statement(r[4]); 482*773Speter goto aloha; 483*773Speter } 484*773Speter p = lookup(rr[2]); 485*773Speter p->value[NL_FORV] = 1; 486*773Speter if (isnta(t1, "bcis")) { 487*773Speter error("For variables cannot be %ss", nameof(t1)); 488*773Speter statement(r[4]); 489*773Speter goto aloha; 490*773Speter } 491*773Speter /* 492*773Speter * Allocate automatic 493*773Speter * space for limit variable 494*773Speter */ 495*773Speter sizes[cbn].om_off -= 4; 496*773Speter if (sizes[cbn].om_off < sizes[cbn].om_max) 497*773Speter sizes[cbn].om_max = sizes[cbn].om_off; 498*773Speter i = sizes[cbn].om_off; 499*773Speter /* 500*773Speter * Initialize the limit variable 501*773Speter */ 502*773Speter put2(O_LV | cbn<<8+INDX, i); 503*773Speter t2 = rvalue(r[3], NIL , RREQ ); 504*773Speter if (incompat(t2, t1, r[3])) { 505*773Speter cerror("Limit type clashed with index type in 'for' statement"); 506*773Speter statement(r[4]); 507*773Speter goto aloha; 508*773Speter } 509*773Speter put1(width(t2) <= 2 ? O_AS24 : O_AS4); 510*773Speter /* 511*773Speter * See if we can skip the loop altogether 512*773Speter */ 513*773Speter rr = r[2]; 514*773Speter if (rr != NIL) 515*773Speter rvalue(rr[2], NIL , RREQ ); 516*773Speter put2(O_RV4 | cbn<<8+INDX, i); 517*773Speter gen(NIL, r[0] == T_FORU ? T_LE : T_GE, width(t1), 4); 518*773Speter /* 519*773Speter * L1 will be patched to skip the body of the loop. 520*773Speter * L2 marks the top of the loop when we go around. 521*773Speter */ 522*773Speter put2(O_IF, (l1 = getlab())); 523*773Speter putlab(l2 = getlab()); 524*773Speter putcnt(); 525*773Speter statement(r[4]); 526*773Speter /* 527*773Speter * now we see if we get to go again 528*773Speter */ 529*773Speter if (opt('t') == 0) { 530*773Speter /* 531*773Speter * Easy if we dont have to test 532*773Speter */ 533*773Speter put2(O_RV4 | cbn<<8+INDX, i); 534*773Speter if (rr != NIL) 535*773Speter lvalue(rr[2], MOD , RREQ ); 536*773Speter put2((r[0] == T_FORU ? O_FOR1U : O_FOR1D) + (width(t1) >> 1), l2); 537*773Speter } else { 538*773Speter line = r[1]; 539*773Speter putline(); 540*773Speter if (rr != NIL) 541*773Speter rvalue(rr[2], NIL , RREQ ); 542*773Speter put2(O_RV4 | cbn << 8+INDX, i); 543*773Speter gen(NIL, (r[0] == T_FORU ? T_LT : T_GT), width(t1), 4); 544*773Speter l3 = put2(O_IF, getlab()); 545*773Speter lvalue((int *) rr[2], MOD , RREQ ); 546*773Speter rvalue(rr[2], NIL , RREQ ); 547*773Speter put2(O_CON2, 1); 548*773Speter t2 = gen(NIL, r[0] == T_FORU ? T_ADD: T_SUB, width(t1), 2); 549*773Speter rangechk(t1, t2); /* The point of all this */ 550*773Speter gen(O_AS2, O_AS2, width(t1), width(t2)); 551*773Speter put2(O_TRA, l2); 552*773Speter patch(l3); 553*773Speter } 554*773Speter sizes[cbn].om_off += 4; 555*773Speter patch(l1); 556*773Speter aloha: 557*773Speter noreach = 0; 558*773Speter if (p != NIL) 559*773Speter p->value[NL_FORV] = 0; 560*773Speter if (goc != gocnt) 561*773Speter putcnt(); 562*773Speter } 563*773Speter #endif OBJ 564*773Speter 565*773Speter /* 566*773Speter * if expr then stat [ else stat ] 567*773Speter */ 568*773Speter ifop(r) 569*773Speter int *r; 570*773Speter { 571*773Speter register struct nl *p; 572*773Speter register l1, l2; /* l1 is start of else, l2 is end of else */ 573*773Speter int nr, goc; 574*773Speter 575*773Speter goc = gocnt; 576*773Speter if (r == NIL) 577*773Speter return; 578*773Speter putline(); 579*773Speter p = rvalue(r[2], NIL , RREQ ); 580*773Speter if (p == NIL) { 581*773Speter statement(r[3]); 582*773Speter noreach = 0; 583*773Speter statement(r[4]); 584*773Speter noreach = 0; 585*773Speter return; 586*773Speter } 587*773Speter if (isnta(p, "b")) { 588*773Speter error("Type of expression in if statement must be Boolean, not %s", nameof(p)); 589*773Speter statement(r[3]); 590*773Speter noreach = 0; 591*773Speter statement(r[4]); 592*773Speter noreach = 0; 593*773Speter return; 594*773Speter } 595*773Speter # ifdef OBJ 596*773Speter l1 = put2(O_IF, getlab()); 597*773Speter # endif OBJ 598*773Speter # ifdef PC 599*773Speter l1 = getlab(); 600*773Speter putleaf( P2ICON , l1 , 0 , P2INT , 0 ); 601*773Speter putop( P2CBRANCH , P2INT ); 602*773Speter putdot( filename , line ); 603*773Speter # endif PC 604*773Speter putcnt(); 605*773Speter statement(r[3]); 606*773Speter nr = noreach; 607*773Speter if (r[4] != NIL) { 608*773Speter /* 609*773Speter * else stat 610*773Speter */ 611*773Speter --level; 612*773Speter ungoto(); 613*773Speter ++level; 614*773Speter # ifdef OBJ 615*773Speter l2 = put2(O_TRA, getlab()); 616*773Speter # endif OBJ 617*773Speter # ifdef PC 618*773Speter l2 = getlab(); 619*773Speter putjbr( l2 ); 620*773Speter # endif PC 621*773Speter patch(l1); 622*773Speter noreach = 0; 623*773Speter statement(r[4]); 624*773Speter noreach &= nr; 625*773Speter l1 = l2; 626*773Speter } else 627*773Speter noreach = 0; 628*773Speter patch(l1); 629*773Speter if (goc != gocnt) 630*773Speter putcnt(); 631*773Speter } 632*773Speter 633*773Speter /* 634*773Speter * while expr do stat 635*773Speter */ 636*773Speter whilop(r) 637*773Speter int *r; 638*773Speter { 639*773Speter register struct nl *p; 640*773Speter register l1, l2; 641*773Speter int goc; 642*773Speter 643*773Speter goc = gocnt; 644*773Speter if (r == NIL) 645*773Speter return; 646*773Speter putlab(l1 = getlab()); 647*773Speter putline(); 648*773Speter p = rvalue(r[2], NIL , RREQ ); 649*773Speter if (p == NIL) { 650*773Speter statement(r[3]); 651*773Speter noreach = 0; 652*773Speter return; 653*773Speter } 654*773Speter if (isnta(p, "b")) { 655*773Speter error("Type of expression in while statement must be Boolean, not %s", nameof(p)); 656*773Speter statement(r[3]); 657*773Speter noreach = 0; 658*773Speter return; 659*773Speter } 660*773Speter l2 = getlab(); 661*773Speter # ifdef OBJ 662*773Speter put2(O_IF, l2); 663*773Speter # endif OBJ 664*773Speter # ifdef PC 665*773Speter putleaf( P2ICON , l2 , 0 , P2INT , 0 ); 666*773Speter putop( P2CBRANCH , P2INT ); 667*773Speter putdot( filename , line ); 668*773Speter # endif PC 669*773Speter putcnt(); 670*773Speter statement(r[3]); 671*773Speter # ifdef OBJ 672*773Speter put2(O_TRA, l1); 673*773Speter # endif OBJ 674*773Speter # ifdef PC 675*773Speter putjbr( l1 ); 676*773Speter # endif PC 677*773Speter patch(l2); 678*773Speter if (goc != gocnt) 679*773Speter putcnt(); 680*773Speter } 681*773Speter 682*773Speter /* 683*773Speter * repeat stat* until expr 684*773Speter */ 685*773Speter repop(r) 686*773Speter int *r; 687*773Speter { 688*773Speter register struct nl *p; 689*773Speter register l; 690*773Speter int goc; 691*773Speter 692*773Speter goc = gocnt; 693*773Speter if (r == NIL) 694*773Speter return; 695*773Speter l = putlab(getlab()); 696*773Speter putcnt(); 697*773Speter statlist(r[2]); 698*773Speter line = r[1]; 699*773Speter p = rvalue(r[3], NIL , RREQ ); 700*773Speter if (p == NIL) 701*773Speter return; 702*773Speter if (isnta(p,"b")) { 703*773Speter error("Until expression type must be Boolean, not %s, in repeat statement", nameof(p)); 704*773Speter return; 705*773Speter } 706*773Speter # ifdef OBJ 707*773Speter put2(O_IF, l); 708*773Speter # endif OBJ 709*773Speter # ifdef PC 710*773Speter putleaf( P2ICON , l , 0 , P2INT , 0 ); 711*773Speter putop( P2CBRANCH , P2INT ); 712*773Speter putdot( filename , line ); 713*773Speter # endif PC 714*773Speter if (goc != gocnt) 715*773Speter putcnt(); 716*773Speter } 717*773Speter 718*773Speter /* 719*773Speter * assert expr 720*773Speter */ 721*773Speter asrtop(r) 722*773Speter register int *r; 723*773Speter { 724*773Speter register struct nl *q; 725*773Speter 726*773Speter if (opt('s')) { 727*773Speter standard(); 728*773Speter error("Assert statement is non-standard"); 729*773Speter } 730*773Speter if (!opt('t')) 731*773Speter return; 732*773Speter r = r[2]; 733*773Speter # ifdef OBJ 734*773Speter q = rvalue((int *) r, NLNIL , RREQ ); 735*773Speter # endif OBJ 736*773Speter # ifdef PC 737*773Speter putleaf( P2ICON , 0 , 0 738*773Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_ASRT" ); 739*773Speter q = stkrval( r , NLNIL , RREQ ); 740*773Speter # endif PC 741*773Speter if (q == NIL) 742*773Speter return; 743*773Speter if (isnta(q, "b")) 744*773Speter error("Assert expression must be Boolean, not %ss", nameof(q)); 745*773Speter # ifdef OBJ 746*773Speter put1(O_ASRT); 747*773Speter # endif OBJ 748*773Speter # ifdef PC 749*773Speter putop( P2CALL , P2INT ); 750*773Speter putdot( filename , line ); 751*773Speter # endif PC 752*773Speter } 753