xref: /csrg-svn/usr.bin/pascal/src/forop.c (revision 62211)
148116Sbostic /*-
2*62211Sbostic  * Copyright (c) 1980, 1993
3*62211Sbostic  *	The Regents of the University of California.  All rights reserved.
448116Sbostic  *
548116Sbostic  * %sccs.include.redist.c%
622167Sdist  */
714732Sthien 
814732Sthien #ifndef lint
9*62211Sbostic static char sccsid[] = "@(#)forop.c	8.1 (Berkeley) 06/06/93";
1048116Sbostic #endif /* not lint */
112187Smckusick 
122187Smckusick #include	"whoami.h"
132187Smckusick #include	"0.h"
142187Smckusick #include	"opcode.h"
152187Smckusick #include	"tree.h"
162187Smckusick #include	"objfmt.h"
172187Smckusick #ifdef PC
182187Smckusick #    include	"pc.h"
1918459Sralph #    include	<pcc.h>
202187Smckusick #endif PC
2111335Speter #include	"tmps.h"
2214732Sthien #include	"tree_ty.h"
233371Speter 
242187Smckusick     /*
2510798Speter      *	for-statements.
2610798Speter      *
2710798Speter      *	the relevant quote from the standard:  6.8.3.9:
2810798Speter      *	``The control-variable shall be an entire-variable whose identifier
2910798Speter      *	is declared in the variable-declaration-part of the block closest-
3010798Speter      *	containing the for-statement.  The control-variable shall possess
3110798Speter      *	an ordinal-type, and the initial-value and the final-value shall be
3210798Speter      *	of a type compatible with this type.  The statement of a for-statement
3310798Speter      *	shall not contain an assigning-reference to the control-variable
3410798Speter      *	of the for-statement.  The value of the final-value shall be
3510798Speter      *	assignment-compatible with the control-variable when the initial-value
3610798Speter      *	is assigned to the control-variable.  After a for-statement is
3710798Speter      *	executed (other than being left by a goto-statement leading out of it)
3810798Speter      *	the control-variable shall be undefined.  Apart from the restrictions
3910798Speter      *	imposed by these requirements, the for-statement
4010798Speter      *		for v := e1 to e2 do body
4110798Speter      *	shall be equivalent to
4210798Speter      *		begin
4310798Speter      *		    temp1 := e1;
4410798Speter      *		    temp2 := e2;
4510798Speter      *		    if temp1 <= temp2 then begin
4610798Speter      *			v := temp1;
4710798Speter      *			body;
4810798Speter      *			while v <> temp2 do begin
4910798Speter      *			    v := succ(v);
5010798Speter      *			    body;
5110798Speter      *			end
5210798Speter      *		    end
5310798Speter      *		end
5410798Speter      *	where temp1 and temp2 denote auxiliary variables that the program
5510798Speter      *	does not otherwise contain, and that possess the type possessed by
5610798Speter      *	the variable v if that type is not a subrange-type;  otherwise the
5710798Speter      *	host type possessed by the variable v.''
5810798Speter      *
5910798Speter      *	The Berkeley Pascal systems try to do all that without duplicating
6010798Speter      *	the body, and shadowing the control-variable in (possibly) a
6110798Speter      *	register variable.
6210798Speter      *
632187Smckusick      *	arg here looks like:
642187Smckusick      *	arg[0]	T_FORU or T_FORD
652187Smckusick      *	   [1]	lineof "for"
662187Smckusick      *	   [2]	[0]	T_ASGN
672187Smckusick      *		[1]	lineof ":="
682187Smckusick      *		[2]	[0]	T_VAR
692187Smckusick      *			[1]	lineof id
702187Smckusick      *			[2]	char * to id
712187Smckusick      *			[3]	qualifications
722187Smckusick      *		[3]	initial expression
732187Smckusick      *	  [3]	termination expression
742187Smckusick      *	  [4]	statement
752187Smckusick      */
7614732Sthien forop( tree_node)
7714732Sthien     struct tnode	*tree_node;
782187Smckusick     {
7914732Sthien 	struct tnode	*lhs;
8014732Sthien 	VAR_NODE	*lhs_node;
8114732Sthien 	FOR_NODE	*f_node;
822187Smckusick 	struct nl	*forvar;
832187Smckusick 	struct nl	*fortype;
8410666Speter #ifdef PC
8510798Speter 	int		forp2type;
8610666Speter #endif PC
8710666Speter 	int		forwidth;
8814732Sthien 	struct tnode	*init_node;
892187Smckusick 	struct nl	*inittype;
903836Speter 	struct nl	*initnlp;	/* initial value namelist entry */
9114732Sthien 	struct tnode	*term_node;
922187Smckusick 	struct nl	*termtype;
933836Speter 	struct nl	*termnlp;	/* termination value namelist entry */
9410798Speter 	struct nl	*shadownlp;	/* namelist entry for the shadow */
9514732Sthien 	struct tnode	*stat_node;
962187Smckusick 	int		goc;		/* saved gocnt */
972187Smckusick 	int		again;		/* label at the top of the loop */
982187Smckusick 	int		after;		/* label after the end of the loop */
9910798Speter 	struct nl	saved_nl;	/* saved namelist entry for loop var */
1002187Smckusick 
1012187Smckusick 	goc = gocnt;
10214732Sthien 	forvar = NLNIL;
10314732Sthien 	if ( tree_node == TR_NIL ) {
1042187Smckusick 	    goto byebye;
1052187Smckusick 	}
10614732Sthien 	f_node = &(tree_node->for_node);
10714732Sthien 	if ( f_node->init_asg == TR_NIL ) {
1082187Smckusick 	    goto byebye;
1092187Smckusick 	}
11014732Sthien 	line = f_node->line_no;
1112187Smckusick 	putline();
11214732Sthien 	lhs = f_node->init_asg->asg_node.lhs_var;
11314732Sthien 	init_node = f_node->init_asg->asg_node.rhs_expr;
11414732Sthien 	term_node = f_node->term_expr;
11514732Sthien 	stat_node = f_node->for_stmnt;
11614732Sthien 	if (lhs == TR_NIL) {
1173278Smckusic nogood:
1183584Speter 	    if (forvar != NIL) {
1193584Speter 		forvar->value[ NL_FORV ] = FORVAR;
1203584Speter 	    }
12114732Sthien 	    (void) rvalue( init_node , NLNIL , RREQ );
12214732Sthien 	    (void) rvalue( term_node , NLNIL , RREQ );
12314732Sthien 	    statement( stat_node );
1242187Smckusick 	    goto byebye;
1252187Smckusick 	}
12614732Sthien 	else lhs_node = &(lhs->var_node);
1272187Smckusick 	    /*
1282187Smckusick 	     * and this marks the variable as used!!!
1292187Smckusick 	     */
13014732Sthien 	forvar = lookup( lhs_node->cptr );
1312187Smckusick 	if ( forvar == NIL ) {
1323278Smckusic 	    goto nogood;
1332187Smckusick 	}
13410798Speter 	saved_nl = *forvar;
13514732Sthien 	if ( lhs_node->qual != TR_NIL ) {
1363278Smckusic 	    error("For variable %s must be unqualified", forvar->symbol);
1373278Smckusic 	    goto nogood;
1383278Smckusic 	}
1393278Smckusic 	if (forvar->class == WITHPTR) {
14014732Sthien 	    error("For variable %s cannot be an element of a record",
14114732Sthien 			lhs_node->cptr);
1423278Smckusic 	    goto nogood;
1433278Smckusic 	}
1443836Speter 	if ( opt('s') &&
1453836Speter 	    ( ( bn != cbn ) ||
1463836Speter #ifdef OBJ
14714732Sthien 		(whereis(forvar->value[NL_OFFS], 0) == PARAMVAR)
1483836Speter #endif OBJ
1493836Speter #ifdef PC
15014732Sthien 		(whereis(forvar->value[NL_OFFS], forvar->extra_flags)
1513836Speter 		    == PARAMVAR )
1523836Speter #endif PC
1533836Speter 	    ) ) {
1543278Smckusic 	    standard();
1553278Smckusic 	    error("For variable %s must be declared in the block in which it is used", forvar->symbol);
1563278Smckusic 	}
1572187Smckusick 	    /*
1582187Smckusick 	     * find out the type of the loop variable
1592187Smckusick 	     */
1602187Smckusick 	codeoff();
1612187Smckusick 	fortype = lvalue( lhs , MOD , RREQ );
1622187Smckusick 	codeon();
16314732Sthien 	if ( fortype == NLNIL ) {
1643278Smckusic 	    goto nogood;
1652187Smckusick 	}
1662187Smckusick 	if ( isnta( fortype , "bcis" ) ) {
1673278Smckusic 	    error("For variable %s cannot be %ss", forvar->symbol, nameof( fortype ) );
1683278Smckusic 	    goto nogood;
1692187Smckusick 	}
1703584Speter 	if ( forvar->value[ NL_FORV ] & FORVAR ) {
1713584Speter 	    error("Can't modify the for variable %s in the range of the loop", forvar->symbol);
17214732Sthien 	    forvar = NLNIL;
1733584Speter 	    goto nogood;
1743584Speter 	}
17510798Speter 	forwidth = lwidth(fortype);
17610798Speter #	ifdef PC
17710798Speter 	    forp2type = p2type(fortype);
17810798Speter #	endif PC
1792187Smckusick 	    /*
18010798Speter 	     *	allocate temporaries for the initial and final expressions
18110798Speter 	     *	and maybe a register to shadow the for variable.
1822187Smckusick 	     */
18314732Sthien 	initnlp = tmpalloc((long) sizeof(long), nl+T4INT, NOREG);
18414732Sthien 	termnlp = tmpalloc((long) sizeof(long), nl+T4INT, NOREG);
18514732Sthien 	shadownlp = tmpalloc((long) forwidth, fortype, REGOK);
1862187Smckusick #	ifdef PC
1872187Smckusick 		/*
1882187Smckusick 		 * compute and save the initial expression
1892187Smckusick 		 */
19014732Sthien 	    putRV((char *) 0 , cbn , initnlp -> value[ NL_OFFS ] ,
19118459Sralph 		    initnlp -> extra_flags , PCCT_INT );
1922187Smckusick #	endif PC
1932187Smckusick #	ifdef OBJ
19414732Sthien 	    (void) put(2, O_LV | cbn<<8+INDX, initnlp -> value[ NL_OFFS ] );
1952187Smckusick #	endif OBJ
19614732Sthien 	inittype = rvalue( init_node , fortype , RREQ );
19714732Sthien 	if ( incompat( inittype , fortype , init_node ) ) {
1982187Smckusick 	    cerror("Type of initial expression clashed with index type in 'for' statement");
19914732Sthien 	    if (forvar != NLNIL) {
2003584Speter 		forvar->value[ NL_FORV ] = FORVAR;
2013584Speter 	    }
20214732Sthien 	    (void) rvalue( term_node , NLNIL , RREQ );
20314732Sthien 	    statement( stat_node );
2042187Smckusick 	    goto byebye;
2052187Smckusick 	}
2062187Smckusick #	ifdef PC
20718459Sralph 	    sconv(p2type(inittype), PCCT_INT);
20818459Sralph 	    putop( PCC_ASSIGN , PCCT_INT );
2092187Smckusick 	    putdot( filename , line );
2102187Smckusick 		/*
2112187Smckusick 		 * compute and save the termination expression
2122187Smckusick 		 */
21314732Sthien 	    putRV((char *) 0 , cbn , termnlp -> value[ NL_OFFS ] ,
21418459Sralph 		    termnlp -> extra_flags , PCCT_INT );
2152187Smckusick #	endif PC
2162187Smckusick #	ifdef OBJ
21714732Sthien 	    (void) gen(O_AS2, O_AS2, sizeof(long), width(inittype));
2182187Smckusick 		/*
2192187Smckusick 		 * compute and save the termination expression
2202187Smckusick 		 */
22114732Sthien 	    (void) put(2, O_LV | cbn<<8+INDX, termnlp -> value[ NL_OFFS ] );
2222187Smckusick #	endif OBJ
22314732Sthien 	termtype = rvalue( term_node , fortype , RREQ );
22414732Sthien 	if ( incompat( termtype , fortype , term_node ) ) {
2252187Smckusick 	    cerror("Type of limit expression clashed with index type in 'for' statement");
22614732Sthien 	    if (forvar != NLNIL) {
2273584Speter 		forvar->value[ NL_FORV ] = FORVAR;
2283584Speter 	    }
22914732Sthien 	    statement( stat_node );
2302187Smckusick 	    goto byebye;
2312187Smckusick 	}
2322187Smckusick #	ifdef PC
23318459Sralph 	    sconv(p2type(termtype), PCCT_INT);
23418459Sralph 	    putop( PCC_ASSIGN , PCCT_INT );
2352187Smckusick 	    putdot( filename , line );
2362187Smckusick 		/*
2372187Smckusick 		 * we can skip the loop altogether if !( init <= term )
2382187Smckusick 		 */
23914732Sthien 	    after = (int) getlab();
24014732Sthien 	    putRV((char *) 0 , cbn , initnlp -> value[ NL_OFFS ] ,
24118459Sralph 		    initnlp -> extra_flags , PCCT_INT );
24214732Sthien 	    putRV((char *) 0 , cbn , termnlp -> value[ NL_OFFS ] ,
24318459Sralph 		    termnlp -> extra_flags , PCCT_INT );
24418459Sralph 	    putop( ( tree_node->tag == T_FORU ? PCC_LE : PCC_GE ) , PCCT_INT );
24518459Sralph 	    putleaf( PCC_ICON , after , 0 , PCCT_INT, (char *) 0 );
24618459Sralph 	    putop( PCC_CBRANCH , PCCT_INT );
2472187Smckusick 	    putdot( filename , line );
2482187Smckusick 		/*
24910798Speter 		 * okay, so we have to execute the loop body,
25010798Speter 		 * but first, if checking is on,
25110798Speter 		 * check that the termination expression
25210798Speter 		 * is assignment compatible with the control-variable.
25310798Speter 		 */
25410798Speter 	    if (opt('t')) {
25510798Speter 		precheck(fortype, "_RANG4", "_RSNG4");
25614732Sthien 		putRV((char *) 0, cbn, termnlp -> value[NL_OFFS],
25718459Sralph 		    termnlp -> extra_flags, PCCT_INT);
25810798Speter 		postcheck(fortype, nl+T4INT);
25910798Speter 		putdot(filename, line);
26010798Speter 	    }
26110798Speter 		/*
26210798Speter 		 * assign the initial expression to the shadow
26310798Speter 		 * checking the assignment if necessary.
26410798Speter 		 */
26514732Sthien 	    putRV((char *) 0, cbn, shadownlp -> value[NL_OFFS],
26610798Speter 		shadownlp -> extra_flags, forp2type);
26710798Speter 	    if (opt('t')) {
26810798Speter 		precheck(fortype, "_RANG4", "_RSNG4");
26914732Sthien 		putRV((char *) 0, cbn, initnlp -> value[NL_OFFS],
27018459Sralph 		    initnlp -> extra_flags, PCCT_INT);
27110798Speter 		postcheck(fortype, nl+T4INT);
27210798Speter 	    } else {
27314732Sthien 		putRV((char *) 0, cbn, initnlp -> value[NL_OFFS],
27418459Sralph 		    initnlp -> extra_flags, PCCT_INT);
27510798Speter 	    }
27618459Sralph 	    sconv(PCCT_INT, forp2type);
27718459Sralph 	    putop(PCC_ASSIGN, forp2type);
27810798Speter 	    putdot(filename, line);
27910798Speter 		/*
2803278Smckusic 		 * put down the label at the top of the loop
2813278Smckusic 		 */
28214732Sthien 	    again = (int) getlab();
28314732Sthien 	    (void) putlab((char *) again );
2843278Smckusic 		/*
28510798Speter 		 * each time through the loop
28610798Speter 		 * assign the shadow to the for variable.
2872187Smckusick 		 */
28814732Sthien 	    (void) lvalue(lhs, NOUSE, RREQ);
28914732Sthien 	    putRV((char *) 0, cbn, shadownlp -> value[NL_OFFS],
29010798Speter 		    shadownlp -> extra_flags, forp2type);
29118459Sralph 	    putop(PCC_ASSIGN, forp2type);
29210798Speter 	    putdot(filename, line);
2932187Smckusick #	endif PC
2942187Smckusick #	ifdef OBJ
29514732Sthien 	    (void) gen(O_AS2, O_AS2, sizeof(long), width(termtype));
2962187Smckusick 		/*
2972187Smckusick 		 * we can skip the loop altogether if !( init <= term )
2982187Smckusick 		 */
29914732Sthien 	    (void) put(2, O_RV4 | cbn<<8+INDX, initnlp -> value[ NL_OFFS ] );
30014732Sthien 	    (void) put(2, O_RV4 | cbn<<8+INDX, termnlp -> value[ NL_OFFS ] );
30114732Sthien 	    (void) gen(NIL, tree_node->tag == T_FORU ? T_LE : T_GE, sizeof(long),
30210798Speter 			sizeof(long));
30314732Sthien 	    after = (int) getlab();
30414732Sthien 	    (void) put(2, O_IF, after);
3052187Smckusick 		/*
30610798Speter 		 * okay, so we have to execute the loop body,
30710798Speter 		 * but first, if checking is on,
30810798Speter 		 * check that the termination expression
30910798Speter 		 * is assignment compatible with the control-variable.
31010798Speter 		 */
31110798Speter 	    if (opt('t')) {
31214732Sthien 		(void) put(2, O_LV | cbn<<8+INDX, shadownlp -> value[ NL_OFFS ] );
31314732Sthien 		(void) put(2, O_RV4 | cbn<<8+INDX, termnlp -> value[ NL_OFFS ] );
31410798Speter 		rangechk(fortype, nl+T4INT);
31514732Sthien 		(void) gen(O_AS2, O_AS2, forwidth, sizeof(long));
31610798Speter 	    }
31710798Speter 		/*
31810798Speter 		 * assign the initial expression to the shadow
31910798Speter 		 * checking the assignment if necessary.
32010798Speter 		 */
32114732Sthien 	    (void) put(2, O_LV | cbn<<8+INDX, shadownlp -> value[ NL_OFFS ] );
32214732Sthien 	    (void) put(2, O_RV4 | cbn<<8+INDX, initnlp -> value[ NL_OFFS ] );
32310798Speter 	    rangechk(fortype, nl+T4INT);
32414732Sthien 	    (void) gen(O_AS2, O_AS2, forwidth, sizeof(long));
32510798Speter 		/*
3263278Smckusic 		 * put down the label at the top of the loop
3273278Smckusic 		 */
32814732Sthien 	    again = (int) getlab();
32914732Sthien 	    (void) putlab( (char *) again );
3303278Smckusic 		/*
33110798Speter 		 * each time through the loop
33210798Speter 		 * assign the shadow to the for variable.
3332187Smckusick 		 */
33414732Sthien 	    (void) lvalue(lhs, NOUSE, RREQ);
33514732Sthien 	    (void) stackRV(shadownlp);
33614732Sthien 	    (void) gen(O_AS2, O_AS2, forwidth, sizeof(long));
3372187Smckusick #	endif OBJ
3382187Smckusick 	    /*
3393584Speter 	     *	shadowing the real for variable
34010798Speter 	     *	with the shadow temporary:
34110798Speter 	     *	save the real for variable flags (including nl_block).
34210798Speter 	     *	replace them with the shadow's offset,
34310798Speter 	     *	and mark the for variable as being a for variable.
3443584Speter 	     */
34510842Smckusick 	shadownlp -> nl_flags |= NLFLAGS(forvar -> nl_flags);
34610798Speter 	*forvar = *shadownlp;
34710798Speter 	forvar -> symbol = saved_nl.symbol;
34810798Speter 	forvar -> nl_next = saved_nl.nl_next;
34910798Speter 	forvar -> type = saved_nl.type;
3503584Speter 	forvar -> value[ NL_FORV ] = FORVAR;
3513584Speter 	    /*
3522187Smckusick 	     * and don't forget ...
3532187Smckusick 	     */
3543278Smckusic 	putcnt();
35514732Sthien 	statement( stat_node );
3562187Smckusick 	    /*
3572187Smckusick 	     * wasn't that fun?  do we get to do it again?
3582187Smckusick 	     *	we don't do it again if ( !( forvar < limit ) )
3592187Smckusick 	     *	pretend we were doing this at the top of the loop
3602187Smckusick 	     */
36114732Sthien 	line = f_node->line_no;
3622187Smckusick #	ifdef PC
3632187Smckusick 	    if ( opt( 'p' ) ) {
3642187Smckusick 		if ( opt('t') ) {
36518459Sralph 		    putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
3662187Smckusick 			    , "_LINO" );
36718459Sralph 		    putop( PCCOM_UNARY PCC_CALL , PCCT_INT );
3682187Smckusick 		    putdot( filename , line );
3692187Smckusick 		} else {
37018459Sralph 		    putRV( STMTCOUNT , 0 , 0 , NGLOBAL , PCCT_INT );
37118459Sralph 		    putleaf( PCC_ICON , 1 , 0 , PCCT_INT , (char *) 0 );
37218459Sralph 		    putop( PCCOM_ASG PCC_PLUS , PCCT_INT );
3732187Smckusick 		    putdot( filename , line );
3742187Smckusick 		}
3752187Smckusick 	    }
37614732Sthien 	    /*rvalue( lhs_node , NIL , RREQ );*/
37714732Sthien 	    putRV( (char *) 0 , cbn , shadownlp -> value[ NL_OFFS ] ,
37810798Speter 		    shadownlp -> extra_flags , forp2type );
37918459Sralph 	    sconv(forp2type, PCCT_INT);
38014732Sthien 	    putRV( (char *) 0 , cbn , termnlp -> value[ NL_OFFS ] ,
38118459Sralph 		    termnlp -> extra_flags , PCCT_INT );
38218459Sralph 	    putop( ( tree_node->tag == T_FORU ? PCC_LT : PCC_GT ) , PCCT_INT );
38318459Sralph 	    putleaf( PCC_ICON , after , 0 , PCCT_INT , (char *) 0 );
38418459Sralph 	    putop( PCC_CBRANCH , PCCT_INT );
3852187Smckusick 	    putdot( filename , line );
3862187Smckusick 		/*
3872187Smckusick 		 * okay, so we have to do it again,
3882187Smckusick 		 * but first, increment the for variable.
38910798Speter 		 * no need to rangecheck it, since we checked the
39010798Speter 		 * termination value before we started.
3912187Smckusick 		 */
3923836Speter 	    /*lvalue( lhs , MOD , RREQ );*/
39314732Sthien 	    putRV( (char *) 0 , cbn , shadownlp -> value[ NL_OFFS ] ,
39410798Speter 		    shadownlp -> extra_flags , forp2type );
39514732Sthien 	    /*rvalue( lhs_node , NIL , RREQ );*/
39614732Sthien 	    putRV( (char *) 0 , cbn , shadownlp -> value[ NL_OFFS ] ,
39710798Speter 		    shadownlp -> extra_flags , forp2type );
39818459Sralph 	    sconv(forp2type, PCCT_INT);
39918459Sralph 	    putleaf( PCC_ICON , 1 , 0 , PCCT_INT , (char *) 0 );
40018459Sralph 	    putop( ( tree_node->tag == T_FORU ? PCC_PLUS : PCC_MINUS ) , PCCT_INT );
40118459Sralph 	    sconv(PCCT_INT, forp2type);
40218459Sralph 	    putop( PCC_ASSIGN , forp2type );
4032187Smckusick 	    putdot( filename , line );
4042187Smckusick 		/*
4052187Smckusick 		 * and do it all again
4062187Smckusick 		 */
40714732Sthien 	    putjbr( (long) again );
4082187Smckusick 		/*
4092187Smckusick 		 * and here we are
4102187Smckusick 		 */
41114732Sthien 	    (void) putlab( (char *) after );
4122187Smckusick #	endif PC
4132187Smckusick #	ifdef OBJ
4142187Smckusick 		/*
4152187Smckusick 		 * okay, so we have to do it again.
4162187Smckusick 		 * Luckily we have a magic opcode which increments the
4172187Smckusick 		 * index variable, checks the limit falling through if
41810798Speter 		 * it has been reached, else updating the index variable,
41910798Speter 		 * and returning to the top of the loop.
4202187Smckusick 		 */
4212649Speter 	    putline();
42214732Sthien 	    (void) put(2, O_RV4 | cbn<<8+INDX, termnlp -> value[ NL_OFFS ] );
42314732Sthien 	    (void) put(2, O_LV | cbn<<8+INDX, shadownlp -> value[ NL_OFFS ] );
42414732Sthien 	    (void) put(2, (tree_node->tag == T_FORU ? O_FOR1U : O_FOR1D) + (forwidth >> 1),
42510798Speter 		    again);
4262187Smckusick 		/*
4272187Smckusick 		 * and here we are
4282187Smckusick 		 */
42914732Sthien 	    patch( (PTR_DCL) after );
4302187Smckusick #	endif OBJ
4312187Smckusick byebye:
43214732Sthien 	noreach = FALSE;
43314732Sthien 	if (forvar != NLNIL) {
43410842Smckusick 	    saved_nl.nl_flags |= NLFLAGS(forvar -> nl_flags) & (NUSED|NMOD);
43510798Speter 	    *forvar = saved_nl;
4362187Smckusick 	}
4372187Smckusick 	if ( goc != gocnt ) {
4382187Smckusick 	    putcnt();
4392187Smckusick 	}
4402187Smckusick     }
441