[comp.lang.fortran] Assigned GOTO

chris@mimsy.UUCP (Chris Torek) (06/29/88)

In article <1544@microsoft.UUCP> bobal@microsoft.UUCP (Bob Allison) writes:
>reading [a previous] article I did manage to come up with a feature
>which is fairly difficult to implement in C: assigned gotos.  I don't
>believe C can take the address of a label ...

(Some compilers allow it, but that is just a bug.)

I am confident that I could convert any assigned GOTO FORTRAN code into
something more reasonable, but I am curious: what do people actually
use it for?  I once did some fairly extensive FORTRAN programming (the
alterative was BASIC, without local variables, etc); the only thing I
used ASSIGN statements for was to bypass the FORTRAN system to get
addresses into arguments to assembly coded support routines.

This is, of course, not legal FORTRAN, just useful.  (I was emulating
IBM's extension where one can say

	CALL FOO(param, &label1, &label2)
	...
	SUBROUTINE FOO(param, *, *)
	...
C I forget the exact syntax, but... jump to label1:
	RETURN 1
	END
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

kurtk@tekcae.TEK.COM (Kurt Krueger) (07/01/88)

Another mis-use of assigned GOTO takes into account that most implementations
use the actual address of the label and don't bother to check against the list
of possible branches that is required for the GOTO LABEL, (100,300) statement.
If you pass LABEL to a subroutine or put it in common, you can branch from
one subroutine directly into another. (!)

dik@cwi.nl (Dik T. Winter) (07/03/88)

In article <1821@tekcae.TEK.COM> kurtk@tekcae.UUCP (Kurt Krueger) writes:
 > Another mis-use of assigned GOTO takes into account that most implementations
 > use the actual address of the label and don't bother to check against the list
 > of possible branches that is required for the GOTO LABEL, (100,300) statement.
 > If you pass LABEL to a subroutine or put it in common, you can branch from
 > one subroutine directly into another. (!)

Yes, but most likely, the routine you jump to is not able to access its
parameters.  (This happens if the parameter list address is stored in a
register.)
-- 
dik t. winter, cwi, amsterdam, nederland
INTERNET   : dik@cwi.nl
BITNET/EARN: dik@mcvax

nmm@cl.cam.ac.uk (Nick Maclaren) (07/04/88)

In article 766, chris@mimsy.UUCP (Chris Torek) writes:
> I am confident that I could convert any assigned GOTO FORTRAN code into 
> something more reasonable, but I am curious: what do people actually 
> use it for?  ...

In general, I agree, but there are a few algorithms where assigned GOTOs
clarify the code (sic).  The ones I have written were all simple finite
state algorithms (e.g. contour plotting), where the next state to go to
was a function of the previous state.  That is, state n+1 is decided by
state n-1, rather than state n.

The 'structured' approach is a case statement inside an infinite loop;
I find this rather less clear.  Still, I would not preserve assigned GOTOs
for the sake of a few unusual algorithms, and no longer use them myself
(even in Fortran).

Nick Maclaren
University of Cambridge Computer Laboratory
nmm@uk.ac.cam.cl

jerry@violet.berkeley.edu ( Jerry Berkman ) (07/06/88)

In article <1821@tekcae.TEK.COM> kurtk@tekcae.UUCP (Kurt Krueger) writes:
>Another mis-use of assigned GOTO takes into account that most implementations
>use the actual address of the label and don't bother to check against the list
>of possible branches that is required for the GOTO LABEL, (100,300) statement.
>If you pass LABEL to a subroutine or put it in common, you can branch from
>one subroutine directly into another. (!)

According to the 1977 standard, p.11-2, the list is optional, not required.
However:

	"If the parenthesized list is present, the statement label
	assigned to i must be one of the statement labels in the list."

and branching between routines is not allowed:

	"the variable i must be defined with the value of a statement label
	of an executable statement that appears in the same program unit".

Although part of the standard, assigned GO TOs should be avoided.

	- Jerry Berkman
	  U.C. Berkeley, jerry@violet.berkeley.edu

ssd@sugar.UUCP (Scott Denham) (07/07/88)

In article <12215@mimsy.UUCP>, chris@mimsy.UUCP (Chris Torek) writes:
> I am confident that I could convert any assigned GOTO FORTRAN code into
> something more reasonable, but I am curious: what do people actually
> use it for?        { one example of such use deleted}
> In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)


 One of the few helpful uses I've made of assigned GOTO is to implement
