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