148116Sbostic /*-
2*62217Sbostic * Copyright (c) 1980, 1993
3*62217Sbostic * The Regents of the University of California. All rights reserved.
448116Sbostic *
548116Sbostic * %sccs.include.redist.c%
622192Sdist */
7773Speter
815941Smckusick #ifndef lint
9*62217Sbostic static char sccsid[] = "@(#)stat.c 8.1 (Berkeley) 06/06/93";
1048116Sbostic #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
ungoto()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
putcnt()161773Speter putcnt()
162773Speter {
163773Speter
16415941Smckusick if (monflg == FALSE) {
165773Speter return;
166773Speter }
167773Speter inccnt( getcnt() );
168773Speter }
169773Speter
170773Speter int
getcnt()171773Speter getcnt()
172773Speter {
173773Speter
174773Speter return ++cnts;
175773Speter }
176773Speter
inccnt(counter)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
putline()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 */
withop(s)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 */
asgnop(r)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 *
asgnop1(r,p)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 *
pcasgconf(r,p)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 */
ifop(if_n)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 */
whilop(w_node)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 */
repop(r)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