a form of internal procedures - for small chunks of code that can't
be handled as statement function definitions but need access to too 
much stuff to make a reasonable subroutine out of it. (Subroutine calls
also break optimization pretty badly on IBM, or did at one time). Such
use might look something like 
   
          ASSIGN 1400 TO R1
          GOTO 10020
     1400 CONTINUE 
          .......
    10200 FOO = FOO ** 2
          .......
          GOTO R1 (1400,1500,1600,1700) 
 
 Unfortunately, IBM's compiler does no checking whatsoever of the possible
 return values - at one time they didn't even have to be valid labels!!
 This can lead to some rather misleading documention. Are other compilers
 as loose with the defintions ???  
 
  Scott Denham 
  Western Atlas International

ags@s.cc.purdue.edu (Dave Seaman) (07/07/88)

In article <2261@sugar.UUCP> ssd@sugar.UUCP (Scott Denham) writes:
>Such use might look something like 
   
>          ASSIGN 1400 TO R1
>          GOTO 10020
>     1400 CONTINUE 
>          .......
>    10200 FOO = FOO ** 2
>          .......
>          GOTO R1 (1400,1500,1600,1700) 
 
> Unfortunately, IBM's compiler does no checking whatsoever of the possible
> return values - at one time they didn't even have to be valid labels!!
> This can lead to some rather misleading documention. Are other compilers
> as loose with the defintions ???  

The fact that a compiler does not check the return values does not
necessarily mean that it is safe to put in anything you like.  An
optimizing compiler may assume (without bothering to check) that your list
of return values is accurate and use that assumption to generate more
efficient code.  Naturally, such code is likely to break if the
destination of the GOTO is not in the label list.  

I have actually seen this happen with CDC's old FTN compiler.  The program
worked with optimization turned off, but bombed with optimization on.

-- 
Dave Seaman	  					
ags@j.cc.purdue.edu

jackson@esosun.UUCP (Jerry Jackson) (07/08/88)

