4BSD/usr/src/cmd/f77/gram.exec

exec:	  iffable
	| SDO end_spec intonlyon label intonlyoff dospec
		{
		if($4->labdefined)
			execerr("no backward DO loops", CNULL);
		$4->blklevel = blklevel+1;
		exdo($4->labelno, $6);
		}
	| logif iffable
		{ exendif();  thiswasbranch = NO; }
	| logif STHEN
	| SELSEIF end_spec SLPAR expr SRPAR STHEN
		{ exelif($4); lastwasbranch = NO; }
	| SELSE end_spec
		{ exelse(); lastwasbranch = NO; }
	| SENDIF end_spec
		{ exendif(); lastwasbranch = NO; }
	;

logif:	  SLOGIF end_spec SLPAR expr SRPAR
		{ exif($4); }
	;

dospec:	  name SEQUALS exprlist
		{ $$ = mkchain($1, $3); }
	;

iffable:  let lhs SEQUALS expr
		{ exequals($2, $4); }
	| SASSIGN end_spec assignlabel STO name
		{ exassign($5, $3); }
	| SCONTINUE end_spec
	| goto
	| io
		{ inioctl = NO; }
	| SARITHIF end_spec SLPAR expr SRPAR label SCOMMA label SCOMMA label
		{ exarif($4, $6, $8, $10);  thiswasbranch = YES; }
	| call
		{ excall($1, PNULL, 0, labarray); }
	| call SLPAR SRPAR
		{ excall($1, PNULL, 0, labarray); }
	| call SLPAR callarglist SRPAR
		{ if(nstars < MAXLABLIST)
			excall($1, mklist($3), nstars, labarray);
		  else
			err("too many alternate returns");
		}
	| SRETURN end_spec opt_expr
		{ exreturn($3);  thiswasbranch = YES; }
	| stop end_spec opt_expr
		{ exstop($1, $3);  thiswasbranch = $1; }
	;

assignlabel:   SICON
		{ $$ = mklabel( convci(toklen, token) ); }
	;

let:	  SLET
		{ if(parstate == OUTSIDE)
			{
			newproc();
			startproc(PNULL, CLMAIN);
			}
		}
	;

goto:	  SGOTO end_spec label
		{ exgoto($3);  thiswasbranch = YES; }
	| SASGOTO end_spec name
		{ exasgoto($3);  thiswasbranch = YES; }
	| SASGOTO end_spec name opt_comma SLPAR labellist SRPAR
		{ exasgoto($3);  thiswasbranch = YES; }
	| SCOMPGOTO end_spec SLPAR labellist SRPAR opt_comma expr
		{ if(nstars < MAXLABLIST)
			putcmgo(fixtype($7), nstars, labarray);
		  else
			err("computed GOTO list too long");
		}
	;

opt_comma:
	| SCOMMA
	;

call:	  SCALL end_spec name
		{ nstars = 0; $$ = $3; }
	;

callarglist:  callarg
		{ $$ = ($1 ? mkchain($1,CHNULL) : CHNULL); }
	| callarglist SCOMMA callarg
		{ if($3)
			if($1) $$ = hookup($1, mkchain($3,CHNULL));
			else $$ = mkchain($3,CHNULL);
		  else
			$$ = $1;
		}
	;

callarg:  expr
	| SSTAR label
		{ if(nstars<MAXLABLIST) labarray[nstars++] = $2; $$ = 0; }
	;

stop:	  SPAUSE
		{ $$ = 0; }
	| SSTOP
		{ $$ = 1; }
	;

exprlist:  expr
		{ $$ = mkchain($1, CHNULL); }
	| exprlist SCOMMA expr
		{ $$ = hookup($1, mkchain($3,CHNULL) ); }
	;

end_spec:
		{ if(parstate == OUTSIDE)
			{
			newproc();
			startproc(PNULL, CLMAIN);
			}
		  if(parstate < INDATA) enddcl();
		}
	;

intonlyon:
		{ intonly = YES; }
	;

intonlyoff:
		{ intonly = NO; }
	;