xref: /csrg-svn/usr.bin/f77/pass1.vax/exec.c (revision 25735)
122809Smckusick /*
222809Smckusick  * Copyright (c) 1980 Regents of the University of California.
322809Smckusick  * All rights reserved.  The Berkeley software License Agreement
422809Smckusick  * specifies the terms and conditions for redistribution.
522809Smckusick  */
622809Smckusick 
722809Smckusick #ifndef lint
8*25735Sdonn static char sccsid[] = "@(#)exec.c	5.5 (Berkeley) 01/07/86";
922809Smckusick #endif not lint
1022809Smckusick 
1122809Smckusick /*
1222809Smckusick  * exec.c
1322809Smckusick  *
1422809Smckusick  * Routines for handling the semantics of control structures.
1522809Smckusick  * F77 compiler, pass 1.
1622809Smckusick  *
1722809Smckusick  * University of Utah CS Dept modification history:
1822809Smckusick  *
1924476Sdonn  * $Log:	exec.c,v $
20*25735Sdonn  * Revision 5.6  85/12/20  19:42:46  donn
21*25735Sdonn  * Change style of error reporting in last fix.
22*25735Sdonn  *
23*25735Sdonn  * Revision 5.5  85/12/20  18:54:10  donn
24*25735Sdonn  * Complain about calls to things which aren't subroutines.
25*25735Sdonn  *
26*25735Sdonn  * Revision 5.4  85/12/18  19:57:58  donn
27*25735Sdonn  * Assignment statements are executable statements -- advance the magic
28*25735Sdonn  * parser state to forbid DATA statements and statement functions.
29*25735Sdonn  *
30*25735Sdonn  * Revision 5.3  85/11/25  00:23:49  donn
31*25735Sdonn  * 4.3 beta
32*25735Sdonn  *
3324476Sdonn  * Revision 5.2  85/08/10  04:07:36  donn
3424476Sdonn  * Changed an error message to correct spelling and be more accurate.
3524476Sdonn  * From Jerry Berkman.
3624476Sdonn  *
3722809Smckusick  * Revision 2.3  85/03/18  08:03:31  donn
3822809Smckusick  * Hacks for conversions from type address to numeric type -- prevent addresses
3922809Smckusick  * from being stored in shorts and prevent warnings about implicit conversions.
4022809Smckusick  *
4122809Smckusick  * Revision 2.2  84/09/03  23:18:30  donn
4222809Smckusick  * When a DO loop had the same variable as its loop variable and its limit,
4322809Smckusick  * the limit temporary was assigned to AFTER the original value of the variable
4422809Smckusick  * was destroyed by assigning the initial value to the loop variable.  I
4522809Smckusick  * swapped the operands of a comparison and changed the direction of the
4622809Smckusick  * operator...  This only affected programs when optimizing.  (This may not
4722809Smckusick  * be enough if something alters the order of evaluation of side effects
4822809Smckusick  * later on... sigh.)
4922809Smckusick  *
5022809Smckusick  * Revision 2.1  84/07/19  12:02:53  donn
5122809Smckusick  * Changed comment headers for UofU.
5222809Smckusick  *
5322809Smckusick  * Revision 1.3  84/07/12  18:35:12  donn
5422809Smckusick  * Added change to enddo() to detect open 'if' blocks at the ends of loops.
5522809Smckusick  *
5622809Smckusick  * Revision 1.2  84/06/08  11:22:53  donn
5722809Smckusick  * Fixed bug in exdo() -- if a loop parameter contained an instance of the loop
5822809Smckusick  * variable and the optimizer was off, the loop variable got converted to
5922809Smckusick  * register before the parameters were processed and so the loop parameters
6022809Smckusick  * were initialized from garbage in the register instead of the memory version
6122809Smckusick  * of the loop variable.
6222809Smckusick  *
6322809Smckusick  */
6422809Smckusick 
6522809Smckusick #include "defs.h"
6622809Smckusick #include "optim.h"
6722809Smckusick 
6822809Smckusick 
6922809Smckusick /*   Logical IF codes
7022809Smckusick */
7122809Smckusick 
7222809Smckusick 
7322809Smckusick exif(p)
7422809Smckusick expptr p;
7522809Smckusick {
7622809Smckusick register int k;
7722809Smckusick pushctl(CTLIF);
7822809Smckusick ctlstack->elselabel = newlabel();
7922809Smckusick 
8022809Smckusick if( ( k = (p = fixtype(p))->headblock.vtype) != TYLOGICAL)
8122809Smckusick 	{
8222809Smckusick 	if(k != TYERROR)
8322809Smckusick 		err("non-logical expression in IF statement");
8422809Smckusick 	frexpr(p);
8522809Smckusick 	}
8622809Smckusick else if (optimflag)
8722809Smckusick 	optbuff (SKIFN, p, ctlstack->elselabel, 0);
8822809Smckusick else
8922809Smckusick 	putif (p, ctlstack->elselabel);
9022809Smckusick }
9122809Smckusick 
9222809Smckusick 
9322809Smckusick 
9422809Smckusick exelif(p)
9522809Smckusick expptr p;
9622809Smckusick {
9722809Smckusick int k,oldelse;
9822809Smckusick 
9922809Smckusick if( ( k = (p = fixtype(p))->headblock.vtype) != TYLOGICAL)
10022809Smckusick 	{
10122809Smckusick 	if(k != TYERROR)
10222809Smckusick 		err("non-logical expression in IF statement");
10322809Smckusick 	frexpr(p);
10422809Smckusick 	}
10522809Smckusick else    {
10622809Smckusick         if(ctlstack->ctltype == CTLIF)
10722809Smckusick 		{
10822809Smckusick 		if(ctlstack->endlabel == 0) ctlstack->endlabel = newlabel();
10922809Smckusick         	oldelse=ctlstack->elselabel;
11022809Smckusick 		ctlstack->elselabel = newlabel();
11122809Smckusick 		if (optimflag)
11222809Smckusick 			{
11322809Smckusick 			optbuff (SKGOTO, 0, ctlstack->endlabel, 0);
11422809Smckusick 			optbuff (SKLABEL, 0, oldelse, 0);
11522809Smckusick 			optbuff (SKIFN, p, ctlstack->elselabel, 0);
11622809Smckusick 			}
11722809Smckusick 		else
11822809Smckusick 			{
11922809Smckusick 			putgoto (ctlstack->endlabel);
12022809Smckusick 			putlabel (oldelse);
12122809Smckusick 			putif (p, ctlstack->elselabel);
12222809Smckusick 			}
12322809Smckusick 		}
12422809Smckusick         else	execerr("elseif out of place", CNULL);
12522809Smckusick         }
12622809Smckusick }
12722809Smckusick 
12822809Smckusick 
12922809Smckusick 
13022809Smckusick 
13122809Smckusick 
13222809Smckusick exelse()
13322809Smckusick {
13422809Smckusick if(ctlstack->ctltype==CTLIF)
13522809Smckusick 	{
13622809Smckusick 	if(ctlstack->endlabel == 0)
13722809Smckusick 		ctlstack->endlabel = newlabel();
13822809Smckusick 	ctlstack->ctltype = CTLELSE;
13922809Smckusick 	if (optimflag)
14022809Smckusick 		{
14122809Smckusick 		optbuff (SKGOTO, 0, ctlstack->endlabel, 0);
14222809Smckusick 		optbuff (SKLABEL, 0, ctlstack->elselabel, 0);
14322809Smckusick 		}
14422809Smckusick 	else
14522809Smckusick 		{
14622809Smckusick 		putgoto (ctlstack->endlabel);
14722809Smckusick 		putlabel (ctlstack->elselabel);
14822809Smckusick 		}
14922809Smckusick 	}
15022809Smckusick 
15122809Smckusick else	execerr("else out of place", CNULL);
15222809Smckusick }
15322809Smckusick 
15422809Smckusick 
15522809Smckusick exendif()
15622809Smckusick {
15722809Smckusick if (ctlstack->ctltype == CTLIF)
15822809Smckusick 	{
15922809Smckusick 	if (optimflag)
16022809Smckusick 		{
16122809Smckusick 		optbuff (SKLABEL, 0, ctlstack->elselabel, 0);
16222809Smckusick 		if (ctlstack->endlabel)
16322809Smckusick 			optbuff (SKLABEL, 0, ctlstack->endlabel, 0);
16422809Smckusick 		}
16522809Smckusick 	else
16622809Smckusick 		{
16722809Smckusick 		putlabel (ctlstack->elselabel);
16822809Smckusick 		if (ctlstack->endlabel)
16922809Smckusick 			putlabel (ctlstack->endlabel);
17022809Smckusick 		}
17122809Smckusick 	popctl ();
17222809Smckusick 	}
17322809Smckusick else if (ctlstack->ctltype == CTLELSE)
17422809Smckusick 	{
17522809Smckusick 	if (optimflag)
17622809Smckusick 		optbuff (SKLABEL, 0, ctlstack->endlabel, 0);
17722809Smckusick 	else
17822809Smckusick 		putlabel (ctlstack->endlabel);
17922809Smckusick 	popctl ();
18022809Smckusick 	}
18122809Smckusick else
18222809Smckusick 	execerr("endif out of place", CNULL);
18322809Smckusick }
18422809Smckusick 
18522809Smckusick 
18622809Smckusick 
18722809Smckusick LOCAL pushctl(code)
18822809Smckusick int code;
18922809Smckusick {
19022809Smckusick register int i;
19122809Smckusick 
19222809Smckusick /* fprintf(diagfile,"old blklevel %d \n",blklevel); dmpframe(ctlstack); */
19322809Smckusick if(++ctlstack >= lastctl)
19422809Smckusick 	many("loops or if-then-elses", 'c');
19522809Smckusick ctlstack->ctltype = code;
19622809Smckusick for(i = 0 ; i < 4 ; ++i)
19722809Smckusick 	ctlstack->ctlabels[i] = 0;
19822809Smckusick ++blklevel;
19922809Smckusick }
20022809Smckusick 
20122809Smckusick 
20222809Smckusick LOCAL popctl()
20322809Smckusick {
20422809Smckusick if( ctlstack-- < ctls )
20522809Smckusick 	fatal("control stack empty");
20622809Smckusick --blklevel;
20722809Smckusick }
20822809Smckusick 
20922809Smckusick 
21022809Smckusick 
21122809Smckusick LOCAL poplab()
21222809Smckusick {
21322809Smckusick register struct Labelblock  *lp;
21422809Smckusick 
21522809Smckusick for(lp = labeltab ; lp < highlabtab ; ++lp)
21622809Smckusick 	if(lp->labdefined)
21722809Smckusick 		{
21822809Smckusick 		/* mark all labels in inner blocks unreachable */
21922809Smckusick 		if(lp->blklevel > blklevel)
22022809Smckusick 			lp->labinacc = YES;
22122809Smckusick 		}
22222809Smckusick 	else if(lp->blklevel > blklevel)
22322809Smckusick 		{
22422809Smckusick 		/* move all labels referred to in inner blocks out a level */
22522809Smckusick 		lp->blklevel = blklevel;
22622809Smckusick 		}
22722809Smckusick }
22822809Smckusick 
22922809Smckusick 
23022809Smckusick 
23122809Smckusick /*  BRANCHING CODE
23222809Smckusick */
23322809Smckusick 
23422809Smckusick exgoto(lab)
23522809Smckusick struct Labelblock *lab;
23622809Smckusick {
23722809Smckusick if (optimflag)
23822809Smckusick 	optbuff (SKGOTO, 0, lab->labelno, 0);
23922809Smckusick else
24022809Smckusick 	putgoto (lab->labelno);
24122809Smckusick }
24222809Smckusick 
24322809Smckusick 
24422809Smckusick 
24522809Smckusick 
24622809Smckusick 
24722809Smckusick 
24822809Smckusick 
24922809Smckusick exequals(lp, rp)
25022809Smckusick register struct Primblock *lp;
25122809Smckusick register expptr rp;
25222809Smckusick {
25322809Smckusick register Namep np;
25422809Smckusick 
25522809Smckusick if(lp->tag != TPRIM)
25622809Smckusick 	{
25722809Smckusick 	err("assignment to a non-variable");
25822809Smckusick 	frexpr(lp);
25922809Smckusick 	frexpr(rp);
26022809Smckusick 	}
26122809Smckusick else if(lp->namep->vclass!=CLVAR && lp->argsp)
26222809Smckusick 	{
26322809Smckusick 	if(parstate >= INEXEC)
26424476Sdonn 		err("undimensioned array or statement function out of order");
26522809Smckusick 	else
26622809Smckusick 		mkstfunct(lp, rp);
26722809Smckusick 	}
26822809Smckusick else
26922809Smckusick 	{
27022809Smckusick 	np = (Namep) lp->namep;
27122809Smckusick 	if (np->vclass == CLPROC && np->vprocclass == PTHISPROC
27222809Smckusick 		&& proctype == TYSUBR)
27322809Smckusick 		{
27422809Smckusick 		err("assignment to a subroutine name");
27522809Smckusick 		return;
27622809Smckusick 		}
27722809Smckusick 	if(parstate < INDATA)
27822809Smckusick 		enddcl();
279*25735Sdonn 	parstate = INEXEC;
28022809Smckusick 	if (optimflag)
28122809Smckusick 		optbuff (SKEQ, mkexpr(OPASSIGN, mklhs(lp), fixtype(rp)), 0, 0);
28222809Smckusick 	else
28322809Smckusick 		puteq (mklhs(lp), fixtype(rp));
28422809Smckusick 	}
28522809Smckusick }
28622809Smckusick 
28722809Smckusick 
28822809Smckusick 
28922809Smckusick mkstfunct(lp, rp)
29022809Smckusick struct Primblock *lp;
29122809Smckusick expptr rp;
29222809Smckusick {
29322809Smckusick register struct Primblock *p;
29422809Smckusick register Namep np;
29522809Smckusick chainp args;
29622809Smckusick 
29722809Smckusick if(parstate < INDATA)
29822809Smckusick 	{
29922809Smckusick 	enddcl();
30022809Smckusick 	parstate = INDATA;
30122809Smckusick 	}
30222809Smckusick 
30322809Smckusick np = lp->namep;
30422809Smckusick if(np->vclass == CLUNKNOWN)
30522809Smckusick 	np->vclass = CLPROC;
30622809Smckusick else
30722809Smckusick 	{
30822809Smckusick 	dclerr("redeclaration of statement function", np);
30922809Smckusick 	return;
31022809Smckusick 	}
31122809Smckusick np->vprocclass = PSTFUNCT;
31222809Smckusick np->vstg = STGSTFUNCT;
31322809Smckusick impldcl(np);
31422809Smckusick args = (lp->argsp ? lp->argsp->listp : CHNULL);
31522809Smckusick np->varxptr.vstfdesc = mkchain(args , rp );
31622809Smckusick 
31722809Smckusick for( ; args ; args = args->nextp)
31822809Smckusick 	if( args->datap->tag!=TPRIM ||
31922809Smckusick 		(p = (struct Primblock *) (args->datap) )->argsp ||
32022809Smckusick 		p->fcharp || p->lcharp )
32122809Smckusick 		err("non-variable argument in statement function definition");
32222809Smckusick 	else
32322809Smckusick 		{
32422809Smckusick 		args->datap = (tagptr) (p->namep);
32522809Smckusick 		vardcl(p->namep);
32622809Smckusick 		free(p);
32722809Smckusick 		}
32822809Smckusick }
32922809Smckusick 
33022809Smckusick 
33122809Smckusick 
33222809Smckusick excall(name, args, nstars, labels)
33322809Smckusick Namep name;
33422809Smckusick struct Listblock *args;
33522809Smckusick int nstars;
33622809Smckusick struct Labelblock *labels[ ];
33722809Smckusick {
33822809Smckusick register expptr p;
33922809Smckusick 
340*25735Sdonn if (name->vdcldone)
341*25735Sdonn 	if (name->vclass != CLPROC && name->vclass != CLENTRY)
342*25735Sdonn 		{
343*25735Sdonn 		dclerr("call to non-subroutine", name);
344*25735Sdonn 		return;
345*25735Sdonn 		}
346*25735Sdonn 	else if (name->vtype != TYSUBR)
347*25735Sdonn 		{
348*25735Sdonn 		dclerr("subroutine invocation of function", name);
349*25735Sdonn 		return;
350*25735Sdonn 		}
35122809Smckusick settype(name, TYSUBR, ENULL);
35222809Smckusick p = mkfunct( mkprim(name, args, CHNULL) );
35322809Smckusick p->exprblock.vtype = p->exprblock.leftp->headblock.vtype = TYINT;
35422809Smckusick if (nstars > 0)
35522809Smckusick 	if (optimflag)
35622809Smckusick 		optbuff (SKCMGOTO, p, nstars, labels);
35722809Smckusick 	else
35822809Smckusick 		putcmgo (p, nstars, labels);
35922809Smckusick else
36022809Smckusick 	if (optimflag)
36122809Smckusick 		optbuff (SKCALL, p, 0, 0);
36222809Smckusick 	else
36322809Smckusick 		putexpr (p);
36422809Smckusick }
36522809Smckusick 
36622809Smckusick 
36722809Smckusick 
36822809Smckusick exstop(stop, p)
36922809Smckusick int stop;
37022809Smckusick register expptr p;
37122809Smckusick {
37222809Smckusick char *q;
37322809Smckusick int n;
37422809Smckusick expptr mkstrcon();
37522809Smckusick 
37622809Smckusick if(p)
37722809Smckusick 	{
37822809Smckusick 	if( ! ISCONST(p) )
37922809Smckusick 		{
38022809Smckusick 		execerr("pause/stop argument must be constant", CNULL);
38122809Smckusick 		frexpr(p);
38222809Smckusick 		p = mkstrcon(0, CNULL);
38322809Smckusick 		}
38422809Smckusick 	else if( ISINT(p->constblock.vtype) )
38522809Smckusick 		{
38622809Smckusick 		q = convic(p->constblock.const.ci);
38722809Smckusick 		n = strlen(q);
38822809Smckusick 		if(n > 0)
38922809Smckusick 			{
39022809Smckusick 			p->constblock.const.ccp = copyn(n, q);
39122809Smckusick 			p->constblock.vtype = TYCHAR;
39222809Smckusick 			p->constblock.vleng = (expptr) ICON(n);
39322809Smckusick 			}
39422809Smckusick 		else
39522809Smckusick 			p = (expptr) mkstrcon(0, CNULL);
39622809Smckusick 		}
39722809Smckusick 	else if(p->constblock.vtype != TYCHAR)
39822809Smckusick 		{
39922809Smckusick 		execerr("pause/stop argument must be integer or string", CNULL);
40022809Smckusick 		p = (expptr) mkstrcon(0, CNULL);
40122809Smckusick 		}
40222809Smckusick 	}
40322809Smckusick else	p = (expptr) mkstrcon(0, CNULL);
40422809Smckusick 
40522809Smckusick if (optimflag)
40622809Smckusick 	optbuff ((stop ? SKSTOP : SKPAUSE), p, 0, 0);
40722809Smckusick else
40822809Smckusick 	putexpr (call1(TYSUBR, (stop ? "s_stop" : "s_paus"), p));
40922809Smckusick }
41022809Smckusick 
41122809Smckusick 
41222809Smckusick /* UCB DO LOOP CODE */
41322809Smckusick 
41422809Smckusick #define DOINIT	par[0]
41522809Smckusick #define DOLIMIT	par[1]
41622809Smckusick #define DOINCR	par[2]
41722809Smckusick 
41822809Smckusick #define CONSTINIT  const[0]
41922809Smckusick #define CONSTLIMIT const[1]
42022809Smckusick #define CONSTINCR  const[2]
42122809Smckusick 
42222809Smckusick #define VARSTEP	0
42322809Smckusick #define POSSTEP	1
42422809Smckusick #define NEGSTEP	2
42522809Smckusick 
42622809Smckusick 
42722809Smckusick exdo(range, spec)
42822809Smckusick int range;
42922809Smckusick chainp spec;
43022809Smckusick 
43122809Smckusick {
43222809Smckusick   register expptr p, q;
43322809Smckusick   expptr q1;
43422809Smckusick   register Namep np;
43522809Smckusick   chainp cp;
43622809Smckusick   register int i;
43722809Smckusick   int dotype, incsign;
43822809Smckusick   Addrp dovarp, dostgp;
43922809Smckusick   expptr par[3];
44022809Smckusick   expptr const[3];
44122809Smckusick   Slotp doslot;
44222809Smckusick 
44322809Smckusick   pushctl(CTLDO);
44422809Smckusick   dorange = ctlstack->dolabel = range;
44522809Smckusick   np = (Namep) (spec->datap);
44622809Smckusick   ctlstack->donamep = NULL;
44722809Smckusick   if(np->vdovar)
44822809Smckusick     {
44922809Smckusick       errstr("nested loops with variable %s", varstr(VL,np->varname));
45022809Smckusick       return;
45122809Smckusick     }
45222809Smckusick 
45322809Smckusick   dovarp = mkplace(np);
45422809Smckusick   dotype = dovarp->vtype;
45522809Smckusick 
45622809Smckusick   if( ! ONEOF(dotype, MSKINT|MSKREAL) )
45722809Smckusick     {
45822809Smckusick       err("bad type on DO variable");
45922809Smckusick       return;
46022809Smckusick     }
46122809Smckusick 
46222809Smckusick 
46322809Smckusick   for(i=0 , cp = spec->nextp ; cp!=NULL && i<3 ; cp = cp->nextp)
46422809Smckusick     {
46522809Smckusick       p = fixtype((expptr) cpexpr((tagptr) q = cp->datap));
46622809Smckusick       if(!ONEOF(p->headblock.vtype, MSKINT|MSKREAL) )
46722809Smckusick 	{
46822809Smckusick 	  err("bad type on DO parameter");
46922809Smckusick 	  return;
47022809Smckusick 	}
47122809Smckusick 
47222809Smckusick 
47322809Smckusick       if (ISCONST(q))
47422809Smckusick 	const[i] = mkconv(dotype, q);
47522809Smckusick       else
47622809Smckusick 	{
47722809Smckusick 	  frexpr(q);
47822809Smckusick 	  const[i] = NULL;
47922809Smckusick 	}
48022809Smckusick 
48122809Smckusick       par[i++] = mkconv(dotype, p);
48222809Smckusick     }
48322809Smckusick 
48422809Smckusick   frchain(&spec);
48522809Smckusick   switch(i)
48622809Smckusick     {
48722809Smckusick     case 0:
48822809Smckusick     case 1:
48922809Smckusick       err("too few DO parameters");
49022809Smckusick       return;
49122809Smckusick 
49222809Smckusick     case 2:
49322809Smckusick       DOINCR = (expptr) ICON(1);
49422809Smckusick       CONSTINCR = ICON(1);
49522809Smckusick 
49622809Smckusick     case 3:
49722809Smckusick       break;
49822809Smckusick 
49922809Smckusick     default:
50022809Smckusick       err("too many DO parameters");
50122809Smckusick       return;
50222809Smckusick     }
50322809Smckusick 
50422809Smckusick   ctlstack->donamep = np;
50522809Smckusick 
50622809Smckusick   np->vdovar = YES;
50722809Smckusick   if( !optimflag && enregister(np) )
50822809Smckusick     {
50922809Smckusick       /* stgp points to a storage version, varp to a register version */
51022809Smckusick       dostgp = dovarp;
51122809Smckusick       dovarp = mkplace(np);
51222809Smckusick     }
51322809Smckusick   else
51422809Smckusick     dostgp = NULL;
51522809Smckusick 
51622809Smckusick   for (i = 0; i < 4; i++)
51722809Smckusick     ctlstack->ctlabels[i] = newlabel();
51822809Smckusick 
51922809Smckusick   if( CONSTLIMIT )
52022809Smckusick     ctlstack->domax = DOLIMIT;
52122809Smckusick   else
52222809Smckusick     ctlstack->domax = (expptr) mktemp(dotype, PNULL);
52322809Smckusick 
52422809Smckusick   if( CONSTINCR )
52522809Smckusick     {
52622809Smckusick       ctlstack->dostep = DOINCR;
52722809Smckusick       if( (incsign = conssgn(CONSTINCR)) == 0)
52822809Smckusick 	err("zero DO increment");
52922809Smckusick       ctlstack->dostepsign = (incsign > 0 ? POSSTEP : NEGSTEP);
53022809Smckusick     }
53122809Smckusick   else
53222809Smckusick     {
53322809Smckusick       ctlstack->dostep = (expptr) mktemp(dotype, PNULL);
53422809Smckusick       ctlstack->dostepsign = VARSTEP;
53522809Smckusick     }
53622809Smckusick 
53722809Smckusick if (optimflag)
53822809Smckusick 	doslot = optbuff (SKDOHEAD,0,0,ctlstack);
53922809Smckusick 
54022809Smckusick if( CONSTLIMIT && CONSTINIT && ctlstack->dostepsign!=VARSTEP)
54122809Smckusick 	{
54222809Smckusick 	if (optimflag)
54322809Smckusick 		optbuff (SKEQ,mkexpr(OPASSIGN,cpexpr(dovarp),cpexpr(DOINIT)),
54422809Smckusick 			0,0);
54522809Smckusick 	else
54622809Smckusick 		puteq (cpexpr(dovarp), cpexpr(DOINIT));
54722809Smckusick 	if( ! onetripflag )
54822809Smckusick 		{
54922809Smckusick 		q = mkexpr(OPMINUS, cpexpr(CONSTLIMIT), cpexpr(CONSTINIT));
55022809Smckusick 		if((incsign * conssgn(q)) == -1)
55122809Smckusick 			{
55222809Smckusick 			warn("DO range never executed");
55322809Smckusick 			if (optimflag)
55422809Smckusick 				optbuff (SKGOTO,0,ctlstack->endlabel,0);
55522809Smckusick 			else
55622809Smckusick 				putgoto (ctlstack->endlabel);
55722809Smckusick 			}
55822809Smckusick 		frexpr(q);
55922809Smckusick 		}
56022809Smckusick 	}
56122809Smckusick 
56222809Smckusick 
56322809Smckusick else if (ctlstack->dostepsign != VARSTEP && !onetripflag)
56422809Smckusick 	{
56522809Smckusick 	if (CONSTLIMIT)
56622809Smckusick 		q = (expptr) cpexpr(ctlstack->domax);
56722809Smckusick 	else
56822809Smckusick 		q = mkexpr(OPASSIGN, cpexpr(ctlstack->domax), DOLIMIT);
56922809Smckusick 	q1 = mkexpr(OPASSIGN, cpexpr(dovarp), DOINIT);
57022809Smckusick 	q = mkexpr( (ctlstack->dostepsign == POSSTEP ? OPGE : OPLE),
57122809Smckusick 		   q, q1);
57222809Smckusick 	if (optimflag)
57322809Smckusick 		optbuff (SKIFN,q, ctlstack->endlabel,0);
57422809Smckusick 	else
57522809Smckusick 		putif (q, ctlstack->endlabel);
57622809Smckusick 	}
57722809Smckusick else
57822809Smckusick 	{
57922809Smckusick 	if (!CONSTLIMIT)
58022809Smckusick 	    if (optimflag)
58122809Smckusick 		optbuff (SKEQ,
58222809Smckusick 			mkexpr(OPASSIGN,cpexpr(ctlstack->domax),DOLIMIT),0,0);
58322809Smckusick 	    else
58422809Smckusick 		puteq (cpexpr(ctlstack->domax), DOLIMIT);
58522809Smckusick 	q = DOINIT;
58622809Smckusick 	if (!onetripflag)
58722809Smckusick 		q = mkexpr(OPMINUS, q,
58822809Smckusick 			mkexpr(OPASSIGN, cpexpr(ctlstack->dostep),
58922809Smckusick 			       DOINCR) );
59022809Smckusick 	if (optimflag)
59122809Smckusick 		optbuff (SKEQ,mkexpr(OPASSIGN,cpexpr(dovarp), q),0,0);
59222809Smckusick 	else
59322809Smckusick 		puteq (cpexpr(dovarp), q);
59422809Smckusick 	if (onetripflag && ctlstack->dostepsign == VARSTEP)
59522809Smckusick 	    if (optimflag)
59622809Smckusick 		optbuff (SKEQ,
59722809Smckusick 			mkexpr(OPASSIGN,cpexpr(ctlstack->dostep),DOINCR),0,0);
59822809Smckusick 	    else
59922809Smckusick 		puteq (cpexpr(ctlstack->dostep), DOINCR);
60022809Smckusick 	}
60122809Smckusick 
60222809Smckusick if (ctlstack->dostepsign == VARSTEP)
60322809Smckusick 	{
60422809Smckusick 	expptr incr,test;
60522809Smckusick 	if (onetripflag)
60622809Smckusick 		if (optimflag)
60722809Smckusick 			optbuff (SKGOTO,0,ctlstack->dobodylabel,0);
60822809Smckusick 		else
60922809Smckusick 			putgoto (ctlstack->dobodylabel);
61022809Smckusick 	else
61122809Smckusick 	    if (optimflag)
61222809Smckusick 		optbuff (SKIFN,mkexpr(OPGE, cpexpr(ctlstack->dostep), ICON(0)),
61322809Smckusick 			ctlstack->doneglabel,0);
61422809Smckusick 	    else
61522809Smckusick 		putif (mkexpr(OPGE, cpexpr(ctlstack->dostep), ICON(0)),
61622809Smckusick 			ctlstack->doneglabel);
61722809Smckusick 	if (optimflag)
61822809Smckusick 		optbuff (SKLABEL,0,ctlstack->doposlabel,0);
61922809Smckusick 	else
62022809Smckusick 		putlabel (ctlstack->doposlabel);
62122809Smckusick 	incr = mkexpr(OPPLUSEQ, cpexpr(dovarp), cpexpr(ctlstack->dostep));
62222809Smckusick 	test = mkexpr(OPLE, incr, cpexpr(ctlstack->domax));
62322809Smckusick 	if (optimflag)
62422809Smckusick 		optbuff (SKIFN,test, ctlstack->endlabel,0);
62522809Smckusick 	else
62622809Smckusick 		putif (test, ctlstack->endlabel);
62722809Smckusick 	}
62822809Smckusick 
62922809Smckusick if (optimflag)
63022809Smckusick 	optbuff (SKLABEL,0,ctlstack->dobodylabel,0);
63122809Smckusick else
63222809Smckusick 	putlabel (ctlstack->dobodylabel);
63322809Smckusick if (dostgp)
63422809Smckusick 	{
63522809Smckusick 	if (optimflag)
63622809Smckusick 		optbuff (SKEQ,mkexpr(OPASSIGN,dostgp, dovarp),0,0);
63722809Smckusick 	else
63822809Smckusick 		puteq (dostgp, dovarp);
63922809Smckusick 	}
64022809Smckusick else
64122809Smckusick 	frexpr(dovarp);
64222809Smckusick if (optimflag)
64322809Smckusick 	doslot->nullslot = optbuff (SKNULL,0,0,0);
64422809Smckusick 
64522809Smckusick frexpr(CONSTINIT);
64622809Smckusick frexpr(CONSTLIMIT);
64722809Smckusick frexpr(CONSTINCR);
64822809Smckusick }
64922809Smckusick 
65022809Smckusick 
65122809Smckusick enddo(here)
65222809Smckusick int here;
65322809Smckusick 
65422809Smckusick {
65522809Smckusick   register struct Ctlframe *q;
65622809Smckusick   Namep np;
65722809Smckusick   Addrp ap, rv;
65822809Smckusick   expptr t;
65922809Smckusick   register int i;
66022809Smckusick   Slotp doslot;
66122809Smckusick 
66222809Smckusick   while (here == dorange)
66322809Smckusick     {
66422809Smckusick       while (ctlstack->ctltype == CTLIF || ctlstack->ctltype == CTLELSE)
66522809Smckusick 	{
66622809Smckusick 	  execerr("missing endif", CNULL);
66722809Smckusick 	  exendif();
66822809Smckusick 	}
66922809Smckusick 
67022809Smckusick       if (np = ctlstack->donamep)
67122809Smckusick 	{
67222809Smckusick 	rv = mkplace (np);
67322809Smckusick 
67422809Smckusick 	t = mkexpr(OPPLUSEQ, cpexpr(rv), cpexpr(ctlstack->dostep) );
67522809Smckusick 
67622809Smckusick 	if (optimflag)
67722809Smckusick 		doslot = optbuff (SKENDDO,0,0,ctlstack);
67822809Smckusick 
67922809Smckusick 	if (ctlstack->dostepsign == VARSTEP)
68022809Smckusick 		if (optimflag)
68122809Smckusick 			{
68222809Smckusick 			optbuff (SKIFN,
68322809Smckusick 				mkexpr(OPLE, cpexpr(ctlstack->dostep), ICON(0)),
68422809Smckusick 				ctlstack->doposlabel,0);
68522809Smckusick 			optbuff (SKLABEL,0,ctlstack->doneglabel,0);
68622809Smckusick 			optbuff (SKIFN,mkexpr(OPLT, t, ctlstack->domax),
68722809Smckusick 				ctlstack->dobodylabel,0);
68822809Smckusick 			}
68922809Smckusick 		else
69022809Smckusick 			{
69122809Smckusick 			putif (mkexpr(OPLE, cpexpr(ctlstack->dostep), ICON(0)),
69222809Smckusick 				ctlstack->doposlabel);
69322809Smckusick 			putlabel (ctlstack->doneglabel);
69422809Smckusick 			putif (mkexpr(OPLT, t, ctlstack->domax),
69522809Smckusick 				ctlstack->dobodylabel);
69622809Smckusick 			}
69722809Smckusick 	else
69822809Smckusick 		{
69922809Smckusick 		int op;
70022809Smckusick 		op = (ctlstack->dostepsign == POSSTEP ? OPGT : OPLT);
70122809Smckusick 		if (optimflag)
70222809Smckusick 			optbuff (SKIFN, mkexpr(op,t,ctlstack->domax),
70322809Smckusick 				ctlstack->dobodylabel,0);
70422809Smckusick 		else
70522809Smckusick 			putif (mkexpr(op, t, ctlstack->domax),
70622809Smckusick 				ctlstack->dobodylabel);
70722809Smckusick 		}
70822809Smckusick 	if (optimflag)
70922809Smckusick 		optbuff (SKLABEL,0,ctlstack->endlabel,0);
71022809Smckusick 	else
71122809Smckusick 		putlabel (ctlstack->endlabel);
71222809Smckusick 
71322809Smckusick 	if (ap = memversion(np))
71422809Smckusick 		{
71522809Smckusick 		if (optimflag)
71622809Smckusick 			optbuff (SKEQ,mkexpr(OPASSIGN,ap, rv),0,0);
71722809Smckusick 		else
71822809Smckusick 			puteq (ap, rv);
71922809Smckusick 		}
72022809Smckusick 	else
72122809Smckusick 		frexpr(rv);
72222809Smckusick 	for (i = 0; i < 4; i++)
72322809Smckusick 		ctlstack->ctlabels[i] = 0;
72422809Smckusick 	if (!optimflag)
72522809Smckusick 		deregister(ctlstack->donamep);
72622809Smckusick 	ctlstack->donamep->vdovar = NO;
72722809Smckusick 	if (optimflag)
72822809Smckusick 		doslot->nullslot = optbuff (SKNULL,0,0,0);
72922809Smckusick 	}
73022809Smckusick 
73122809Smckusick       popctl();
73222809Smckusick       poplab();
73322809Smckusick 
73422809Smckusick       dorange = 0;
73522809Smckusick       for (q = ctlstack; q >= ctls; --q)
73622809Smckusick 	if (q->ctltype == CTLDO)
73722809Smckusick 	  {
73822809Smckusick 	    dorange = q->dolabel;
73922809Smckusick 	    break;
74022809Smckusick 	  }
74122809Smckusick     }
74222809Smckusick }
74322809Smckusick 
74422809Smckusick 
74522809Smckusick exassign(vname, labelval)
74622809Smckusick Namep vname;
74722809Smckusick struct Labelblock *labelval;
74822809Smckusick {
74922809Smckusick Addrp p;
75022809Smckusick expptr mkaddcon();
75122809Smckusick 
75222809Smckusick p = mkplace(vname);
75322809Smckusick #if SZADDR > SZSHORT
75422809Smckusick if( p->vtype == TYSHORT )
75522809Smckusick 	err("insufficient precision in ASSIGN variable");
75622809Smckusick else
75722809Smckusick #endif
75822809Smckusick if( ! ONEOF(p->vtype, MSKINT|MSKADDR) )
75922809Smckusick 	err("noninteger assign variable");
76022809Smckusick else
76122809Smckusick 	{
76222809Smckusick 	if (optimflag)
76322809Smckusick 		optbuff (SKASSIGN, p, labelval->labelno, 0);
76422809Smckusick 	else
76522809Smckusick 		puteq (p, intrconv(p->vtype, mkaddcon(labelval->labelno)));
76622809Smckusick 	}
76722809Smckusick }
76822809Smckusick 
76922809Smckusick 
77022809Smckusick 
77122809Smckusick exarif(expr, neglab, zerlab, poslab)
77222809Smckusick expptr expr;
77322809Smckusick struct Labelblock *neglab, *zerlab, *poslab;
77422809Smckusick {
77522809Smckusick register int lm, lz, lp;
77622809Smckusick struct Labelblock *labels[3];
77722809Smckusick 
77822809Smckusick lm = neglab->labelno;
77922809Smckusick lz = zerlab->labelno;
78022809Smckusick lp = poslab->labelno;
78122809Smckusick expr = fixtype(expr);
78222809Smckusick 
78322809Smckusick if( ! ONEOF(expr->headblock.vtype, MSKINT|MSKREAL) )
78422809Smckusick 	{
78522809Smckusick 	err("invalid type of arithmetic if expression");
78622809Smckusick 	frexpr(expr);
78722809Smckusick 	}
78822809Smckusick else
78922809Smckusick 	{
79022809Smckusick 	if(lm == lz)
79122809Smckusick 		exar2(OPLE, expr, lm, lp);
79222809Smckusick 	else if(lm == lp)
79322809Smckusick 		exar2(OPNE, expr, lm, lz);
79422809Smckusick 	else if(lz == lp)
79522809Smckusick 		exar2(OPGE, expr, lz, lm);
79622809Smckusick 	else
79722809Smckusick 		if (optimflag)
79822809Smckusick 			{
79922809Smckusick 			labels[0] = neglab;
80022809Smckusick 			labels[1] = zerlab;
80122809Smckusick 			labels[2] = poslab;
80222809Smckusick 			optbuff (SKARIF, expr, 0, labels);
80322809Smckusick 			}
80422809Smckusick 		else
80522809Smckusick 			prarif(expr, lm, lz, lp);
80622809Smckusick 	}
80722809Smckusick }
80822809Smckusick 
80922809Smckusick 
81022809Smckusick 
81122809Smckusick LOCAL exar2 (op, e, l1, l2)
81222809Smckusick int	op;
81322809Smckusick expptr	e;
81422809Smckusick int	l1,l2;
81522809Smckusick {
81622809Smckusick if (optimflag)
81722809Smckusick 	{
81822809Smckusick 	optbuff (SKIFN, mkexpr(op, e, ICON(0)), l2, 0);
81922809Smckusick 	optbuff (SKGOTO, 0, l1, 0);
82022809Smckusick 	}
82122809Smckusick else
82222809Smckusick 	{
82322809Smckusick 	putif (mkexpr(op, e, ICON(0)), l2);
82422809Smckusick 	putgoto (l1);
82522809Smckusick 	}
82622809Smckusick }
82722809Smckusick 
82822809Smckusick 
82922809Smckusick exreturn(p)
83022809Smckusick register expptr p;
83122809Smckusick {
83222809Smckusick if(procclass != CLPROC)
83322809Smckusick 	warn("RETURN statement in main or block data");
83422809Smckusick if(p && (proctype!=TYSUBR || procclass!=CLPROC) )
83522809Smckusick 	{
83622809Smckusick 	err("alternate return in nonsubroutine");
83722809Smckusick 	p = 0;
83822809Smckusick 	}
83922809Smckusick 
84022809Smckusick if(p)
84122809Smckusick 	if (optimflag)
84222809Smckusick 		optbuff (SKRETURN, p, retlabel, 0);
84322809Smckusick 	else
84422809Smckusick 		{
84522809Smckusick 		putforce (TYINT, p);
84622809Smckusick 		putgoto (retlabel);
84722809Smckusick 		}
84822809Smckusick else
84922809Smckusick 	if (optimflag)
85022809Smckusick 		optbuff (SKRETURN, p,
85122809Smckusick 			 (proctype==TYSUBR ? ret0label : retlabel), 0);
85222809Smckusick 	else
85322809Smckusick 		putgoto (proctype==TYSUBR ? ret0label : retlabel);
85422809Smckusick }
85522809Smckusick 
85622809Smckusick 
85722809Smckusick 
85822809Smckusick exasgoto(labvar)
85922809Smckusick struct Hashentry *labvar;
86022809Smckusick {
86122809Smckusick register Addrp p;
86222809Smckusick 
86322809Smckusick p = mkplace(labvar);
86422809Smckusick if( ! ISINT(p->vtype) )
86522809Smckusick 	err("assigned goto variable must be integer");
86622809Smckusick else
86722809Smckusick 	if (optimflag)
86822809Smckusick 		optbuff (SKASGOTO, p, 0, 0);
86922809Smckusick 	else
87022809Smckusick 		putbranch (p);
87122809Smckusick }
872