Someone asked for uses for the assigned goto.  Until this discussion, I
did not know Fortran had such a beast.  However, I know of an application
where I would dearly have loved to have it.  (I'm mostly a Lisp/C hacker..)

I wrote a Scheme interpreter in 'C'.  One of the properties of Scheme
is that procedure calls MUST be tail recursive -- hence, the 'C'
function calling mechanism was not applicable to Scheme function
calls.  What I had to do was simulate a procedure call/return
sequence.  To do this right, you have to be able to push return
addresses (i.e. labels) on an explicit stack, then pop them and goto
the result. C does not allow you to 'goto' the value of a variable --
If it did, I could have written a much more efficient interpreter.

I would have liked to have written:

pop(ReturnAddress);
goto ReturnAddress;

Instead, I had to use a giant switch statement on tags that looked
like:

pop(ReturnAddress);
switch (ReturnAddress)
{
	case APPLY: code for apply...;
	case XXXX:  code for XXXX...;

		.
		.
		.
}

I spent much time cursing 'C' for not having an assigned goto.

+-----------------------------------------------------------------------------+
|   Jerry Jackson                       UUCP:  seismo!esosun!jackson          |
|   Geophysics Division, MS/22          ARPA:  esosun!jackson@seismo.css.gov  |
|   SAIC                                SOUND: (619)458-4924                  |
|   10210 Campus Point Drive                                                  |
|   San Diego, CA  92121                                                      |
+-----------------------------------------------------------------------------+

ssd@sugar.UUCP (Scott Denham) (07/08/88)

In article <3350@s.cc.purdue.edu>, ags@s.cc.purdue.edu (Dave Seaman) writes:
 (discussion and examples of computed GOTO's deleted)
> 
> The fact that a compiler does not check the return values does not
> necessarily mean that it is safe to put in anything you like.  An
> optimizing compiler may assume (without bothering to check) that your list
> of return values is accurate and use that assumption to generate more
> efficient code.  Naturally, such code is likely to break if the
> destination of the GOTO is not in the label list.  
> 
> Dave Seaman	  					
 
 I certainly didn't mean to condone putting bogus values into the 
 list of alternate branch points. As one who derives a large portion of
 my livelyhood out of trying to mantain, debug, and extend FORTRAN code
 written be other (soimetimes LOTS of other) people, I can testify that 
 the only thing WORSE than undocumented code is MIS-documented code. No
 matter how much skepticism you view the documentation with, it tends
 to lead you to a particular mindset when trying to understand how a
 program does (or doesn't :} ) what it is supposed to do. Bogus lists
 of alternate returns from assigned GOTO's are one of the nastiest!
 (Did he REALLY tghink he could get there from here....here from there???!)
 
  Scott Denham 

chris@mimsy.UUCP (Chris Torek) (07/08/88)

In article <222@esosun.UUCP> jackson@esosun.UUCP (Jerry Jackson) writes:
>Someone asked for uses for the assigned goto. ...
>I wrote a Scheme interpreter in 'C'.  One of the properties of Scheme
>is that procedure calls MUST be tail recursive -- hence, the 'C'
>function calling mechanism was not applicable to Scheme function
>calls.  What I had to do was simulate a procedure call/return
>sequence.  To do this right, you have to be able to push return
>addresses (i.e. labels) on an explicit stack, then pop them and goto
>the result. C does not allow you to 'goto' the value of a variable --
>If it did, I could have written a much more efficient interpreter.

On the other hand, FORTRAN does not allow this either: not the
way you want it.  The GOTO is only allowed to transfer control
within the current module (program, subroutine, or function).  It
sometimes works to jump outside the function, but it is by no means
required to work.

You can almost do this with setjmp and longjmp in C.  A better
way is to do it in assembly:

	extern void foo();
	...
	bar()
	{
		...
		jump_to(foo);
	}

	# jump_to, for vax:
		.globl	_jump_to
	_jump_to:.word	0
		movl	4(ap),12(fp)	# stash new return pc
		ret			# and away we go

This version is somewhat simplistic; it assumes that bar() and
foo() have the same register save mask, for instance.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

jackson@esosun.UUCP (Jerry Jackson) (07/08/88)

In article <12362@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:

   Path: esosun!seismo!uunet!lll-winken!lll-tis!ames!ncar!oddjob!mimsy!chris
   From: chris@mimsy.UUCP (Chris Torek)
   Newsgroups: comp.lang.fortran
   Date: 8 Jul 88 04:38:27 GMT
   References: <2742@utastro.UUCP> <20008@beta.UUCP> <224@raunvis.UUCP> <222@esosun.UUCP>
   Organization: U of Maryland, Dept. of Computer Science, Coll. Pk., MD 20742
   Lines: 38

   In article <222@esosun.UUCP> jackson@esosun.UUCP (Jerry Jackson) writes:
   >Someone asked for uses for the assigned goto. ...
   >I wrote a Scheme interpreter in 'C'.  One of the properties of Scheme
   >is that procedure calls MUST be tail recursive -- hence, the 'C'
   >function calling mechanism was not applicable to Scheme function
   >calls.  What I had to do was simulate a procedure call/return
   >sequence.  To do this right, you have to be able to push return
   >addresses (i.e. labels) on an explicit stack, then pop them and goto
   >the result. C does not allow you to 'goto' the value of a variable --
   >If it did, I could have written a much more efficient interpreter.

   On the other hand, FORTRAN does not allow this either: not the
   way you want it.  The GOTO is only allowed to transfer control
   within the current module (program, subroutine, or function).  It
   sometimes works to jump outside the function, but it is by no means
   required to work.

   You can almost do this with setjmp and longjmp in C.  A better
   way is to do it in assembly:

	   extern void foo();
	   ...
	   bar()
	   {
		   ...
		   jump_to(foo);
	   }

	   # jump_to, for vax:
		   .globl	_jump_to
	   _jump_to:.word	0
		   movl	4(ap),12(fp)	# stash new return pc
		   ret			# and away we go

   This version is somewhat simplistic; it assumes that bar() and
   foo() have the same register save mask, for instance.
   -- 
   In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
   Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris



I don't know if this really requires a follow-up but, actually, the
ability to jump to a label stored in a variable within the current
function would have been enough to do what I wanted... Only Scheme
special forms (mostly) would have required the goto's (primitive
functions that do not call the evaluator need not be tail-recursive --
they will always return before evaluation continues anyway).  The code
for each of the special forms would just have to have been included in
the main function for the interpreter.  So, I would have had a large
main function, but it would have been fast!!!!



+-----------------------------------------------------------------------------+
|   Jerry Jackson                       UUCP:  seismo!esosun!jackson          |
|   Geophysics Division, MS/22          ARPA:  esosun!jackson@seismo.css.gov  |
|   SAIC                                SOUND: (619)458-4924                  |
|   10210 Campus Point Drive                                                  |
|   San Diego, CA  92121                                                      |
+-----------------------------------------------------------------------------+

jlg@beta.lanl.gov (Jim Giles) (07/12/88)

In article <12362@mimsy.UUCP>, chris@mimsy.UUCP (Chris Torek) writes:
> [...]
> You can almost do this with setjmp and longjmp in C.  A better
> way is to do it in assembly:
> 
> 	# jump_to, for vax:
> 		.globl	_jump_to
> 	_jump_to:.word	0
> 		movl	4(ap),12(fp)	# stash new return pc
> 		ret			# and away we go
> 
Think again.  My machine doesn't have any of these mnemonics.  I'm
not even sure what the above code means.  The requirement is for a
PORTABLE way of doing the action.  In this respect, a 'better way'
would be to allow pointers to code, and allow jumps to them (you
already can reference a code pointer for a procedure call).

Note: this doesn't mean that I agree that the original poster had
found a legitimate use of assigned GOTOs.  I would have tried VERY
hard to avoid his solution.  But, if this method was indeed the
most efficient, then assembly is not a good substitute to having
the feature in the language.

J. Giles
Los Alamos

chris@mimsy.UUCP (Chris Torek) (07/12/88)

>In article <12362@mimsy.UUCP> I suggested doing `jump to another function
without changing {stack frames / execution environments / whatever you want
to call them}':
>>do it in assembly:
>>	# jump_to, for vax:
		       ---

In article <20664@beta.lanl.gov> jlg@beta.lanl.gov (Jim Giles) writes:
>Think again.  My machine doesn't have any of these mnemonics.

Are you deliberately being irritating?

>... The requirement is for a PORTABLE way of doing the action.

Not necessarily.

>In this respect, a 'better way' would be to allow pointers to code,
>and allow jumps to them ....

Possibly so.  But if you MUST use some language (perhaps it is the only
one you have that is anywhere near suited to the task) and you cannot
do something within that language, the best way is to do it out of that
language---*AFTER* abstracting the operation, so that it can be done on
other machines without too much effort.  (Perhaps it will take a fair
bit of effort; maybe the reason it is not in the language is because it
is *hard* on some machines.  The VAX version I wrote is basically
wrong; a correct version is quite a bit longer.)

>...  But, if this method was indeed the
>most efficient, then assembly is not a good substitute to having
>the feature in the language.

No, but changing the language to add it is also not a good substitute
for having it in the language, unless you intend to convince everyone
else also to change the language in the same way (and are willing to
back off if the next ANSI or ISO or ... standard decides it should be
done differently).

(If it is your own language, of course, do whatever you like.)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris