xref: /csrg-svn/usr.bin/pascal/src/stat.c (revision 15985)
1773Speter /* Copyright (c) 1979 Regents of the University of California */
2773Speter 
315941Smckusick #ifndef lint
4*15985Saoki static char sccsid[] = "@(#)stat.c 1.15 02/08/84";
515941Smckusick #endif
6773Speter 
7773Speter #include "whoami.h"
8773Speter #include "0.h"
9773Speter #include "tree.h"
10773Speter #include "objfmt.h"
11773Speter #ifdef PC
12773Speter #   include "pcops.h"
13773Speter #   include "pc.h"
14773Speter #endif PC
1511330Speter #include "tmps.h"
16773Speter 
17773Speter int cntstat;
18773Speter short cnts = 3;
19773Speter #include "opcode.h"
2015941Smckusick #include "tree_ty.h"
21773Speter 
22773Speter /*
23773Speter  * Statement list
24773Speter  */
25773Speter statlist(r)
2615941Smckusick 	struct tnode *r;
27773Speter {
2815941Smckusick 	register struct tnode *sl;
29773Speter 
3015941Smckusick 	for (sl=r; sl != TR_NIL; sl=sl->list_node.next)
3115941Smckusick 		statement(sl->list_node.list);
32773Speter }
33773Speter 
34773Speter /*
35773Speter  * Statement
36773Speter  */
37773Speter statement(r)
3815941Smckusick 	struct tnode *r;
39773Speter {
4015941Smckusick 	register struct tnode *tree_node;
41773Speter 	register struct nl *snlp;
423228Smckusic 	struct tmps soffset;
43773Speter 
4415941Smckusick 	tree_node = r;
45773Speter 	snlp = nlp;
463228Smckusic 	soffset = sizes[cbn].curtmps;
47773Speter top:
48773Speter 	if (cntstat) {
49773Speter 		cntstat = 0;
50773Speter 		putcnt();
51773Speter 	}
5215941Smckusick 	if (tree_node == TR_NIL)
53773Speter 		return;
5415941Smckusick 	line = tree_node->lined.line_no;
5515941Smckusick 	if (tree_node->tag == T_LABEL) {
5615941Smckusick 		labeled(tree_node->label_node.lbl_ptr);
5715941Smckusick 		tree_node = tree_node->label_node.stmnt;
5815941Smckusick 		noreach = FALSE;
59773Speter 		cntstat = 1;
60773Speter 		goto top;
61773Speter 	}
62773Speter 	if (noreach) {
6315941Smckusick 		noreach = FALSE;
64773Speter 		warning();
65773Speter 		error("Unreachable statement");
66773Speter 	}
6715941Smckusick 	switch (tree_node->tag) {
68773Speter 		case T_PCALL:
69773Speter 			putline();
70773Speter #			ifdef OBJ
7115941Smckusick 			    proc(tree_node);
72773Speter #			endif OBJ
73773Speter #			ifdef PC
7415941Smckusick 			    pcproc( tree_node );
75773Speter #			endif PC
76773Speter 			break;
77773Speter 		case T_ASGN:
78773Speter 			putline();
7915941Smckusick 			asgnop(&(tree_node->asg_node));
80773Speter 			break;
81773Speter 		case T_GOTO:
82773Speter 			putline();
8315941Smckusick 			gotoop(tree_node->goto_node.lbl_ptr);
8415941Smckusick 			noreach = TRUE;
85773Speter 			cntstat = 1;
86773Speter 			break;
87773Speter 		default:
88773Speter 			level++;
8915941Smckusick 			switch (tree_node->tag) {
90773Speter 				default:
91773Speter 					panic("stat");
92773Speter 				case T_IF:
93773Speter 				case T_IFEL:
9415941Smckusick 					ifop(&(tree_node->if_node));
95773Speter 					break;
96773Speter 				case T_WHILE:
9715941Smckusick 					whilop(&(tree_node->whi_cas));
9815941Smckusick 					noreach = FALSE;
99773Speter 					break;
100773Speter 				case T_REPEAT:
10115941Smckusick 					repop(&(tree_node->repeat));
102773Speter 					break;
103773Speter 				case T_FORU:
104773Speter 				case T_FORD:
10515941Smckusick 				        forop(tree_node);
10615941Smckusick 					noreach = FALSE;
107773Speter 					break;
108773Speter 				case T_BLOCK:
10915941Smckusick 					statlist(tree_node->stmnt_blck.stmnt_list);
110773Speter 					break;
111773Speter 				case T_CASE:
112773Speter 					putline();
113773Speter #					ifdef OBJ
11415941Smckusick 					    caseop(&(tree_node->whi_cas));
115773Speter #					endif OBJ
116773Speter #					ifdef PC
11715941Smckusick 					    pccaseop(&(tree_node->whi_cas));
118773Speter #					endif PC
119773Speter 					break;
120773Speter 				case T_WITH:
12115941Smckusick 					withop(&(tree_node->with_node));
122773Speter 					break;
123773Speter 			}
124773Speter 			--level;
125773Speter 			if (gotos[cbn])
126773Speter 				ungoto();
127773Speter 			break;
128773Speter 	}
129773Speter 	/*
130773Speter 	 * Free the temporary name list entries defined in
131773Speter 	 * expressions, e.g. STRs, and WITHPTRs from withs.
132773Speter 	 */
133773Speter 	nlfree(snlp);
134773Speter 	    /*
135773Speter 	     *	free any temporaries allocated for this statement
136773Speter 	     *	these come from strings and sets.
137773Speter 	     */
1383228Smckusic 	tmpfree(&soffset);
139773Speter }
140773Speter 
141773Speter ungoto()
142773Speter {
143773Speter 	register struct nl *p;
144773Speter 
14515941Smckusick 	for (p = gotos[cbn]; p != NLNIL; p = p->chain)
146773Speter 		if ((p->nl_flags & NFORWD) != 0) {
147773Speter 			if (p->value[NL_GOLEV] != NOTYET)
148773Speter 				if (p->value[NL_GOLEV] > level)
149773Speter 					p->value[NL_GOLEV] = level;
150773Speter 		} else
151773Speter 			if (p->value[NL_GOLEV] != DEAD)
152773Speter 				if (p->value[NL_GOLEV] > level)
153773Speter 					p->value[NL_GOLEV] = DEAD;
154773Speter }
155773Speter 
156773Speter putcnt()
157773Speter {
158773Speter 
15915941Smckusick 	if (monflg == FALSE) {
160773Speter 		return;
161773Speter 	}
162773Speter 	inccnt( getcnt() );
163773Speter }
164773Speter 
165773Speter int
166773Speter getcnt()
167773Speter     {
168773Speter 
169773Speter 	return ++cnts;
170773Speter     }
171773Speter 
172773Speter inccnt( counter )
173773Speter     int	counter;
174773Speter     {
175773Speter 
176773Speter #	ifdef OBJ
17715941Smckusick 	    (void) put(2, O_COUNT, counter );
178773Speter #	endif OBJ
179773Speter #	ifdef PC
1803835Speter 	    putRV( PCPCOUNT , 0 , counter * sizeof (long) , NGLOBAL , P2INT );
18115941Smckusick 	    putleaf( P2ICON , 1 , 0 , P2INT , (char *) 0 );
182773Speter 	    putop( P2ASG P2PLUS , P2INT );
183773Speter 	    putdot( filename , line );
184773Speter #	endif PC
185773Speter     }
186773Speter 
187773Speter putline()
188773Speter {
189773Speter 
190773Speter #	ifdef OBJ
191773Speter 	    if (opt('p') != 0)
19215941Smckusick 		    (void) put(2, O_LINO, line);
1935654Slinton 
1945654Slinton 	    /*
1955654Slinton 	     * put out line number information for pdx
1965654Slinton 	     */
1975654Slinton 	    lineno(line);
1985654Slinton 
199773Speter #	endif OBJ
200773Speter #	ifdef PC
201773Speter 	    static lastline;
202773Speter 
203773Speter 	    if ( line != lastline ) {
204773Speter 		stabline( line );
205773Speter 		lastline = line;
206773Speter 	    }
207773Speter 	    if ( opt( 'p' ) ) {
208773Speter 		if ( opt('t') ) {
209773Speter 		    putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR )
210773Speter 			    , "_LINO" );
211773Speter 		    putop( P2UNARY P2CALL , P2INT );
212773Speter 		    putdot( filename , line );
213773Speter 		} else {
2143835Speter 		    putRV( STMTCOUNT , 0 , 0 , NGLOBAL , P2INT );
21515941Smckusick 		    putleaf( P2ICON , 1 , 0 , P2INT , (char *) 0 );
216773Speter 		    putop( P2ASG P2PLUS , P2INT );
217773Speter 		    putdot( filename , line );
218773Speter 		}
219773Speter 	    }
220773Speter #	endif PC
221773Speter }
222773Speter 
223773Speter /*
224773Speter  * With varlist do stat
225773Speter  *
226773Speter  * With statement requires an extra word
227773Speter  * in automatic storage for each level of withing.
228773Speter  * These indirect pointers are initialized here, and
229773Speter  * the scoping effect of the with statement occurs
230773Speter  * because lookup examines the field names of the records
231773Speter  * associated with the WITHPTRs on the withlist.
232773Speter  */
233773Speter withop(s)
23415941Smckusick 	WITH_NODE *s;
235773Speter {
23615941Smckusick 	register struct tnode *p;
237773Speter 	register struct nl *r;
2383835Speter 	struct nl	*tempnlp;
23915941Smckusick 	struct nl *swl;
240773Speter 
241773Speter 	putline();
242773Speter 	swl = withlist;
24315941Smckusick 	for (p = s->var_list; p != TR_NIL; p = p->list_node.next) {
24415951Smckusick 		tempnlp = tmpalloc((long) (sizeof(int *)), nl+TPTR, REGOK);
24515951Smckusick 		    /*
24615951Smckusick 		     *	no one uses the allocated temporary namelist entry,
24715951Smckusick 		     *	since we have to use it before we know its type;
24815951Smckusick 		     *	but we use its runtime location for the with pointer.
24915951Smckusick 		     */
250773Speter #		ifdef OBJ
25115941Smckusick 		    (void) put(2, O_LV | cbn <<8+INDX, tempnlp -> value[ NL_OFFS ] );
252773Speter #		endif OBJ
253773Speter #		ifdef PC
25415941Smckusick 		    putRV( (char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] ,
2553835Speter 			    tempnlp -> extra_flags , P2PTR|P2STRTY );
256773Speter #		endif PC
25715941Smckusick 		r = lvalue(p->list_node.list, MOD , LREQ );
25815941Smckusick 		if (r == NLNIL)
259773Speter 			continue;
260773Speter 		if (r->class != RECORD) {
261773Speter 			error("Variable in with statement refers to %s, not to a record", nameof(r));
262773Speter 			continue;
263773Speter 		}
26415941Smckusick 		r = defnl((char *) 0, WITHPTR, r, tempnlp -> value[ NL_OFFS ] );
2653835Speter #		ifdef PC
2663835Speter 		    r -> extra_flags |= tempnlp -> extra_flags;
2673835Speter #		endif PC
268773Speter 		r->nl_next = withlist;
269773Speter 		withlist = r;
270773Speter #		ifdef OBJ
27115941Smckusick 		    (void) put(1, PTR_AS);
272773Speter #		endif OBJ
273773Speter #		ifdef PC
274773Speter 		    putop( P2ASSIGN , P2PTR|P2STRTY );
275773Speter 		    putdot( filename , line );
276773Speter #		endif PC
277773Speter 	}
27815941Smckusick 	statement(s->stmnt);
279773Speter 	withlist = swl;
280773Speter }
281773Speter 
282773Speter extern	flagwas;
283773Speter /*
284773Speter  * var := expr
285773Speter  */
286773Speter asgnop(r)
28715941Smckusick 	ASG_NODE *r;
288773Speter {
289773Speter 	register struct nl *p;
29015941Smckusick 	register struct tnode *av;
291773Speter 
292773Speter 	/*
293773Speter 	 * Asgnop's only function is
294773Speter 	 * to handle function variable
295773Speter 	 * assignments.  All other assignment
296773Speter 	 * stuff is handled by asgnop1.
297773Speter 	 * the if below checks for unqualified lefthandside:
298773Speter 	 * necessary for fvars.
299773Speter 	 */
30015941Smckusick 	av = r->lhs_var;
30115941Smckusick 	if (av != TR_NIL && av->tag == T_VAR && av->var_node.qual == TR_NIL) {
30215941Smckusick 		p = lookup1(av->var_node.cptr);
30315941Smckusick 		if (p != NLNIL)
304773Speter 			p->nl_flags = flagwas;
30515941Smckusick 		if (p != NLNIL && p->class == FVAR) {
306773Speter 			/*
307773Speter 			 * Give asgnop1 the func
308773Speter 			 * which is the chain of
309773Speter 			 * the FVAR.
310773Speter 			 */
311773Speter 			p->nl_flags |= NUSED|NMOD;
312773Speter 			p = p->chain;
31315941Smckusick 			if (p == NLNIL) {
31415941Smckusick 				p = rvalue(r->rhs_expr, NLNIL , RREQ );
315773Speter 				return;
316773Speter 			}
317773Speter #			ifdef OBJ
31815941Smckusick 			    (void) put(2, O_LV | bn << 8+INDX, (int)p->value[NL_OFFS]);
319773Speter 			    if (isa(p->type, "i") && width(p->type) == 1)
32015941Smckusick 				    (void) asgnop1(r, nl+T2INT);
321773Speter 			    else
32215941Smckusick 				    (void) asgnop1(r, p->type);
323773Speter #			endif OBJ
324773Speter #			ifdef PC
325773Speter 				/*
326773Speter 				 * this should be the lvalue of the fvar,
327773Speter 				 * but since the second pass knows to use
328773Speter 				 * the address of the left operand of an
329773Speter 				 * assignment, what i want here is an rvalue.
330773Speter 				 * see note in funchdr about fvar allocation.
331773Speter 				 */
332773Speter 			    p = p -> ptr[ NL_FVAR ];
3333835Speter 			    putRV( p -> symbol , bn , p -> value[ NL_OFFS ] ,
3343835Speter 				    p -> extra_flags , p2type( p -> type ) );
33515941Smckusick 			    (void) asgnop1( r , p -> type );
336773Speter #			endif PC
337773Speter 			return;
338773Speter 		}
339773Speter 	}
34015941Smckusick 	(void) asgnop1(r, NLNIL);
341773Speter }
342773Speter 
343773Speter /*
344773Speter  * Asgnop1 handles all assignments.
345773Speter  * If p is not nil then we are assigning
346773Speter  * to a function variable, otherwise
347773Speter  * we look the variable up ourselves.
348773Speter  */
349773Speter struct nl *
350773Speter asgnop1(r, p)
35115941Smckusick 	ASG_NODE *r;
352773Speter 	register struct nl *p;
353773Speter {
354773Speter 	register struct nl *p1;
355*15985Saoki 	int	clas;
35615941Smckusick #ifdef OBJ
3573079Smckusic 	int w;
358*15985Saoki #endif OBJ
359773Speter 
360*15985Saoki #ifdef OBJ
36115941Smckusick 	if (p == NLNIL) {
362*15985Saoki 	    p = lvalue(r->lhs_var, MOD|ASGN|NOUSE , LREQ );
36315941Smckusick 	    if ( p == NLNIL ) {
36415941Smckusick 		(void) rvalue( r->rhs_expr , NLNIL , RREQ );
36515941Smckusick 		return NLNIL;
366773Speter 	    }
367*15985Saoki 	    w = width(p);
368*15985Saoki 	} else {
3693079Smckusic 	    /*
3703079Smckusic 	     * assigning to the return value, which is at least
3713079Smckusic 	     * of width two since it resides on the stack
3723079Smckusic 	     */
373*15985Saoki 	    w = width(p);
374*15985Saoki 	    if (w < 2)
375*15985Saoki 		w = 2;
376*15985Saoki 	}
377*15985Saoki 	clas = classify(p);
378*15985Saoki 	if ((clas == TARY || clas == TSTR) && p->chain->class == CRANGE) {
379*15985Saoki 	    p1 = lvalue(r->rhs_expr, p , LREQ ); /* SHOULD THIS BE rvalue? */
380*15985Saoki 	} else {
381*15985Saoki 	    p1 = rvalue(r->rhs_expr, p , RREQ );
382*15985Saoki 	}
383*15985Saoki #   endif OBJ
384*15985Saoki #   ifdef PC
385*15985Saoki 	if (p == NLNIL) {
386*15985Saoki 	    /* check for conformant array type */
387*15985Saoki 	    codeoff();
388*15985Saoki 	    p = rvalue(r->lhs_var, MOD|ASGN|NOUSE, LREQ);
389*15985Saoki 	    codeon();
390*15985Saoki 	    if (p == NLNIL) {
391*15985Saoki 		(void) rvalue(r->rhs_expr, NLNIL, RREQ);
392*15985Saoki 		return NLNIL;
3933079Smckusic 	    }
394*15985Saoki 	    clas = classify(p);
395*15985Saoki 	    if ((clas == TARY || clas == TSTR) && p->chain->class == CRANGE) {
396*15985Saoki 		return pcasgconf(r, p);
39715970Smckusick 	    } else {
398773Speter 		/*
399*15985Saoki 		 * since the second pass knows that it should reference
400*15985Saoki 		 * the lefthandside of asignments, what i need here is
401*15985Saoki 		 * an rvalue.
402773Speter 		 */
403*15985Saoki 		p = lvalue( r->lhs_var , MOD|ASGN|NOUSE , RREQ );
404773Speter 	    }
405*15985Saoki 	    if ( p == NLNIL ) {
406*15985Saoki 		(void) rvalue( r->rhs_expr , NLNIL , RREQ );
407*15985Saoki 		return NLNIL;
408*15985Saoki 	    }
409*15985Saoki 	}
410*15985Saoki 	    /*
411*15985Saoki 	     *	if this is a scalar assignment,
412*15985Saoki 	     *	    then i want to rvalue the righthandside.
413*15985Saoki 	     *	if this is a structure assignment,
414*15985Saoki 	     *	    then i want an lvalue to the righthandside.
415*15985Saoki 	     *  that's what the intermediate form sez.
416*15985Saoki 	     */
417*15985Saoki 	switch ( classify( p ) ) {
418*15985Saoki 	    case TINT:
419*15985Saoki 	    case TCHAR:
420*15985Saoki 	    case TBOOL:
421*15985Saoki 	    case TSCAL:
422*15985Saoki 		precheck( p , "_RANG4" , "_RSNG4" );
423*15985Saoki 		/* and fall through */
424*15985Saoki 	    case TDOUBLE:
425*15985Saoki 	    case TPTR:
426*15985Saoki 		p1 = rvalue( r->rhs_expr , p , RREQ );
427*15985Saoki 		break;
428*15985Saoki 	    default:
429*15985Saoki 		p1 = rvalue( r->rhs_expr , p , LREQ );
430*15985Saoki 		break;
431*15985Saoki 	}
432773Speter #	endif PC
43315941Smckusick 	if (p1 == NLNIL)
43415941Smckusick 		return (NLNIL);
43515941Smckusick 	if (incompat(p1, p, r->rhs_expr)) {
436773Speter 		cerror("Type of expression clashed with type of variable in assignment");
43715941Smckusick 		return (NLNIL);
438773Speter 	}
4398758Speter #	ifdef OBJ
4408758Speter 	    switch (classify(p)) {
4418758Speter 		    case TINT:
4428758Speter 		    case TBOOL:
4438758Speter 		    case TCHAR:
4448758Speter 		    case TSCAL:
445773Speter 			    rangechk(p, p1);
44615941Smckusick 			    (void) gen(O_AS2, O_AS2, w, width(p1));
4478758Speter 			    break;
4488758Speter 		    case TDOUBLE:
4498758Speter 		    case TPTR:
45015941Smckusick 			    (void) gen(O_AS2, O_AS2, w, width(p1));
4518758Speter 			    break;
45215970Smckusick 		    case TARY:
45315970Smckusick 		    case TSTR:
45415970Smckusick 			    if (p->chain->class == CRANGE) {
45515970Smckusick 				/* conformant array assignment */
45615970Smckusick 				p1 = p->chain;
45715970Smckusick 				w = width(p1->type);
45815970Smckusick 				putcbnds(p1, 1);
45915970Smckusick 				putcbnds(p1, 0);
46015970Smckusick 				gen(NIL, T_SUB, w, w);
46115970Smckusick 				put(2, w > 2? O_CON24: O_CON2, 1);
46215970Smckusick 				gen(NIL, T_ADD, w, w);
46315970Smckusick 				putcbnds(p1, 2);
46415970Smckusick 				gen(NIL, T_MULT, w, w);
46515970Smckusick 				put(1, O_VAS);
46615970Smckusick 				break;
46715970Smckusick 			    }
46815970Smckusick 			    /* else fall through */
4698758Speter 		    default:
47015941Smckusick 			    (void) put(2, O_AS, w);
4718758Speter 			    break;
4728758Speter 	    }
4738758Speter #	endif OBJ
4748758Speter #	ifdef PC
4758758Speter 	    switch (classify(p)) {
4768758Speter 		    case TINT:
4778758Speter 		    case TBOOL:
4788758Speter 		    case TCHAR:
4798758Speter 		    case TSCAL:
48010362Smckusick 			    postcheck(p, p1);
48110362Smckusick 			    sconv(p2type(p1), p2type(p));
482773Speter 			    putop( P2ASSIGN , p2type( p ) );
483773Speter 			    putdot( filename , line );
4848758Speter 			    break;
4858758Speter 		    case TPTR:
4868758Speter 			    putop( P2ASSIGN , p2type( p ) );
4878758Speter 			    putdot( filename , line );
4888758Speter 			    break;
4898758Speter 		    case TDOUBLE:
49010362Smckusick 			    sconv(p2type(p1), p2type(p));
4918758Speter 			    putop( P2ASSIGN , p2type( p ) );
4928758Speter 			    putdot( filename , line );
4938758Speter 			    break;
4948758Speter 		    default:
49511854Speter 			    putstrop(P2STASG, ADDTYPE(p2type(p), P2PTR),
49615941Smckusick 					(int) lwidth(p), align(p));
497773Speter 			    putdot( filename , line );
4988758Speter 			    break;
4998758Speter 	    }
5008758Speter #	endif PC
501773Speter 	return (p);	/* Used by for statement */
502773Speter }
503773Speter 
504*15985Saoki #ifdef PC
505773Speter /*
506*15985Saoki  * assignment to conformant arrays.  Since these are variable length,
507*15985Saoki  *	we use blkcpy() to perform the assignment.
508*15985Saoki  *	blkcpy(rhs, lhs, (upper - lower + 1) * width)
509*15985Saoki  */
510*15985Saoki struct nl *
511*15985Saoki pcasgconf(r, p)
512*15985Saoki 	register ASG_NODE *r;
513*15985Saoki 	struct nl *p;
514*15985Saoki {
515*15985Saoki 	struct nl *p1;
516*15985Saoki 
517*15985Saoki 	if (r == (ASG_NODE *) TR_NIL || p == NLNIL)
518*15985Saoki 		return NLNIL;
519*15985Saoki 	putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR) , "_blkcpy" );
520*15985Saoki 	p1 = rvalue( r->rhs_expr , p , LREQ );
521*15985Saoki 	if (p1 == NLNIL)
522*15985Saoki 		return NLNIL;
523*15985Saoki 	p = lvalue( r->lhs_var , MOD|ASGN|NOUSE , LREQ );
524*15985Saoki 	if (p == NLNIL)
525*15985Saoki 		return NLNIL;
526*15985Saoki 	putop(P2LISTOP, P2INT);
527*15985Saoki 		/* upper bound */
528*15985Saoki 	p1 = p->chain->nptr[1];
529*15985Saoki 	putRV(p1->symbol, (p1->nl_block & 037), p1->value[0],
530*15985Saoki 	    p1->extra_flags, p2type( p1 ) );
531*15985Saoki 		/* minus lower bound */
532*15985Saoki 	p1 = p->chain->nptr[0];
533*15985Saoki 	putRV(p1->symbol, (p1->nl_block & 037), p1->value[0],
534*15985Saoki 	    p1->extra_flags, p2type( p1 ) );
535*15985Saoki 	putop( P2MINUS, P2INT );
536*15985Saoki 		/* add one */
537*15985Saoki 	putleaf(P2ICON, 1, 0, P2INT, 0);
538*15985Saoki 	putop( P2PLUS, P2INT );
539*15985Saoki 		/* and multiply by the width */
540*15985Saoki 	p1 = p->chain->nptr[2];
541*15985Saoki 	putRV(p1->symbol, (p1->nl_block & 037), p1->value[0],
542*15985Saoki 	    p1->extra_flags, p2type( p1 ) );
543*15985Saoki 	putop( P2MUL , P2INT );
544*15985Saoki 	putop(P2LISTOP, P2INT);
545*15985Saoki 	putop(P2CALL, P2INT);
546*15985Saoki 	putdot( filename , line);
547*15985Saoki 	return p;
548*15985Saoki }
549*15985Saoki #endif PC
550*15985Saoki 
551*15985Saoki /*
552773Speter  * if expr then stat [ else stat ]
553773Speter  */
55415941Smckusick ifop(if_n)
55515941Smckusick 	IF_NODE *if_n;
556773Speter {
557773Speter 	register struct nl *p;
558773Speter 	register l1, l2;	/* l1 is start of else, l2 is end of else */
5593079Smckusic 	int goc;
5603079Smckusic 	bool nr;
561773Speter 
562773Speter 	goc = gocnt;
563773Speter 	putline();
56415941Smckusick 	p = rvalue(if_n->cond_expr, NLNIL , RREQ );
565773Speter 	if (p == NIL) {
56615941Smckusick 		statement(if_n->then_stmnt);
56715941Smckusick 		noreach = FALSE;
56815941Smckusick 		statement(if_n->else_stmnt);
56915941Smckusick 		noreach = FALSE;
570773Speter 		return;
571773Speter 	}
572773Speter 	if (isnta(p, "b")) {
573773Speter 		error("Type of expression in if statement must be Boolean, not %s", nameof(p));
57415941Smckusick 		statement(if_n->then_stmnt);
57515941Smckusick 		noreach = FALSE;
57615941Smckusick 		statement(if_n->else_stmnt);
57715941Smckusick 		noreach = FALSE;
578773Speter 		return;
579773Speter 	}
580773Speter #	ifdef OBJ
5813079Smckusic 	    l1 = put(2, O_IF, getlab());
582773Speter #	endif OBJ
583773Speter #	ifdef PC
58415941Smckusick 	    l1 = (int) getlab();
58515941Smckusick 	    putleaf( P2ICON , l1 , 0 , P2INT , (char *) 0 );
586773Speter 	    putop( P2CBRANCH , P2INT );
587773Speter 	    putdot( filename , line );
588773Speter #	endif PC
589773Speter 	putcnt();
59015941Smckusick 	statement(if_n->then_stmnt);
591773Speter 	nr = noreach;
59215941Smckusick 	if (if_n->else_stmnt != TR_NIL) {
593773Speter 		/*
594773Speter 		 * else stat
595773Speter 		 */
596773Speter 		--level;
597773Speter 		ungoto();
598773Speter 		++level;
599773Speter #		ifdef OBJ
6003079Smckusic 		    l2 = put(2, O_TRA, getlab());
601773Speter #		endif OBJ
602773Speter #		ifdef PC
60315941Smckusick 		    l2 = (int) getlab();
60415941Smckusick 		    putjbr( (long) l2 );
605773Speter #		endif PC
60615941Smckusick 		patch((PTR_DCL)l1);
60715941Smckusick 		noreach = FALSE;
60815941Smckusick 		statement(if_n->else_stmnt);
60915941Smckusick 		noreach = (noreach && nr)?TRUE:FALSE;
610773Speter 		l1 = l2;
611773Speter 	} else
61215941Smckusick 		noreach = FALSE;
61315941Smckusick 	patch((PTR_DCL)l1);
614773Speter 	if (goc != gocnt)
615773Speter 		putcnt();
616773Speter }
617773Speter 
618773Speter /*
619773Speter  * while expr do stat
620773Speter  */
62115941Smckusick whilop(w_node)
62215941Smckusick 	WHI_CAS *w_node;
623773Speter {
624773Speter 	register struct nl *p;
62515941Smckusick 	register char *l1, *l2;
626773Speter 	int goc;
627773Speter 
628773Speter 	goc = gocnt;
62915941Smckusick 	l1 = getlab();
63015941Smckusick 	(void) putlab(l1);
631773Speter 	putline();
63215941Smckusick 	p = rvalue(w_node->expr, NLNIL , RREQ );
63315941Smckusick 	if (p == NLNIL) {
63415941Smckusick 		statement(w_node->stmnt_list);
63515941Smckusick 		noreach = FALSE;
636773Speter 		return;
637773Speter 	}
638773Speter 	if (isnta(p, "b")) {
639773Speter 		error("Type of expression in while statement must be Boolean, not %s", nameof(p));
64015941Smckusick 		statement(w_node->stmnt_list);
64115941Smckusick 		noreach = FALSE;
642773Speter 		return;
643773Speter 	}
644773Speter 	l2 = getlab();
645773Speter #	ifdef OBJ
64615941Smckusick 	    (void) put(2, O_IF, l2);
647773Speter #	endif OBJ
648773Speter #	ifdef PC
64915941Smckusick 	    putleaf( P2ICON , (int) l2 , 0 , P2INT , (char *) 0 );
650773Speter 	    putop( P2CBRANCH , P2INT );
651773Speter 	    putdot( filename , line );
652773Speter #	endif PC
653773Speter 	putcnt();
65415941Smckusick 	statement(w_node->stmnt_list);
655773Speter #	ifdef OBJ
65615941Smckusick 	    (void) put(2, O_TRA, l1);
657773Speter #	endif OBJ
658773Speter #	ifdef PC
65915941Smckusick 	    putjbr( (long) l1 );
660773Speter #	endif PC
66115941Smckusick 	patch((PTR_DCL) l2);
662773Speter 	if (goc != gocnt)
663773Speter 		putcnt();
664773Speter }
665773Speter 
666773Speter /*
667773Speter  * repeat stat* until expr
668773Speter  */
669773Speter repop(r)
67015941Smckusick 	REPEAT *r;
671773Speter {
672773Speter 	register struct nl *p;
673773Speter 	register l;
674773Speter 	int goc;
675773Speter 
676773Speter 	goc = gocnt;
67715941Smckusick 	l = (int) putlab(getlab());
678773Speter 	putcnt();
67915941Smckusick 	statlist(r->stmnt_list);
68015941Smckusick 	line = r->line_no;
68115941Smckusick 	p = rvalue(r->term_expr, NLNIL , RREQ );
68215941Smckusick 	if (p == NLNIL)
683773Speter 		return;
684773Speter 	if (isnta(p,"b")) {
685773Speter 		error("Until expression type must be Boolean, not %s, in repeat statement", nameof(p));
686773Speter 		return;
687773Speter 	}
688773Speter #	ifdef OBJ
68915941Smckusick 	    (void) put(2, O_IF, l);
690773Speter #	endif OBJ
691773Speter #	ifdef PC
69215941Smckusick 	    putleaf( P2ICON , l , 0 , P2INT , (char *) 0 );
693773Speter 	    putop( P2CBRANCH , P2INT );
694773Speter 	    putdot( filename , line );
695773Speter #	endif PC
696773Speter 	if (goc != gocnt)
697773Speter 		putcnt();
698773Speter }
699