xref: /csrg-svn/usr.bin/pascal/src/stat.c (revision 62217)
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