[comp.lang.c] gotos

henry@utzoo.uucp (Henry Spencer) (04/06/88)

> Sometimes, gotos are perfectly justifiable because they vastly
> simplify and clarify you code.

And once in a long while, there is no better way.  A loooong while.
If I were running a software house, I'd be tempted to say that using
a goto -- except in fixing a program that already uses them -- means
having $50 docked from your pay.  It's not *forbidden*, you understand,
it's just that you have to want it really badly!
-- 
"Noalias must go.  This is           |  Henry Spencer @ U of Toronto Zoology
non-negotiable."  --DMR              | {allegra,ihnp4,decvax,utai}!utzoo!henry

djones@megatest.UUCP (Dave Jones) (04/07/88)

in article <1988Apr5.213343.1528@utzoo.uucp>, henry@utzoo.uucp (Henry Spencer) says:
> 
...
> If I were running a software house, I'd be tempted to say that using
> a goto -- except in fixing a program that already uses them -- means
> having $50 docked from your pay.  
>

HAHAHAHAHAHAHAHAHHAHHAHAHAHAHHAHAHHAHAHAHAHAHHAHAHAHAHHAHAHAHAHA.

Try to pull that around here, and you'd be in the pond in about ten
minutes flat.



NOW. The first volley has been fired.  May the goto-wars resume!



	Dave (Do Not Pass Go) Jones

nevin1@ihlpf.ATT.COM (00704a-Liber) (04/07/88)

In article <1988Apr5.213343.1528@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes:

>And once in a long while, there is no better way.  A loooong while.

Agreed.  Although I feel that most of the uses of GOTO in C these days
occurs in the output of something like LEX and YACC, where I really don't
mind it.  Just as long as 'mere mortals' try to avoid using it.

>If I were running a software house, I'd be tempted to say that using
>a goto -- except in fixing a program that already uses them -- means
>having $50 docked from your pay.  It's not *forbidden*, you understand,
>it's just that you have to want it really badly!

Can I work for you??  I mean, if you would deduct $50 from my pay every
time I use GOTO, I would rather spend the *over*time and write code that
avoids it!  :-)
-- 
 _ __			NEVIN J. LIBER	..!ihnp4!ihlpf!nevin1	(312) 510-6194
' )  )				"The secret compartment of my ring I fill
 /  / _ , __o  ____		 with an Underdog super-energy pill."
/  (_</_\/ <__/ / <_	These are solely MY opinions, not AT&T's, blah blah blah

levy@ttrdc.UUCP (Daniel R. Levy) (04/08/88)

In article <4307@ihlpf.ATT.COM>, nevin1@ihlpf.ATT.COM (00704a-Liber) writes:
> In article <1988Apr5.213343.1528@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes:
> 
> >And once in a long while, there is no better way.  A loooong while.
> 
> Agreed.  Although I feel that most of the uses of GOTO in C these days
> occurs in the output of something like LEX and YACC, where I really don't
> mind it.  Just as long as 'mere mortals' try to avoid using it.

I know this battle is an old chestnut, but for the record do you guys believe
that superfluous flags and great big if-then statements are truly superior
to the goto?  (And the break, which is a goto by another name.)  E.g.:

	while (loopcond) {
		for (i=0; i<limit; i++)
			if (frob(i) == TRUE)
				goto loopagain;	/* nice and CLEAN!!! */
		...
		/* lots and lots of code over many pages */
		...
loopagain:	;
	}

versus

	while (loopcond) {
		boolean_flag=FALSE;
		for (i=0; i<limit; i++) {
			if (boolean_flag == TRUE) {
				;	/* spin uselessly */
			} else if (frob(i) == TRUE) {
				boolean_flag=TRUE;
			}
		}
		if (boolean_flag==FALSE) {
			...
			/* lots and lots of code over many pages */
			...
		}
	}
-- 
|------------Dan Levy------------|  Path: ..!{akgua,homxb,ihnp4,ltuxa,mvuxa,
|         an Engihacker @        |  	<most AT&T machines>}!ttrdc!ttrda!levy
|     AT&T Data Systems Group    |  Disclaimer?  Huh?  What disclaimer???
|--------Skokie, Illinois--------|

davidsen@steinmetz.ge.com (William E. Davidsen Jr) (04/08/88)

In article <2556@ttrdc.UUCP> levy@ttrdc.UUCP (Daniel R. Levy) writes:
> [...]
>I know this battle is an old chestnut, but for the record do you guys believe
>that superfluous flags and great big if-then statements are truly superior
>to the goto?  (And the break, which is a goto by another name.)  E.g.:

But... the break (and continue) are not the same as a goto. The goto
transfers control to a label, which may be anywhere in the program. The
break transfers control out of a loop.
	a) you know what it does when you write it
	b) you know what it does when you read it
	c) you won't move the stupid label or put code before it
	   which should be after.

I maintain that the evil is not the goto but the label. It can be put in
the wrong place to start, and often during program changes gets moved,
or statements inserted on the wrong side of it. I don't contend that
it's EVIL, just that it is inherently a higher overhead to write and
maintain then break and continue.

Yes, I have used a few gotos, but always examine the logic before I do
it. No, I don't think that longjmp() is a solution.
-- 
	bill davidsen		(wedu@ge-crd.arpa)
  {uunet | philabs | seismo}!steinmetz!crdos1!davidsen
"Stupidity, like virtue, is its own reward" -me

cramer@optilink.UUCP (Clayton Cramer) (04/09/88)

> > Sometimes, gotos are perfectly justifiable because they vastly
> > simplify and clarify you code.
> 
> And once in a long while, there is no better way.  A loooong while.
> If I were running a software house, I'd be tempted to say that using
> a goto -- except in fixing a program that already uses them -- means
> having $50 docked from your pay.  It's not *forbidden*, you understand,
> it's just that you have to want it really badly!
> -- 
> "Noalias must go.  This is           |  Henry Spencer @ U of Toronto Zoology
> non-negotiable."  --DMR              | {allegra,ihnp4,decvax,utai}!utzoo!henry

Exactly the right approach.  The last project I supervised, the engineers
that worked for me would occasionally try to justify a goto.  Every single
time, I demonstrated that the worst they were out was an automatic variable
and maybe a do...while construct -- usually the do...while loop and an
appropriate automatic variable were already there.

I accept the remote possibility that goto might be appropriate somewhere --
just as I accept the remote possibility that leprechauns exist, and we've
just never found them.

Clayton E. Cramer

henry@utzoo.uucp (Henry Spencer) (04/09/88)

> Try to pull that around here, and you'd be in the pond in about ten
> minutes flat.

Remind me never to buy any software from you guys!
-- 
"Noalias must go.  This is           |  Henry Spencer @ U of Toronto Zoology
non-negotiable."  --DMR              | {allegra,ihnp4,decvax,utai}!utzoo!henry

nevin1@ihlpf.ATT.COM (00704a-Liber) (04/09/88)

In article <2556@ttrdc.UUCP> levy@ttrdc.UUCP (Daniel R. Levy) writes:
|I know this battle is an old chestnut, but for the record do you guys believe
|that superfluous flags and great big if-then statements are truly superior
|to the goto?  (And the break, which is a goto by another name.)  E.g.:
|
|	while (loopcond) {
|		for (i=0; i<limit; i++)
|			if (frob(i) == TRUE)
|				goto loopagain;	/* nice and CLEAN!!! */
|		...
|		/* lots and lots of code over many pages */
|		...
|loopagain:	;
|	}

Opinion:  this is an example of FORTRAN disguised as C.

|versus

|	while (loopcond) {
|		boolean_flag=FALSE;
|		for (i=0; i<limit; i++) {
|			if (boolean_flag == TRUE) {
|				;	/* spin uselessly */
|			} else if (frob(i) == TRUE) {
|				boolean_flag=TRUE;
|			}
|		}
|		if (boolean_flag==FALSE) {
|			...
|			/* lots and lots of code over many pages */
|			...
|		}
|	}

Opinion:  this is an example of Pascal disguised as C.


For the record:  these are BOTH bad C programming paradigms!!  There are
other constructs which can alter the flow of control:  break, continue, and
return.  Use them!!  In this particular case, using a continue statement
inside in your Fortran-type example instead of a goto is much more preferable.
-- 
 _ __			NEVIN J. LIBER	..!ihnp4!ihlpf!nevin1	(312) 510-6194
' )  )				"The secret compartment of my ring I fill
 /  / _ , __o  ____		 with an Underdog super-energy pill."
/  (_</_\/ <__/ / <_	These are solely MY opinions, not AT&T's, blah blah blah

djones@megatest.UUCP (Dave Jones) (04/09/88)

in article <2556@ttrdc.UUCP>, levy@ttrdc.UUCP (Daniel R. Levy) says:
> 
> In article <4307@ihlpf.ATT.COM>, nevin1@ihlpf.ATT.COM (00704a-Liber) writes:
>> In article <1988Apr5.213343.1528@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes:
>> 
>> >And once in a long while, there is no better way.  A loooong while.
>> 
>> Agreed.  Although I feel that most of the uses of GOTO in C these days
>> occurs in the output of something like LEX and YACC, where I really don't
>> mind it.  Just as long as 'mere mortals' try to avoid using it.
> 
> I know this battle is an old chestnut, but for the record do you guys believe
> that superfluous flags and great big if-then statements are truly superior
> to the goto?


Of course not.  (I can't believe this is starting up again. [Giggle.])

For me, the hardest thing to handle is real long blocks.  You know,
the things delimited by curly braces:


  for(; foo = bar; bleep < blap)
	{
	   /* a skillion lines of code omited. */
        }

It's SO hard to figure out where the darn thing starts and where it ends.
And if their are "breaks" and "continues", yech.  When that happens,
in these long blocks, I would prefer a "done:" label at the end and
"gotos" rather than "breaks".  That way, I can at least search for the label.
Maybe we shoud start a raging argument about whether long blocks are
_considered_harmful_.  Shouldn't be much argument there.

sullivan@vsi.UUCP (Michael T Sullivan) (04/09/88)

In article <2556@ttrdc.UUCP>, levy@ttrdc.UUCP (Daniel R. Levy) writes:
> I know this battle is an old chestnut, but for the record do you guys believe
> that superfluous flags and great big if-then statements are truly superior
> to the goto?  (And the break, which is a goto by another name.)  E.g.:
> 
> 	while (loopcond) {
> 		for (i=0; i<limit; i++)
> 			if (frob(i) == TRUE)
> 				goto loopagain;	/* nice and CLEAN!!! */
> 		...
> 		/* lots and lots of code over many pages */
> 		...
> loopagain:	;
> 	}

	while (loopcond)
	{
		flag = FALSE;
		for (i=0; i<limit; i++)
		{
			if (frob(i))
			{
				flag = TRUE;
				break;
			}
		}
		if (flag)
			continue;
		...
		/* lots and lots of code over many pages */
		...
	}

You don't have to spin your wheels in a for loop and you don't have to use
the goto.  I should think if you can avoid a goto, do it.  Some people
believe gotos are inherently not "nice and CLEAN!!!".  But as you say, this
is an old chestnut.

-- 
Michael Sullivan		{uunet|attmail}!vsi!sullivan
				sullivan@vsi.com
HE V MTL

tainter@ihlpg.ATT.COM (Tainter) (04/09/88)

In article <4347@ihlpf.ATT.COM>, nevin1@ihlpf.ATT.COM (00704a-Liber) writes:
> In article <2556@ttrdc.UUCP> levy@ttrdc.UUCP (Daniel R. Levy) writes:
> |I know this battle is an old chestnut, but for the record do you guys believe
> |that superfluous flags and great big if-then statements are truly superior
> |to the goto?  (And the break, which is a goto by another name.)  E.g.:
> |
> |	while (loopcond) {
> |		for (i=0; i<limit; i++)
> |			if (frob(i) == TRUE)
> |				goto loopagain;	/* nice and CLEAN!!! */
> |		.../* lots and lots of code over many pages */...
> |loopagain:	;
> |	}
> Opinion:  this is an example of FORTRAN disguised as C.
>  In this particular case, using a continue statement
> inside in your Fortran-type example instead of a goto is much more preferable.

Except of course that that wouldn't work since it is nested under a second loop.
This is the only alternative to using a flag on the lines of the alternative
code.

[ Flag riddled code at indentation >> removed ]
> Opinion:  this is an example of Pascal disguised as C.

>  _ __			NEVIN J. LIBER	..!ihnp4!ihlpf!nevin1	(312) 510-6194

People, listen closely, GOTOs are not inherently bad.  If used carefully
as in this example they are quite reasonable and really not hard to follow.
Of course, they would be much harder to understand if they didn't use
mnemonics and instead used numbers ala Pascal or ForTran.

--j.a.tainter

djones@megatest.UUCP (Dave Jones) (04/09/88)

in article <2009@optilink.UUCP>, cramer@optilink.UUCP (Clayton Cramer) says:
> 
>> > Sometimes, gotos are perfectly justifiable because they vastly
>> > simplify and clarify you code.
>> 
>> And once in a long while, there is no better way.  A loooong while.
>> If I were running a software house, I'd be tempted to say that using
>> a goto -- except in fixing a program that already uses them -- means
>> having $50 docked from your pay.  It's not *forbidden*, you understand,
>> it's just that you have to want it really badly!
>> -- 
>> "Noalias must go.  This is           |  Henry Spencer @ U of Toronto Zoology
>> non-negotiable."  --DMR              | {allegra,ihnp4,decvax,utai}!utzoo!henry
> 
> Exactly the right approach.  The last project I supervised, the engineers
> that worked for me would occasionally try to justify a goto.  Every single
       ^^^^^^ ^^^ ^^
> time, I demonstrated that the worst they were out was an automatic variable
> and maybe a do...while construct -- usually the do...while loop and an
> appropriate automatic variable were already there.
> 
> I accept the remote possibility that goto might be appropriate somewhere --
> just as I accept the remote possibility that leprechauns exist, and we've
> just never found them.
> 
> Clayton E. Cramer

( As always, insert smilie faces after every line that irks you.
  I really don't take all of this too seriously. )

No no no.  Threatening employees with punative fines is NOT the right
approach.  I find the idea repugnant.  Blechh! I trust that Mr. Spenser 
meant only that he feels strongly that a goto is a no-no.  I don't think 
he really meant that he has to bully his employees to get them to do it 
his way. He seems like a nice enough fellow. Texan, I think.

Mr. Cramer says that he has always been able to show that adding an
automatic variable and some extra tests can obviate the goto. 
Indeed 'tis true.  There's a famous proof to that effect.
Constructive proof.  Of course the resulting code is harder 
to read than the original, but it's purged of those malicious
communist-inspired gotos.  The "come-from" problem of labels, as it 
has been called, is replaced by the "set-where" problem of SLB's 
(Silly Little Booleans).  No improvement in my estimation.  If it
were, we could just run all of those evil programs through 
a filter that exorcises the daemon gotos, and leaves only morally
correct transpicuous code.  Sorry, it ain't that easy.  

I think Mr. Cramer will find that the readers of this group may not
be quite so willing to agree that his code transformations improve
their goto examples as his employees seem to be.

I am honored to be entrusted with  maintaining some of the hardest to 
read code you have ever seen. (Trust me on this one. It's true.)
So I am something of an expert on how to write for obfuscation.
I haven't been thrown by a goto yet.  That's just control flow.
Piece of cake. If you really want to scramble some heads, screw up the
data structure definitions!

One more thing.  The way I see it, the supervisor works for the 
engineer, not the other way around.  I'm about to embark on supervising
a year-long project. We'll see if I still have that attitude next April.



I can't believe this goto thing is starting all over again.


             Dave (finished = TRUE;) Jones

djones@megatest.UUCP (Dave Jones) (04/10/88)

in article <1988Apr8.183815.3187@utzoo.uucp>, henry@utzoo.uucp (Henry Spencer) says:
> 
>> Try to pull that around here, and you'd be in the pond in about ten
>> minutes flat.
> 
> Remind me never to buy any software from you guys!
> -- 
> "Noalias must go.  This is           |  Henry Spencer @ U of Toronto Zoology
> non-negotiable."  --DMR              | {allegra,ihnp4,decvax,utai}!utzoo!henry

I fail to see any justification for such a remark.  I think an appology
is in order.

Mr. Spenser is replying to my response about about managers fining 
employees for using a goto-statement.


		Dave Jones

henry@utzoo.uucp (Henry Spencer) (04/10/88)

> ... do you guys believe
> that superfluous flags and great big if-then statements are truly superior
> to the goto? ...

Well, speaking only for myself, I believe that thought and organization are
indeed truly superior to "hack it together somehow", and that the former
approach seldom leads to gotos or "superfluous flags and great big if-then
statements" -- or to the *desire* to use either.  Don't confuse the symptoms
with the underlying disease.  The desire to use a goto is not an awful sinful
thought that should be suppressed, it is a warning that you've goofed.  The
proper response is not to kludge around it, but to stand back and re-think
the structure of the code.  (In emergencies there may not be time for this,
of course, but many things can be excused in an emergency... provided that
you go back and clean up the mess afterward.)
-- 
"Noalias must go.  This is           |  Henry Spencer @ U of Toronto Zoology
non-negotiable."  --DMR              | {allegra,ihnp4,decvax,utai}!utzoo!henry

henry@utzoo.uucp (Henry Spencer) (04/10/88)

> ... I don't think he really meant that he has to bully his employees to
> get them to do it his way.

Not a problem, since any who don't, don't stay employees :-).

> He seems like a nice enough fellow. Texan, I think.

Well, you got the longitude roughly right at least...  Saskatchewanian.

> ... The way I see it, the supervisor works for the 
> engineer, not the other way around.

Real engineers work for themselves, not for their supervisors!
-- 
"Noalias must go.  This is           |  Henry Spencer @ U of Toronto Zoology
non-negotiable."  --DMR              | {allegra,ihnp4,decvax,utai}!utzoo!henry

levy@ttrdc.UUCP (Daniel R. Levy) (04/10/88)

In article <5170@ihlpg.ATT.COM>, tainter@ihlpg.ATT.COM (Tainter) writes:
# In article <4347@ihlpf.ATT.COM>, nevin1@ihlpf.ATT.COM (00704a-Liber) writes:
# > In article <2556@ttrdc.UUCP> levy@ttrdc.UUCP (Daniel R. Levy) writes:
# > |I know this battle is an old chestnut, but for the record do you guys believe
# > |that superfluous flags and great big if-then statements are truly superior
# > |to the goto?  (And the break, which is a goto by another name.)  E.g.:
# > |	while (loopcond) {
# > |		for (i=0; i<limit; i++)
# > |			if (frob(i) == TRUE)
# > |				goto loopagain;	/* nice and CLEAN!!! */
# > |		.../* lots and lots of code over many pages */...
# > |loopagain:	;
# > |	}
# > Opinion:  this is an example of FORTRAN disguised as C.
# >  In this particular case, using a continue statement
# > inside in your Fortran-type example instead of a goto is much more preferable.
# 
# Except of course that that wouldn't work since it is nested under a second loop.
# This is the only alternative to using a flag on the lines of the alternative
# code.
# [ Flag riddled code at indentation >> removed ]
# > Opinion:  this is an example of Pascal disguised as C.
# >  _ __			NEVIN J. LIBER	..!ihnp4!ihlpf!nevin1	(312) 510-6194
# People, listen closely, GOTOs are not inherently bad.  If used carefully
# as in this example they are quite reasonable and really not hard to follow.
# Of course, they would be much harder to understand if they didn't use
# mnemonics and instead used numbers ala Pascal or ForTran.
# --j.a.tainter

Somebody mailed me a much better form of what I was trying to do:

	while (loopcond) {
		for (i=0; i<limit && frob(i)!=TRUE; i++)
			;
		if (i<limit)
			continue;
		...
	}

This IS just as clean, just as fast, and doesn't involve any gotos.  The
picture gets muddier when you have multiple nested loops however:

	while (loopcond) {
		for (i=0; i<ilimit; i++)
			for (j=0; j<jlimit; j++)
				for (k=0; k<klimit; k++)
					if (frob(i,j,k)==TRUE)
						goto loopagain;
		/* lotsa code */
loopagain:	;
	}

Getting out of this one without gotos requires continual testing of a flag
in the for loops:

	/* look ma, no gotos! */
	while (loopcond) {
		bustout=FALSE;
		for (i=0; i<ilimit && bustout==FALSE; i++)
			for (j=0; j<jlimit && bustout==FALSE; j++)
				for (k=0; k<klimit; k++)
					if (frob(i,j,k)==TRUE) {
						bustout=TRUE;
						break;
					}
		if (bustout==TRUE)
			continue;
		/* lotsa code */
	}

Trouble with this method is that you lose some performance.  What's a hacker
to do?  :-) :-) :-)
-- 
|------------Dan Levy------------|  Path: ..!{akgua,homxb,ihnp4,ltuxa,mvuxa,
|         an Engihacker @        |  	<most AT&T machines>}!ttrdc!ttrda!levy
|     AT&T Data Systems Group    |  Disclaimer?  Huh?  What disclaimer???
|--------Skokie, Illinois--------|

decot@hpisod2.HP.COM (Dave Decot) (04/10/88)

> For me, the hardest thing to handle is real long blocks.  You know,
> the things delimited by curly braces:
> 
> 
>   for(; foo = bar; bleep < blap)
> 	{
> 	   /* a skillion lines of code omited. */
>         }
> 
> It's SO hard to figure out where the darn thing starts and where it ends.
> And if their are "breaks" and "continues", yech.  When that happens,
> in these long blocks, I would prefer a "done:" label at the end and
> "gotos" rather than "breaks".  That way, I can at least search for the label.
> 
> Maybe we shoud start a raging argument about whether long blocks are
> _considered_harmful_.  Shouldn't be much argument there.

Yes.  The solution is not to introduce a label; it is to break up the long
blocks into appropriate separate functions.

Dave "I use gotos to get fully out of nested loops" Decot
hpda!decot

gwyn@brl-smoke.ARPA (Doug Gwyn ) (04/10/88)

In article <449@goofy.megatest.UUCP> djones@megatest.UUCP (Dave Jones) writes:
-in article <1988Apr8.183815.3187@utzoo.uucp>, henry@utzoo.uucp (Henry Spencer) says:
->> Try to pull that around here, and you'd be in the pond in about ten
->> minutes flat.
-> Remind me never to buy any software from you guys!
-I fail to see any justification for such a remark.  I think an appology
-is in order.

I don't agree.  Henry is simply remarking that he doesn't have much
trust in software produced by people who take pride in using GOTOs.
That seems an eminently defensible position to me.

daveb@geac.UUCP (David Collier-Brown) (04/11/88)

In article <reference lost> djones@megatest.UUCP (Dave Jones) writes:
>>> Try to pull that around here, and you'd be in the pond in about ten
>>> minutes flat.

In article <1988Apr8.183815.3187@utzoo.uucp>, henry@utzoo.uucp (Henry Spencer) says:
>> Remind me never to buy any software from you guys!

In article <449@goofy.megatest.UUCP> djones@megatest.UUCP (Dave Jones) writes:
>I fail to see any justification for such a remark.  I think an appology [sic]
>is in order.

   Quite the contrary: you owe Mr. Spenser an apology for whining: It
is not good form to complain when someone points out you've admitted
in a **public forum** your willingness to enshrine known bad
practice.
    For shame!

--dave (I use goto's && Henry can fine me) c-b
-- 
 David Collier-Brown.                 {mnetor yunexus utgpu}!geac!daveb
 Geac Computers International Inc.,   |  Computer Science loses its
 350 Steelcase Road,Markham, Ontario, |  memory (if not its mind) 
 CANADA, L3R 1B3 (416) 475-0525 x3279 |  every 6 months.

henry@utzoo.uucp (Henry Spencer) (04/12/88)

> >> Try to pull that around here, and you'd be in the pond in about ten
> >> minutes flat.
> 
> > Remind me never to buy any software from you guys!
> 
> I fail to see any justification for such a remark.  I think an appology
> is in order.

Sorry, I consider the remark well-justified and will not apologize.  If
you read my other postings on the subject, you will see that I consider
the use of gotos, especially the frequent use of gotos, to be a sign of
poor organization and "coding before thinking".  Given this opinion, it
is hardly surprising that I would be reluctant to buy software from an
organization which endorses routine use of gotos.
-- 
"Noalias must go.  This is           |  Henry Spencer @ U of Toronto Zoology
non-negotiable."  --DMR              | {allegra,ihnp4,decvax,utai}!utzoo!henry

al@gtx.com (0732) (04/12/88)

->to the goto?  (And the break, which is a goto by another name.)  E.g.:

a quibble here. a break is a "goto by another name" as much as a while
loop is a "goto by another name".  In fact a break is a considerably
restricted form of a goto, and it is this restriction that makes it
easier to read and understand, and not at all comparable to those awful
unrestricted goto's.

By the way, this discussion reminds me of a letter that appeared a few
years ago in CACM.  ,It was from a man in Japan named Mr. Goto, and
it was a complaint about how everyone was always trying to eliminate him.

  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 ( Alan Filipski, GTX Corp, 8836 N. 23rd Avenue, Phoenix, Arizona 85021, USA )
 ( {ihnp4,cbosgd,decvax,hplabs,amdahl,nsc}!sun!sunburn!gtx!al  (602)870-1696 )
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

mick@auspyr.UUCP (Michael J. Andrew) (04/12/88)

In article <1988Apr5.213343.1528@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes:
>> Sometimes, gotos are perfectly justifiable because they vastly
>> simplify and clarify you code.
>
>And once in a long while, there is no better way.  A loooong while.
>If I were running a software house, I'd be tempted to say that using
>a goto -- except in fixing a program that already uses them -- means
>having $50 docked from your pay.  It's not *forbidden*, you understand,
>it's just that you have to want it really badly!

This is a excellent extension to a scheme I keep proposing half-
seriously to management, to encourage good programming
practices among novice, sloppy or lazy programmers.

Provide each member of the team a $500 bonus at the start of a new
project, but deduct $50 each time a global variable is introduced
into the design.

Wh
-- 
-------------------------------------------------------------------------
Michael Andrew		Sr. Systems Engineer	Austec, Inc.  San Jose CA.
mick@aussjo.UUCP				(408) 279 5533

cik@l.cc.purdue.edu (Herman Rubin) (04/12/88)

Here is a challenge to the denigrators of goto.  I present a short fragment of
code; this code should be modified if right shifts are negative left shifts,
but the problems are the same. 

Case 5:	b >>= g16;
	m |= b;
	x = *(--geom);
	if (TEST)
		{if(ODD(x)) goto Case2; else goto Case1;};
	else {g4 = (x+1)/2; if(ODD(x)) goto Case3; else goto Case4;};

I claim that this construction is easily understood, except possibly  by those
who are anti goto, and is efficient code.  TEST involves a random bit, and
geom is a pointer to a random quantity, so that one can not anticipate the
values.  Also each of the Cases 1-4 are more likely to be reached in other
ways than from Case 5.

How else would you do it?
-- 
Herman Rubin, Dept. of Statistics, Purdue Univ., West Lafayette IN47907
Phone: (317)494-6054
hrubin@l.cc.purdue.edu (ARPA or UUCP) or hrubin@purccvm.bitnet

edw@IUS1.CS.CMU.EDU (Eddie Wyatt) (04/13/88)

 > 
 > Case 5:	b >>= g16;
 > 	m |= b;
 > 	x = *(--geom);
 > 	if (TEST)
 > 		{if(ODD(x)) goto Case2; else goto Case1;};
 > 	else {g4 = (x+1)/2; if(ODD(x)) goto Case3; else goto Case4;};
 > 
	....
 >  Also each of the Cases 1-4 are more likely to be reached in other
 > ways than from Case 5.
 > 
 > How else would you do it?

	FUNCTIONS!!!! 


-- 

Eddie Wyatt 				e-mail: edw@ius1.cs.cmu.edu

djones@megatest.UUCP (Dave Jones) (04/13/88)

in article <1988Apr11.201934.20594@utzoo.uucp>, henry@utzoo.uucp (Henry Spencer) says:
> 
>> >> Try to pull that around here, and you'd be in the pond in about ten
>> >> minutes flat.
>> 
>> > Remind me never to buy any software from you guys!
>> 
>> I fail to see any justification for such a remark.  I think an apology
>> is in order.
> 
> Sorry, I consider the remark well-justified and will not apologize.  If
> you read my other postings on the subject, you will see that I consider
> the use of gotos, especially the frequent use of gotos, to be a sign of
> poor organization and "coding before thinking".  Given this opinion, it
> is hardly surprising that I would be reluctant to buy software from an
> organization which endorses routine use of gotos.
> -- 
> "Noalias must go.  This is           |  Henry Spencer @ U of Toronto Zoology
> non-negotiable."  --DMR              | {allegra,ihnp4,decvax,utai}!utzoo!henry


I should not say any more about this, but I can not restrain myself.

My flip remark about the dousing of stuffed shirts was ill judged.
In my defense, let me say that it never occurred to me that Mr. Spencer 
was serious about fining employees for using a goto statement.
I incorrectly thought that I was continuing a joke which he had started.

I did make the postings in good faith, in the sincere expectation of
casting some light on a subject which reappears in the group from time
to time.   Unlike the redoubtable Mr. Spencer, I do not pretend to make 
judgemental pronouncements about the quality of thought of those who use 
or do not use an occasional goto.  But I feel that my seventeen years of 
experience programming,  and my experiences a university computer science 
professor give me some perspective, if nothing else.

Mr Spencer, Mr. David Brown, and the loquacious Mr. Gwyn all say straight 
out that I am an advocate of the use of the goto statement.
But I never once in any of my postings endorsed the use of the goto 
statement!  You may verify as much if you will reread the postings.
(In one posting I said that if I have to read long long blocks,
I would prefer that they be exited by a goto rather than a "break",
simply because it's easier to find the label than it is to find
the closing curly brace.  This "lesser of two evils" is hardly an
endorsement.)  I only stated that the importance which some people place
on avoiding the gotos is exceedingly exaggerated, and that time spent
campaigning against its use is misspent. This is an opinion which I 
still hold. 

But all this is quite incidental.  Mr. Spencer is entitled to his
opinions about programming techniques, as am I. 
I objected not to Mr. Spencer's mistaken reading of my postings.  
I objected to his affrontary.

You three, Spencer, Brown, and Gwyn, hold that it is proper for you to 
publicly criticize the software produced by the company which employs me, 
on the basis of a few lines that I wrote here.  To presume that
you are competent to judge products you have never used is 
ridiculous.  To presume to make such pronouncements publicly is,
by my values, rude at best. Perhaps I should only say that we have 
differing values not only about some  small software engineering matters, 
but also about what constitutes  good manners and acceptable behavior.

I find this whole matter very distasteful.  I regret having provoked it.

I'm through with comp.lang.c for a while.

levy@ttrdc.UUCP (Daniel R. Levy) (04/13/88)

In article <1988Apr11.201934.20594@utzoo.uucp>, henry@utzoo.uucp (Henry Spencer) writes:
> > >> Try to pull that around here, and you'd be in the pond in about ten
> > >> minutes flat.
> > 
> > > Remind me never to buy any software from you guys!
> > 
> > I fail to see any justification for such a remark.  I think an appology
> > is in order.
> 
> Sorry, I consider the remark well-justified and will not apologize.  If
> you read my other postings on the subject, you will see that I consider
> the use of gotos, especially the frequent use of gotos, to be a sign of
> poor organization and "coding before thinking".  Given this opinion, it
> is hardly surprising that I would be reluctant to buy software from an
> organization which endorses routine use of gotos.

You darn well know, if you'd take off your elitist blinders, that the use
of gotos is not an INFALLIBLE sign of "poor organization and 'coding before
thinking'".  Indeed it could well be that Dave Jones and his buddies at
Megatest, in spite of their gotos, may produce code with more functionality,
fewer bugs, and better support than you do, but you'd never know it if you
won't give them a chance to show it.  Gotos are only one metric of style, in
sparse use only weakly related to functionality and bugproofness, and to
declare code that uses them anathema as a matter of broad policy is like
using the Whetstone as your sole criterion for purchasing a computer.

It makes a lot more sense to judge a software producer on their reputation
for other software they have produced, than to judge them on a tiny aspect
of coding style.  There are just too many other variables.  If you are ever
in a position to purchase Megatest's (or any other company's) software, ask
around about how well that company's software (not just the package in
question) has worked in the past and how well it is supported.  Any other
criterion of quality is pure conjecture.
-- 
|------------Dan Levy------------|  Path: ..!{akgua,homxb,ihnp4,ltuxa,mvuxa,
|         an Engihacker @        |  	<most AT&T machines>}!ttrdc!ttrda!levy
|     AT&T Data Systems Group    |  Disclaimer?  Huh?  What disclaimer???
|--------Skokie, Illinois--------|

edw@IUS1.CS.CMU.EDU (Eddie Wyatt) (04/13/88)

In article <451@goofy.megatest.UUCP>, djones@megatest.UUCP (Dave Jones) writes:

> I find this whole matter very distasteful.  I regret having provoked it.
> 
> I'm through with comp.lang.c for a while.


  Please, please, please don't go :-).  Seriously Dave, don't let it get
to you.  No matter what you do on this net, you're bound to piss someone
off eventually.  Hell, I've been exclaimed, I've been ignored and I've
been flamed - I should know.  My attitude has always been to learn from my
mistake or at least try to understand the other persons perspective.  In
doing so I've learned alot and I'm thankful for that.

  In your case, you'll just have to understand that there are
people that have very strong feelings about the use goto.  I advised
you to at least consider what they have to say.

BTW: I would have mailed to you directly but there's no return mailing
path in you signature.
-- 

Eddie Wyatt 				e-mail: edw@ius1.cs.cmu.edu

dhesi@bsu-cs.UUCP (Rahul Dhesi) (04/14/88)

In article <451@goofy.megatest.UUCP> djones@megatest.UUCP (Dave Jones) writes:
>I only stated that the importance which some people place
>on avoiding the gotos is exceedingly exaggerated, and that time spent
>campaigning against its use is misspent.

This is indeed very true.  It is not always wise to simply criticize
gotos instead of asking why a goto was necessary.   It could be lousy
algorithm design or, more commonly than you think, less-than-perfect
programming language design.  Some things are best done with a goto!
And I know of no language, with the possible exception of Ada, that is
rich enough in control structures to always have an elegant and
efficient alternative to using a goto.

The best collection of thoughts I have seen on this issue is by Donald
Knuth, entitled "Structured Programming with goto Statements",
originally published in one of the ACM journals (probably Computing
Surveys) circa 1974 and republished by Prentice Hall in 1977 in
"Current Trends in Programming Methodology" volume I, edited by Raymond
T. Yeh.
-- 
Rahul Dhesi         UUCP:  <backbones>!{iuvax,pur-ee,uunet}!bsu-cs!dhesi

gwyn@brl-smoke.ARPA (Doug Gwyn ) (04/14/88)

In article <451@goofy.megatest.UUCP> djones@megatest.UUCP (Dave Jones) writes:
>Mr Spencer, Mr. David Brown, and the loquacious Mr. Gwyn all say straight 
>out that I am an advocate of the use of the goto statement.

There you go, putting (wrong) words in other peoples' mouths.

>You three, Spencer, Brown, and Gwyn, hold that it is proper for you to 
>publicly criticize the software produced by the company which employs me, 
>on the basis of a few lines that I wrote here.

Ditto.  I merely maintained that it is appropriate for Henry to
think poorly of a company that publicly announces its liberal use
of GOTO with apparent pride.  If that's not what you intended to do,
then Henry and I must have misunderstood you.

I use GOTO myself, but only in a disciplined way and only when there
are sound technical reasons for so doing.  (Branching to a common
section of error-recovery code at the end of a function body is the
most usual situation.)  But I'm not going to wear a lapel pin that
proclaims "I USE GOTOS"!

My, how touchy people get when they think that money is involved.

levy@ttrdc.UUCP (Daniel R. Levy) (04/14/88)

In article <748@l.cc.purdue.edu>, cik@l.cc.purdue.edu (Herman Rubin) writes:
# 
# Here is a challenge to the denigrators of goto.  I present a short fragment of
# code; this code should be modified if right shifts are negative left shifts,
# but the problems are the same. 
# 
# Case 5:	b >>= g16;
# 	m |= b;
# 	x = *(--geom);
# 	if (TEST)
# 		{if(ODD(x)) goto Case2; else goto Case1;};
# 	else {g4 = (x+1)/2; if(ODD(x)) goto Case3; else goto Case4;};

Gak, what IS this?  Where are the Case[1-4] labels even?  This IS raunchy code.
(Are you trying to hand-code a state machine?)
-- 
|------------Dan Levy------------|  Path: ..!{akgua,homxb,ihnp4,ltuxa,mvuxa,
|         an Engihacker @        |  	<most AT&T machines>}!ttrdc!ttrda!levy
|     AT&T Data Systems Group    |  Disclaimer?  Huh?  What disclaimer???
|--------Skokie, Illinois--------|

root@mfci.UUCP (SuperUser) (04/14/88)

Expires:

Sender:

Followup-To:

Distribution:

Keywords:


I feel that taking a near religious stance on the prohibition of
something like goto is a mistake, although I can understand why
people are tempted.  Few would argue that the proper use of
functions, compound statements, and flow control statements isn't
preferable to long rambling routines whose control structures
resemble a tangled ball of fishing line.  Avoiding the use of gotos
is probably a good rule of thumb for beginning programmers or
programmers who have only used languages like Basic or Fortran,
to get them used to the fact that they can do just about anything
without using gotos and without contorting their program structure
(avoiding gotos usually improves program structure).

However, the most important goals in writing code are that it
functions properly, that it is clearly written and maintainable,
and that it is reasonably efficient.  Of course, there may sometimes
be a tradeoff between the last two goals, but in many cases where a
goto may be appropriate it is often in the interests of both these
goals.

The most common place where the use of a goto is not inappropriate in
C is when it is used to exit multiple levels of nested loops or other
such control structures.  Some languages permit constructs such as
"break n" to accomplish this, but I generally consider this sort of
practice to be bad, because it is painful to maintain.  I.e., if you
wanted to wrap it in a loop, or remove a loop from around it, you
would have to delve into the code to alter the "level" of the break.
I prefer to achieve the effect of a the LEAVE expression of Bliss.
This is a STRUCTURED construct, in that it cannot be used to create
irreducible flow graphs (all Bliss flow graphs are reducible).  It
can only be used to exit an expression from anywhere within the
expression, and is no different from returning from a routine within
a loop, except that you are merely exiting from a statement rather
than the entire routine.  In C, the same effect can be achieved by
placing a label right after a loop, then branching to the label
from within one or more nested loops.  The resulting flow graph
is still reducible, and avoids the use of flow control flags, which
almost always obscure the code, and often slow it down as well.
(This isn't to say that I think flow control flags are always
inappropriate, but in most typical cases it is preferable to replace
them with explicit exits, via goto.)

Many other uses of goto are probably best avoided, such as branching into
loops.  Often the need to branch into a loop arises because the loop
is naturally a "mid-tested" loop, in which case it can be rewritten
as a for(;;) { ... } loop, with an explicit exit test in the middle.
In cases where the loop really has multiple entry points, it is up to
the implementor to decide whether it can be restructured to avoid the
problem, or whether it's worth explicitly adjusting the various cases
before the loop so they can all enter at the same point, or whether
it's worth entirely replicating the loop, etc.  However, people should
realize that if their code incorporates irreducible loops, their compiler
may not do a good job of optimizing it.  I have seen rare examples where
an irreducible loop is the clearest way to code something, although even
in those cases it is usually preferable to avoid them.  However, I would
not go so far as to say they are 100% wrong and should NEVER be used.
For example, I have seen people implement small state machines with
gotos, where each state explicity branches to the next state, rather
than having to go through the overhead of a switch statement at the
top of an outer loop.  This can be useful in small, simple lexical
analyzers.  True, keeping the state in a variable which is used in
a switch statement probably isn't that much slower, and could even
be faster in some cases (if the compiler does a better job of optimizing
reducible loops), but nevertheless it may not always be the best choice.

The other case I can think of where a goto might be appropriate is if
you have a complicated loop which is making some determination about
something, and at various points in the loop it may "accept" or "reject"
something, in which case you'd like to go to some common piece of code to
perform the necessary bookkeeping.  Ideally the loop would be contained
in a routine which simply returns true or false and leaves it up to the
caller to take whatever action is appropriate, but again this may not
always be practical.  In this case I would argue that the code being
branched to should be placed outside of the code that branches to it
(rather than coding it as the consequent of one test and then branching
to it from the others).  However, the end of it should not turn around
and branch back into a loop or whatever, but should instead return
from the routine or fall through to the bottom of a loop or to some
ordinary sequential code which follows it, etc.

All this isn't meant to imply that I like gotos and that they don't bother
me.  I very rarely use them, and in cases where I do it is because I have
carefully investigated the alternatives and been unable to eliminate
them without compromising the control structure of my code in even
less desirable ways.  Nevertheless, if used with restraint they do
have their places.

daveb@geac.UUCP (David Collier-Brown) (04/14/88)

In article <1988Apr11.201934.20594@utzoo.uucp>, henry@utzoo.uucp (Henry Spencer) writes:
> Remind me never to buy any software from you guys!

In article <2575@ttrdc.UUCP> levy@ttrdc.UUCP (Daniel R. Levy) writes:
>You darn well know, if you'd take off your elitist blinders, that...

Gentlemen!
   Look back at the discussion to date before throwing assuming
Henry's being nasty: he was defending a proposal to charge $50.00
per goto, to discourage misuse.  The other gentleman was threatening
to throw him in the duckpond (:-).  This was a good-natured, if
spirited, debate.

   I like the $50.00 scheme, actually, although I do use gotos[1].
I figure it (the $50.00) is a good example of making engineering
tradeoffs explicit.

 --dave (a philosopher on the engineering faculty council...) c-b

[1] In time-critical inner loops to avoid returns, typically. See
    Knuth "Structured Programming with Go To Statements".
-- 
 David Collier-Brown.                 {mnetor yunexus utgpu}!geac!daveb
 Geac Computers International Inc.,   |  Computer Science loses its
 350 Steelcase Road,Markham, Ontario, |  memory (if not its mind) 
 CANADA, L3R 1B3 (416) 475-0525 x3279 |  every 6 months.

levy@ttrdc.UUCP (Daniel R. Levy) (04/14/88)

In article <7681@brl-smoke.ARPA>, gwyn@brl-smoke.ARPA (Doug Gwyn ) writes:
# In article <451@goofy.megatest.UUCP> djones@megatest.UUCP (Dave Jones) writes:
# >Mr Spencer, Mr. David Brown, and the loquacious Mr. Gwyn all say straight 
# >out that I am an advocate of the use of the goto statement.
# 
# There you go, putting (wrong) words in other peoples' mouths.
# 
# >You three, Spencer, Brown, and Gwyn, hold that it is proper for you to 
# >publicly criticize the software produced by the company which employs me, 
# >on the basis of a few lines that I wrote here.
# 
# Ditto.  I merely maintained that it is appropriate for Henry to
# think poorly of a company that publicly announces its liberal use
# of GOTO with apparent pride.  If that's not what you intended to do,
# then Henry and I must have misunderstood you.

Begging your pardon, unless Dave posted an article I never saw, the strongest
thing he ever said which would tend to lead one to believe his company
liberally uses GOTO was something to the effect that "You'd get laughed into
the pond in ten minutes if you tried that here" [pay-docking mind games to
sear the fear of GOTO into every programmer's heart].  From what I see,
Spencer especially took that as a endorsement of liberal use of GOTO at
Megatest.  (And even I went along with that notion [viz. an earlier posting of
mine saying "so what if he does use lots of GOTOs?  that's not the only valid
metric of code"] till I looked more carefully at what was actually being said.)
YOU should talk about putting "(wrong)" words into other peoples' mouths!
(Or wrong thoughts into other people's heads, or wrong lines into other
peoples' code.)
-- 
|------------Dan Levy------------|  Path: ..!{akgua,homxb,ihnp4,ltuxa,mvuxa,
|         an Engihacker @        |  	<most AT&T machines>}!ttrdc!ttrda!levy
|     AT&T Data Systems Group    |  Disclaimer?  Huh?  What disclaimer???
|--------Skokie, Illinois--------|

daveb@geac.UUCP (David Collier-Brown) (04/14/88)

  Before sending that last-referenced message, I admit to have
launched a flame.
  Sorry!

  I cancelled it. You shouldn't get it.  If you do, ignore it. If
you can't ignore it, send mail to my boss.

--dave (I gotta pay more attention to what's said, not how) c-b
-- 
 David Collier-Brown.                 {mnetor yunexus utgpu}!geac!daveb
 Geac Computers International Inc.,   |  Computer Science loses its
 350 Steelcase Road,Markham, Ontario, |  memory (if not its mind) 
 CANADA, L3R 1B3 (416) 475-0525 x3279 |  every 6 months.

gwyn@brl-smoke.ARPA (Doug Gwyn ) (04/15/88)

In article <2586@ttrdc.UUCP> levy@ttrdc.UUCP (Daniel R. Levy) writes:
>Spencer especially took that as a endorsement of liberal use of GOTO at
>Megatest.

That was also the impression I got when I read the same posting.
That doesn't mean that it was intended to convey that impression,
but as we should all well know by now it is easy to be misinterpreted.

I don't think I have accused that company of shoddy workmanship or
urged boycotting its products.  I've been defending Henry's right
to draw such conclusions for himself.  It was rather tactless to
post those conclusions publicly, but originally I don't think Henry
was really urging a product boycott either, just remarking on what
he thought the likely effect on product quality would be from what
he perceived as the corporate attitude.

I'm glad to hear that that company (whose name I don't recall) is
not committed to indiscriminate use of GOTO.  I also agree with those
who say that GOTO use is not the only measure of software merit.

Now, can we please stop misunderstanding each other and get back
to squabbling about TECHNICAL issues?

campbell@maynard.BSW.COM (Larry Campbell) (04/15/88)

In article <2618@bsu-cs.UUCP> dhesi@bsu-cs.UUCP (Rahul Dhesi) writes:
<>...And I know of no language, with the possible exception of Ada, that is
<>rich enough in control structures to always have an elegant and
<>efficient alternative to using a goto.

Check out BLISS.  It's not without its flaws -- I consider its extreme
typelessness a botch -- but it has such a complete set of well thought
out control constructs that you don't miss the goto at all.  (BLISS has
no goto.)
-- 
Larry Campbell                                The Boston Software Works, Inc.
Internet: campbell@maynard.bsw.com          120 Fulton Street, Boston MA 02109
uucp: {husc6,mirror,think}!maynard!campbell         +1 617 367 6846

henry@utzoo.uucp (Henry Spencer) (04/16/88)

> The best collection of thoughts I have seen on this issue is by Donald
> Knuth, entitled "Structured Programming with goto Statements"...

The amusing thing about Knuth's article is that when you subtract out the
search loops (which can be handled with break or return), the syntax
example (which can be done *much* more elegantly using ungetc()), and the
things that any modern compiler (NB the 4BSD VAX compiler is an antique)
would look after for you... there's nothing left!

Also left as an exercise for the reader is finding the bug in Knuth's
hash-table-search code.  (He might possibly have corrected this in the
reprint; my copy is the original Computing Surveys paper.)  The hazards
of gotos doth make fools of the best of us...
-- 
"Noalias must go.  This is           |  Henry Spencer @ U of Toronto Zoology
non-negotiable."  --DMR              | {allegra,ihnp4,decvax,utai}!utzoo!henry

nevin1@ihlpf.ATT.COM (00704a-Liber) (04/16/88)

First off Herman, I want to thank you for giving an example of why GOTO's
should NOT be used indiscriminately!

In article <748@l.cc.purdue.edu> cik@l.cc.purdue.edu (Herman Rubin) writes:

>Here is a challenge to the denigrators of goto.  I present a short fragment of
>code; this code should be modified if right shifts are negative left shifts,
>but the problems are the same. 

>Case 5:	b >>= g16;
>	m |= b;
>	x = *(--geom);
>	if (TEST)
>		{if(ODD(x)) goto Case2; else goto Case1;};
>	else {g4 = (x+1)/2; if(ODD(x)) goto Case3; else goto Case4;};

You should enter the whole program in the Obfuscated C contest!  As long as
it's under 1536 characters, it's sure to win!! :-)  If you can't enter it,
wait for the BASIC-disguised-as-C Contest!  :-)

>I claim that this construction is easily understood, except possibly  by those
>who are anti goto, and is efficient code.  TEST involves a random bit, and
>geom is a pointer to a random quantity, so that one can not anticipate the
>values.  Also each of the Cases 1-4 are more likely to be reached in other
>ways than from Case 5.

I cannot, simply by looking at it, tell what it's supposed to do.  60% or
more of the work of programming should go into design and NOT coding, as it
seems like it was done here.

>How else would you do it?

I don't know.  If I had a good design spec of what the *whole* program is
supposed to do I could probably write it in a C-like readable fashion
without using a single GOTO.  But don't expect me to rewrite a code
fragment which is obviously totally dependent on GOTOs.


Off the subject:
For those of you who don't read comp.lang.misc:  Herman has claimed
that he can write a much better language than anything we have now,
provided he can find someone to write the compiler for him.  I, among
others, have volunteered my time to help him on his quest and we are
waiting for him to finish his *formal* detailed description of the
language.  So please don't bother him until *after* he completes this
historical document.  He's keeping the whole world on hold!!

-- 
 _ __			NEVIN J. LIBER	..!ihnp4!ihlpf!nevin1	(312) 510-6194
' )  )				"The secret compartment of my ring I fill
 /  / _ , __o  ____		 with an Underdog super-energy pill."
/  (_</_\/ <__/ / <_	These are solely MY opinions, not AT&T's, blah blah blah

garys@bunker.UUCP (Gary M. Samuelson) (04/16/88)

In article <748@l.cc.purdue.edu> cik@l.cc.purdue.edu (Herman Rubin) writes:
>
>Here is a challenge to the denigrators of goto.

I am not sure I qualify, absolutely, but how about:

Case 5:	b >>= g16;
	m |= b;
	x = *(--geom);
	if (TEST)
	{	
		if(ODD(x))
			Case2();
		else
			Case1();
	}
	else
	{
		g4 = (x+1)/2;
		if(ODD(x))
			Case3();
		else
			Case4();
	}

Readability improved through indentation at no extra charge.
Extraneous semi-colons tossed also.  And, yes, I normally do
such things when I have to deal with ugly code.

Now give me something hard.

Gary Samuelson

nevin1@ihlpf.ATT.COM (00704a-Liber) (04/16/88)

In article <2581@geac.UUCP> daveb@geac.UUCP (David Collier-Brown) writes:
>   I like the $50.00 scheme, actually, although I do use gotos[1].
>I figure it (the $50.00) is a good example of making engineering
>tradeoffs explicit.

I don't like the scheme, because I would rather find a way around using GOTO
than pay the $50.
-- 
 _ __			NEVIN J. LIBER	..!ihnp4!ihlpf!nevin1	(312) 510-6194
' )  )				"The secret compartment of my ring I fill
 /  / _ , __o  ____		 with an Underdog super-energy pill."
/  (_</_\/ <__/ / <_	These are solely MY opinions, not AT&T's, blah blah blah

cik@l.cc.purdue.edu (Herman Rubin) (04/16/88)

In article <3470@bunker.UUCP>, garys@bunker.UUCP (Gary M. Samuelson) writes:
> In article <748@l.cc.purdue.edu> cik@l.cc.purdue.edu (Herman Rubin) writes:
> >
> >Here is a challenge to the denigrators of goto.
> 
> I am not sure I qualify, absolutely, but how about:
> 
> Case 5:	b >>= g16;
> 	m |= b;
> 	x = *(--geom);
> 	if (TEST)
> 	{	
> 		if(ODD(x))
> 			Case2();
> 		else
> 			Case1();
> 	}
> 	else
> 	{
> 		g4 = (x+1)/2;
> 		if(ODD(x))
> 			Case3();
> 		else
> 			Case4();
> 	}
> 
> Readability improved through indentation at no extra charge.
> Extraneous semi-colons tossed also.  And, yes, I normally do
> such things when I have to deal with ugly code.
> 
> Now give me something hard.
> 
> Gary Samuelson

--For those who have not seen the original posting, replace
	Casej() 	by	goto Casej.		---------

I have no qualms with using or not using indentations.  Also I think that
the initial use of semi-colons by C was a mistake, and rather than getting
obscure error messages, I admit I use too many.  Now to the main point.

I stated that this was a _fragment_ of code.  After leaving Case5, this
part of the code is not reached again until entered in the generation of
a new item.  That is, after going to one of the other cases, this block of
code is _not_ to be returned to.  Also, the cost of a subroutine call is
huge compared with the cost of a goto.

One of those responding by mail correctly deduced the original procedure,
which can easily be written without gotos.  The actual procedure as I would
code it uses gotos even more, as it can be recognized that certain information
may be in a reusable form.  For example, instead of 

	*(geom++) = z;

in one case, followed by reading the item in the transferred case, just goto
the intermediate step.

The idea of the whole section of code, in a non-goto format, with most of the
details omitted, as follows:  (Please ignore C grammatical errors.)
	
	{if(w==3)
		{i=3; g4=1; break}
	else if (EVEN(w)){....}
	else if(w==5)ABORT;
	else .....}

	while(i>1)
	{switch(i)
		case 2: b >>= *(--geom); m |= b; i=1; break;
		case 3: (details omitted)
		case 4: (details omitted)
		case 5: as in the posted code, except goto Casej is replaced
			by i = j; break;
		case 6: (details omitted)
		case 7: (details omitted)
		default: (details omitted)}
	
	termination code (details omitted)

A simple analysis of the instructions generated shows that much of the time is
spent in storing the value of i (even if you can get your compiler to put it
into a register) and carrying out the switch comparisons.  In addition, there
are many ways to combine operations using the structure of the code, and 
knowledge of the algorithm, to eliminate unnecesary transfers.  The goto-less
code has at least twice as many machine goto instructions as the goto code for
the transfers to casej, and each there is an additional comparison instruction
for each case move.  I deliberately eliminated the storage of i for i<8.

When your optimizing compiler can convert case switches with case numbers 
generated into the more efficient code such as I would write, I will consider
eliminating those gotos.  Alternatively, those features may be added to the
language.  However, I cannot see how even the most brilliant optimizing 
compiler could see some of the other uses of goto in the algorithm.

There seems to be far more that the algorithm producer can think of than the
language designer realizes is pos

henry@utzoo.uucp (Henry Spencer) (04/17/88)

> You darn well know, if you'd take off your elitist blinders, that the use
> of gotos is not an INFALLIBLE sign of "poor organization and 'coding before
> thinking'"...

Oh, I'll concede the possibility.  But I've never found a clear example in
code that I've either (a) written, or (b) analyzed thoroughly.
-- 
"Noalias must go.  This is           |  Henry Spencer @ U of Toronto Zoology
non-negotiable."  --DMR              | {ihnp4,decvax,uunet!mnetor}!utzoo!henry

henry@utzoo.uucp (Henry Spencer) (04/17/88)

> <>...And I know of no language, with the possible exception of Ada, that is
> <>rich enough in control structures to always have an elegant and
> <>efficient alternative to using a goto.
> 
> Check out BLISS...

Don't forget the Unix shell.  (The standard one, not the silly thing from
Berkeley.)
-- 
"Noalias must go.  This is           |  Henry Spencer @ U of Toronto Zoology
non-negotiable."  --DMR              | {ihnp4,decvax,uunet!mnetor}!utzoo!henry

peter@athena.mit.edu (Peter J Desnoyers) (04/17/88)

In article <751@l.cc.purdue.edu> cik@l.cc.purdue.edu (Herman Rubin) writes:
>When your optimizing compiler can convert case switches with case numbers 
>generated into the more efficient code such as I would write, I will consider
>eliminating those gotos. 

I don't know about optimizing compilers, but I've heard horror stories
of non-optimizing compilers using jumptables for switch statements.
(Oh no!! Why does "switch (n) {case 0: foo(); case 20000: bar();}" generate
an 80k executable?) It may have been an older VMS compiler. I dunno...

Personally, I think that doing such grevious harm to the source code
in the name of 'optimizing' is off the mark. The time spent writing
and maintaining that code could have been spent (1) buying an
optimizing compiler; (2) writing it in assembler; or (3) convincing
your boss to spring for a faster machine. 

Perhaps a better thing than docking people's pay for 'goto's would be
a compiler that put a delay in with every goto. Ten or twenty nop's
should be about right. Then people would only use goto when it was
really needed for stylistic reasons.

btw, my favorite reason for using goto - to cope with the problem that
the same word (break) is used to terminate loops and to signal the end
of a section of a switch. Thus you can write "if (foo) break;", but
you may have reason to write:
					(what you want to write: )
  while (foo)				while (foo)
    switch (bar)			  switch (bar)
    {					  {
      case n: 				    case n:
	goto (end_while); 		      break;
	break;				      esac; /* or whatever */
    }					  }
  end_while:

				Peter Desnoyers
				peter@athena.mit.edu

ajmyrvold@violet.waterloo.edu (Alan Myrvold) (04/17/88)

Why do I use goto's ? 

Because I believe that every function should have 
exactly one entry point and exactly one exit point.

Multiple RETURN statements are as bad as bad goto's -- i.e.
the thread of the subroutine gets confusing.

I only have labels at the end of my functions, and yes 
the real problem with neat code with goto's is that it is soooo easy
for someone else to start inserting code on the wrong side 
of the goto. But don't dock my pay for eliminating RETURN statements
that are scattered through a subroutine.  :-)

-------------------------------------------------------------------
Si je t'aime? Bien sur que je t'aime! Ne suis-je pas en train de
te le prouver encore une fois, dans ce lit? 
-------------------------------------------------------------------
Alan Myrvold     ajmyrvold@violet.waterloo.edu
-------------------------------------------------------------------

purtill@faline.bellcore.com (Mark Purtill) (04/18/88)

In article <> ajmyrvold@violet.waterloo.edu (Alan Myrvold) writes:
>Why do I use goto's ? 
>
>Because I believe that every function should have 
>exactly one entry point and exactly one exit point.
>
>Multiple RETURN statements are as bad as bad goto's -- i.e.
>the thread of the subroutine gets confusing.

First off, I find this claim dubious to say the least, especially
if many returns are error returns (eg:

	char *
get_foo( char *filename) { 	/* returns the foo or NULL on error */
	...
	if(( fp = fopen( filename, mode)) == NULL) {
		return (char *)NULL ;
		}
	...
	if( syntax error in the foo) return (char *)NULL ;
	...
	return foo ;
	}
).


In any case, I fail to see how replacing a "return" with a "goto" will
make it any less confusing, especially given that the label for the goto
may be on the next page, or that the next person to deal with the code
may add code after the label, etc.  All you've done is replace earlier
"return"s with "goto label"s which may not really do what you want.

^.-.^ Mark Purtill
((")) purtill@math.mit.edu

mcdonald@uxe.cso.uiuc.edu (04/18/88)

Why use goto's? Simple: because it makes sense in the context of the
problem at hand.

FLAME ON ... TEMPERATURE 100,000,000 degress !!!  1e28 tons of helium
ready to turn into Nickel56!!!!!!! (ask sci.astro)


I am FED UP with goto bashers! I'll admit that code filled with gotos
may be messy: if I write a goto, it's because I feel like it! I don't
give a DAMN whether you like goto's or not; I believe in using whatever 
tool is at hand to get the job done. I frankly don't believe for
ONE CLOCK TICK OF A CRAY 2 that gotos make code worse. Spaghetti is
spaghetti, whether it is done with gotos or some other construct, and
so is any other equivalent mess.


But keep up the battle; I'll agree it is worth a good chuckle.

Doug McDonald
Professor of Chemistry
University of Illinois

daveb@laidbak.UUCP (Dave Burton) (04/18/88)

In article <3470@bunker.UUCP> garys@bunker.UUCP (Gary M. Samuelson) writes:
|In article <748@l.cc.purdue.edu> cik@l.cc.purdue.edu (Herman Rubin) writes:
|>Here is a challenge to the denigrators of goto.
|Case 5:
|	b >>= g16;
|	m |= b;
|	x = *(--geom);
|	if (TEST) {	
|		if (ODD(x)) Case2();
|		else        Case1();
|	} else {
|		g4 = (x+1)/2;
|		if (ODD(x)) Case3();
|		else        Case4();
|	}

Gary - this is no flame in your direction (Herman deserves all he receives
for writing code like he challenged with). With the type of logic the
original code fragment was using, your modification would be deep down in
nested and re-nested function calls before you could say "Memory fault --
core dumped" :-).

About the only way (from the too little context given by Herman) that I know
to clean up his code without gotos is to use states. The overhead is very
small, typically just one extra test per 'loop'. Maybe something like:

enum calcs { start, state0, ..., state5 } state = start;
enum calcs compute();

switch (state) {
case start:
	state = compute();
	break;
case state0:
	x = 1+2;
	state = CRAP(x) ? state1 : state2;
	break;
...
case state5:
	b >>= g16;
	m |= b;
	x = *(--geom);
	if (TEST) {	
		state = ODD(x) ? state2 : state1;
	} else {
		g4 = (x+1)/2;
		state = ODD(x) ? state3 : state4;
	}
	break;
}
-- 
--------------------"Well, it looked good when I wrote it"---------------------
 Verbal: Dave Burton                        Net: ...!ihnp4!laidbak!daveb
 V-MAIL: (312) 505-9100 x325            USSnail: 1901 N. Naper Blvd.
#include <disclaimer.h>                          Naperville, IL  60540

franka@mmintl.UUCP (Frank Adams) (04/19/88)

In article <4160@auspyr.UUCP> mick@auspyr.UUCP (Michael J. Andrew) writes:
>Provide each member of the team a $500 bonus at the start of a new
>project, but deduct $50 each time a global variable is introduced
>into the design.

This isn't good enough.  One can simply create a struct with one component
for each thing which would otherwise be a global variable, and have a single
instance of it as the only global variable.  This makes the code harder to
read, of course, but it saves (the team) money.
-- 

Frank Adams                           ihnp4!philabs!pwa-b!mmintl!franka
Ashton-Tate          52 Oakland Ave North         E. Hartford, CT 06108

karl@haddock.ISC.COM (Karl Heuer) (04/19/88)

In article <1988Apr16.223658.15649@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes:
>>[re languages so rich in control structures that goto is superfluous]
>Don't forget the Unix shell.  (The standard one, not the silly thing from
>Berkeley.)

It isn't sufficiently rich, at least not for my taste.  Some things I've had
to write in shell are worse than a goto.  (Functions would help, but older
shells don't have them yet, so I avoid them when I need portability.)

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

piet@ruuinf.UUCP (Piet van Oostrum) (04/19/88)

Posting-Front-End: GNU Emacs 18.47.9 of Mon Mar 21 1988 on ruuinf (hcx/ux)


In article <1073@maynard.BSW.COM> campbell@maynard.BSW.COM (Larry Campbell) writes:
   In article <2618@bsu-cs.UUCP> dhesi@bsu-cs.UUCP (Rahul Dhesi) writes:
   <>...And I know of no language, with the possible exception of Ada, that is
   <>rich enough in control structures to always have an elegant and
   <>efficient alternative to using a goto.

   Check out BLISS.  It's not without its flaws -- I consider its extreme
   typelessness a botch -- but it has such a complete set of well thought
   out control constructs that you don't miss the goto at all.  (BLISS has
   no goto.)

Modula-2 doesn't have a GOTO either. It has LOOP ... EXIT ... END.
-- 
Piet van Oostrum, Dept of Computer Science, University of Utrecht
Budapestlaan 6, P.O. Box 80.012, 3508 TA Utrecht, The Netherlands
Telephone: +31-30-531806              UUCP: ...!mcvax!ruuinf!piet

les@chinet.UUCP (Leslie Mikesell) (04/20/88)

In article <1842@faline.bellcore.com> purtill@math.mit.edu (Mark Purtill) writes:
>In any case, I fail to see how replacing a "return" with a "goto" will
>make it any less confusing, especially given that the label for the goto
>may be on the next page, or that the next person to deal with the code
>may add code after the label, etc.  All you've done is replace earlier
>"return"s with "goto label"s which may not really do what you want.

Do people still look at code on paper?  A reasonable editor can find goto's
and their targets no matter what page they are on.  In all the ranting about
writing code that is easy to maintain, no one has mentioned the things
that allow the usual tools to do more of the work for us.  For example,
making all (at least global) names unique to the point that grep can
find exactly the lines that use each one.

  Les Mikesell
>
>^.-.^ Mark Purtill
>((")) purtill@math.mit.edu

terry@wsccs.UUCP (Every system needs one) (04/20/88)

In article <1988Apr11.201934.20594@utzoo.uucp>, henry@utzoo.uucp (Henry Spencer) writes:
> Sorry, I consider the remark well-justified and will not apologize.  If
> you read my other postings on the subject, you will see that I consider
> the use of gotos, especially the frequent use of gotos, to be a sign of
> poor organization and "coding before thinking".  Given this opinion, it
> is hardly surprising that I would be reluctant to buy software from an
> organization which endorses routine use of gotos.

#ifdef FLAME

You probably don't believe in "register" or "char ***", either.  A language
feature is there for a reason, or it rots and falls off, much like a human
cerebellum.  Coding before thinking is when all your local variables are
named "foo" and all your global variables are named "fee", "fie", "foe", and
"fum".  Your functions are named "func1", "func2", etc., and your comments
consist of "Begin program" and "End program".  This is the result of not
thinking.  Use of conditional flags which may have to be loaded from memory
is thinking twice and saying "think think ... click click".

The use of the "goto" statement is much profaned by ex-Pascal programmers
who have almost, but not quite, seen the light.  These are the same people
who do:

#define	BEGIN		{
#define	END.		}
#define	END		}
#define	REMARK(x)	/* (x) */
#define	THEN
#define IF		if

and

	IF (cond) THEN
	BEGIN
		...
		...
	END

They are the same people who who use

	if (cond)
	{
	}

and	#define otherwise default
	switch (val)
	{
		case 1:
			...
			...
		case n:
		otherwise:
	}

and	int function()

Instead of

	if( cond) {
	}
	
and	switch( val) {
	case 1:
		...
		...
	case n:
	default:
	}

and	int
	function()

I like to call these people NOT-C programmers (say it out loud :-)

They are the people who do not realize that

	grep goto /usr/src/uts/3b2/*/*.c | wc

yeilds:

	308	992	8411

...308 "goto"'s in the UNIX kernel. (I checked... NONE were comments).

I thinks this adequately justifies the use of "goto"'s in commercial
programming, at least for those programs expected to PERFORM like a
commercial program.

Try the following some time.  Replace all your "nifty" flags with "goto"
statements, and profile both versions of the code... then, disassemble
both versions and grep for all branch instructions.  Which has more
REAL "goto"'s?

#else
	I'm not saying that "goto"'s should be used in place of all loop
flags, but it certainly seems to make code a lot more readable if you don't
have to use a 264 column terminal.  If you use "goto"'s in place of flags
which are modified in one place only for the express purpose of avoiding a
"goto", you certainly clean up the assembly code, as well.
#endif


| Terry Lambert           UUCP: ...{ decvax, ihnp4 } ...utah-cs!century!terry |
| @ Century Software        OR: ...utah-cs!uplherc!sp7040!obie!wsccs!terry    |
| SLC, Utah                                                                   |
|                   These opinions are not my companies, but if you find them |
|                   useful, send a $20.00 donation to Brisbane Australia...   |
| 'There are monkey boys in the facility.  Do not be alarmed; you are secure' |

sullivan@vsi.UUCP (Michael T Sullivan) (04/21/88)

In article <225800022@uxe.cso.uiuc.edu>, mcdonald@uxe.cso.uiuc.edu writes:
> ...
> tool is at hand to get the job done. I frankly don't believe for
> ONE CLOCK TICK OF A CRAY 2 that gotos make code worse. Spaghetti is
> ...
> Professor of Chemistry
               ^^^^^^^^^

Hmmm...


-- 
Michael Sullivan		{uunet|attmail}!vsi!sullivan
				sullivan@vsi.com
HE V MTL

new@udel.EDU (Darren New) (04/21/88)

In article <3470@bunker.UUCP> garys@bunker.UUCP (Gary M. Samuelson) writes:
>In article <748@l.cc.purdue.edu> cik@l.cc.purdue.edu (Herman Rubin) writes:
>>
>>Here is a challenge to the denigrators of goto.
>> ...
>
>Now give me something hard.
>
>Gary Samuelson

How about: (pseudocode)
   for (i = 0; i < max_in_table && key != name[i]; ++i) 
      if (keypressed()) goto handle_key;
   seek(helpfile, offset[i]);
   if (keypressed()) goto handle_key;
   linecount = 0;
   do {
      read_line_from_file();
      ++linecount;
      if (keypressed()) goto handle_key;
      if (read_line[0] == special_flag_char) goto handle_key;
      insert_spaces_and_color_codes();
      if (keypressed()) goto handle_key;
      display_text_line();
      if (keypressed()) goto handle_key;
      } while (linecount < 24);
   handle_key:
   c = wait_for_key_then_read_it();
   switch (c) {
      case 'A': ...
       ...
      }

I contend that if the reading and formatting and displaying are sufficiently
slow, such behaviour can be desirable (i.e., on microcomputers).
I would like to see a goto-less version of this that is easier to understand.
                             - Darren New
                               Graduate Student
                               University of Delaware.

   

hutch@hubcap.UUCP (David Hutchens) (04/21/88)

From article <2200@louie.udel.EDU>, by new@udel.EDU (Darren New):
> 
> How about: (pseudocode)
>    for (i = 0; i < max_in_table && key != name[i]; ++i) 
>       if (keypressed()) goto handle_key;
>    seek(helpfile, offset[i]);
>    if (keypressed()) goto handle_key;
>    linecount = 0;
>    do {
>       read_line_from_file();
>       ++linecount;
>       if (keypressed()) goto handle_key;
>       if (read_line[0] == special_flag_char) goto handle_key;
>       insert_spaces_and_color_codes();
>       if (keypressed()) goto handle_key;
>       display_text_line();
>       if (keypressed()) goto handle_key;
>       } while (linecount < 24);
>    handle_key:
>    c = wait_for_key_then_read_it();
>    switch (c) {
>       case 'A': ...
>        ...
>       }
> 
> I contend that if the reading and formatting and displaying are sufficiently
> slow, such behaviour can be desirable (i.e., on microcomputers).
> I would like to see a goto-less version of this that is easier to understand.
>                              - Darren New
>                                Graduate Student
>                                University of Delaware.
> 
>    
  for (i=0; i<max_in_table && key!=name[i] && !keypressed(); i++);
  if (!keypressed()) {  
    seek(helpfile,offset[i]);
    looking_for_flag = 1; 
    linecount = 0; 
    while (looking_for_flag && linecount<24 && !keypressed()) {
      read_line_from_file();
      linecount++;
      looking_for_flag = (read_line[0] != special_flag_char);
      if (looking_for_flag && !keypressed()) {
        insert_spaces_and_color_codes();        
        if (!keypressed()) {
          display_text_line();
        }    
      } 
    } 
  } 
  c = wait_for_key_then_read_it();
  switch (c) {
    case 'A': ...
    ...
  }
 

Consider it done.  The important thing to note is that I don't care
if the precise algorithm you used can be done without a goto.  In
fact, it is the algorithm that is the problem.  It is stupid to
write a piece of code with gotos and then translate it to "structured"
code.  I put structured in quotes because such code is not structured
at all.  Indeed, in my implementation I may call keypressed a second
time after I've already received a true response.  This could be
fixed easily enough with another local variable, but that would just
make it harder to understand.  I did use a looking_for_flag to maintain
some information.  I'm just waiting for the first fool to tell me
it is not as efficient as your solution.  ("I contend that if the
reading and formatting and displaying are sufficiently slow," nobody
could possibly notice these few microseconds.)

The reason you don't see structured solutions is that you allow those
silly gotos to control your reasoning.  I insist on remaining in
charge of my code.

Actually, I'd write the first lines as:
  for (i=0; i<max_in_table && key!=name[i]; i++);
  if (!keypressed()) { ....
since unless max_in_table is a bigger number than the available memory
on most micros (your stated environment) I can check the whole array
in less time than a few calls to keypressed() will take and certainly
in less time than a user will be able to notice.

I also note that there is no action taken in the case that
  i==max_in_table (other than seeking to God knows where).
I suspect missing logic in your code.

In summary, think about the problem and don't let gotos get in the way.

			David H. Hutchens
			Clemson University
			gatech!hubcap!hutch
			hutch@hubcap.clemson.edu

lew@gsg.UUCP (Paul Lew) (04/21/88)

> How about: (pseudocode)
>    for (i = 0; i < max_in_table && key != name[i]; ++i) 
>       if (keypressed()) goto handle_key;
>    seek(helpfile, offset[i]);
>    if (keypressed()) goto handle_key;
>    linecount = 0;
>    do {
>       read_line_from_file();
>       ++linecount;
>       if (keypressed()) goto handle_key;
>       if (read_line[0] == special_flag_char) goto handle_key;
>       insert_spaces_and_color_codes();
>       if (keypressed()) goto handle_key;
>       display_text_line();
>       if (keypressed()) goto handle_key;
>       } while (linecount < 24);
>    handle_key:
>    c = wait_for_key_then_read_it();
>    switch (c) {
>       case 'A': ...
>        ...
>       }
> 
> I contend that if the reading and formatting and displaying are sufficiently
> slow, such behaviour can be desirable (i.e., on microcomputers).
> I would like to see a goto-less version of this that is easier to understand.

I think judicious use of goto is ok, but in this example, I think the
following code is easier to understand than your code. The block
stucture and ESPECIALLY indentation make it easier to understand, I
have to read your version line by line to figure out what it does.

    int kp = 0;		/* keypress indicator */
    for (i = 0; i < max_in_table && key != name[i]; ++i) 
       if (kp = keypressed()) break;
    if (!kp) {
       seek(helpfile, offset[i]);
       if (!keypressed()) {
          linecount = 0;
          do {
             read_line_from_file();
             ++linecount;
             if (keypressed() || read_line[0] == special_flag_char) break;
             insert_spaces_and_color_codes();
	     if (keypressed()) break;
             display_text_line();
             if (keypressed()) break;
             } while (linecount < 24);
          }
       }
    c = wait_for_key_then_read_it();
    switch (c) {
       case 'A': ...
        ...
-- 
Paul Lew			{oliveb,harvard,decvax}!gsg!lew	(UUCP)
General Systems Group, 5 Manor Parkway, Salem, NH 03079	(603) 893-1000

ray@micomvax.UUCP (Ray Dunn) (04/22/88)

In article <451@goofy.megatest.UUCP> djones@megatest.UUCP (Dave Jones) writes:
>....
>Mr Spencer, Mr. David Brown, and the loquacious Mr. Gwyn all say straight 
>out that I am an advocate of the use of the goto statement.
>But I never once in any of my postings endorsed the use of the goto 
>statement!  You may verify as much if you will reread the postings.

Unfortunately, it is all too common on the net, even (especially?) by the
supposed "gurus", that a reasoned *non-polarized* argument is immediately
taken as a critisism.

If you are not with them, you are judged to be against them!  It happens to
all of us.

>     ... I only stated that the importance which some people place
>on avoiding the gotos is exceedingly exaggerated, and that time spent
>campaigning against its use is misspent. This is an opinion which I 
>still hold. 

As do many of us!

>
>But all this is quite incidental.  Mr. Spencer is entitled to his
>opinions about programming techniques, as am I. 
>I objected not to Mr. Spencer's mistaken reading of my postings.  
>I objected to his affrontary.
>

Ok.  You object.  All this does now though, is open up another discussion as
to what is "acceptable" behaviour on the net.  You have expressed your
opinion, they have too, by example.  Both opinions should be respected, if
not necessarily agreed with.

>You three, Spencer, Brown, and Gwyn, hold that it is proper for you to 
>publicly criticize the software produced by the company which employs me,
>on the basis of a few lines that I wrote here.  To presume that 
>you are competent to judge products you have never used is
>ridiculous.  To presume to make such pronouncements publicly is,
>by my values, rude at best. Perhaps I should only say that we have
>differing values not only about some  small software engineering matters,
>but also about what constitutes  good manners and acceptable behavior.
>
>I find this whole matter very distasteful.  I regret having provoked it.
>

I'm not fully supportive of your *attitude* here, as the net is essentially
a "soap-box" forum.  A poster *must* realize that (s)he is exposing himself
to all extremes of opinion, attitude, and behaviour, *and be prepared to
take the heat*.

A net poster is like an actor on a stage, (s)he must be prepared to accept
criticism of all sorts.  Support is, by its very nature, most often silent,
except in private e-mail responses.

Why can't you allow your opinions to stand on their own merits with the net
readership as a whole? 

Just because Spencer, Gwyn, et al, disagree with your views does not
denigrate your opinions in the eyes of the open-minded.

Indeed, as I believe in this case, the *opposite* is often correct.  They
don't "hold that it is proper to", they just spout off, in what is, by now,
an expected and predictable way.  *They* are exposing themselves in the same
way you are.

I'm afraid I can't accept whining about "bad manners" in this sort of forum.
To begin with, the right to be "bad mannered" is an intrinsic freedom just
as important as the right to hold stupid opinions.

Are you "hurt" by an opposing opinion?  Should you be "hurt" by a badly
mannered opposing opinion?  I think not.

Remember also, that the definitions of bad manners and stupid opinions are
extremely subjective.

Finally, what you are seeing on the net, is the *mental* responses which do
not get moderated by speech or personal contact - we are all in our own
little worlds here responding to faceless words!  There is no definition of
"bad manners" which has had time to mature in this environment.

Many of us, including myself, expose ourself in both ways.  So, people
disagree some of the time, people are offended some of the time.
Unfortunate, perhaps, but (profound statement follows (:-)) that's life!

There's *always* going to be somebody that disagrees, and there's *always*
going to be somebody whose reaction differs from your norms.

>I'm through with comp.lang.c for a while.

A pity, I respect your views, but it is probably for the best until you
realize that a net posting is very different from expressing an opinion in
private to a friend.  Confidence in yourself and a thick skin are very
useful attributes.


Ray Dunn.  ..{philabs, mnetor}!micomvax!ray

friedl@vsi.UUCP (Stephen J. Friedl) (04/22/88)

In article <2200@louie.udel.EDU>, new@udel.EDU (Darren New) writes:
>
> [responding to the "give me something hard to translate" challenge]
>
> How about: (pseudocode)
>    for (i = 0; i < max_in_table && key != name[i]; ++i) 
>       if (keypressed()) goto handle_key;
>    seek(helpfile, offset[i]);
>    if (keypressed()) goto handle_key;
>
>	[more code with output and "keypressed" here.  Presumably
>	this lets redisplay stop and process the next command and
>	possibly avoiding wasted output.  Emacs and WordStar do
>	this, among others]
> 
> I contend that if the reading and formatting and displaying are sufficiently
> slow, such behaviour can be desirable (i.e., on microcomputers).
> I would like to see a goto-less version of this that is easier to understand.

Let's put this goto business in perspective:

	/*
 	 * strcpy() - written by John Doe
	 */
	strcpy(dst, src)
	char	dst[], src[];
	{
	int	i;

		for (i = 0; dst[i] = src[i]; i++)
			;
	}

     Who objects to this?

     Even a beginnermediate C programmer is likely to rewrite
this function using pointers, but it is unlikely that a
passionate hatred of [arrays] (or of John Doe) will develop as
well.  In this case, the use of arrays indicates lack of
experience or insight, not of evil intent or laziness.

       ***********************************************
       * The problem is not with arrays but with the *
       * underlying thought that caused their use.   *
       *                                             *
       * The solution is not to ban the array but to *
       * teach the insight.                          *
       ***********************************************

     And so it goes with our bedeviled goto.  In the quoted text
above, goto probably indicates a lack of experience with really
neat methods of preemptive redisplay.   Gosling Emacs does this
by checking for keypressed() *one place* very deeply in the
display handler rather than sprinkle these calls everywhere; Sys
V Rel 3 curses does it like this too.  I have oversimplified
it here, but it is extremely elegant and beautiful to behold.
Those attempting mere transliteration of the above fragment
are condemned to failure even if no gotos are used -- the failure
just won't be as "obvious".

       ***********************************************
       * The problem is not with the goto but with   *
       * the underlying thought that caused its use. *
       *                                             *
       * The solution is not to ban the goto but to  *
       * teach the insight.                          *
       ***********************************************

     The array example is a trivial one but (I believe) valid.
When you are learning C you will naturally stumble over the
syntax and semantics of the language, but it is part of learning.
In my opinion, *excessive* use of arrays tells me that the user
needs to get more comfortable with pointers, but I betcha this
person does not believe that they are doing anything "wrong".
Perhaps they are not: the program works, doesn't it?

     Once you've learned C you still have a long way to go.
There are many, many more levels of insight beyond just learning
syntax -- learning to speak Spanish won't make you a great
speaker in Mexico City.  The goto shows lack of insight on a much
higher level, and it is a lot harder to convince people that they
are missing that insight.  Showering users of gotos with $50 fines
and ridicule is hardly conducive to inspired thinking.

     The solution to this goto problem is not to be found by
banning the goto but by better fundamental understandings.
Focusing on language syntax is largely a wasted effort that
distracts from the real issues.

    C'mon guys/gals, let's replace:

 	"you show me a fragment with gotos and I can rewrite
 	it without them" (said with challenging tone)

with

 	"You show me what you want to accomplish, and I'll
 	suggest some alternate ideas" (said with helpful tone).

     If you use gotos a lot, ask a wizard for suggestions and try
to gain something beyond solving the problem at hand.  If you are
a wizard, share your experience as others undoubtedly did with
you.  Most of us really enjoy the fun of computers and want to be
the best we can be.  Let's help each other out.


     I've crossposted this to comp.software-eng in the hope
that some of the net.readers over there might have something
to offer from a software engineering viewpoint rather than a
language syntax viewpoint.  Anyone?

-- 
Steve Friedl       V-Systems, Inc.      Resident access(2) basher
friedl@vsi.com   {backbones}!vsi.com!friedl    attmail!vsi!friedl

campbell@maynard.BSW.COM (Larry Campbell) (04/22/88)

In article <2200@louie.udel.EDU> new@udel.EDU (Darren New) writes:
<>How about: (pseudocode)
<>   for (i = 0; i < max_in_table && key != name[i]; ++i) 
<>      if (keypressed()) goto handle_key;
<>   seek(helpfile, offset[i]);
<>   if (keypressed()) goto handle_key;
<>   linecount = 0;
<>   do {
<>      read_line_from_file();
<>      ++linecount;
<>      if (keypressed()) goto handle_key;
<>      if (read_line[0] == special_flag_char) goto handle_key;
<>      insert_spaces_and_color_codes();
<>      if (keypressed()) goto handle_key;
<>      display_text_line();
<>      if (keypressed()) goto handle_key;
<>      } while (linecount < 24);
<>   handle_key:
<>   c = wait_for_key_then_read_it();
<>   switch (c) {
<>      case 'A': ...
<>       ...
<>      }

Use a signal handler.  Example:

handle_key()
{
c = wait_for_key_then_read_it();
switch (c)
    {
    case 'A': ...
      ...
    }
}

... main body of code:

    signal(SIGIO, handler);
    for (i = 0; i < max_in_table && key != name[i]; ++i) 
        ;
    seek(helpfile, offset[i]);
    linecount = 0;
    do {
        read_line_from_file();
        ++linecount;
        insert_spaces_and_color_codes();
        display_text_line();
        } while (linecount < 24);

This is not only much clearer and easier to read, it's also considerably
faster.  And doesn't use gotos.
-- 
Larry Campbell                                The Boston Software Works, Inc.
Internet: campbell@maynard.bsw.com          120 Fulton Street, Boston MA 02109
uucp: {husc6,mirror,think}!maynard!campbell         +1 617 367 6846

chris@mimsy.UUCP (Chris Torek) (04/23/88)

>In article <2200@louie.udel.EDU> new@udel.EDU (Darren New) writes:
[pseudocode with `goto handle_key']

In article <1075@maynard.BSW.COM> campbell@maynard.BSW.COM (Larry Campbell)
suggests:

>Use a signal handler.

[code deleted]

Remember also to fcntl(fd, FSETFL, FASYNC) or ioctl(fd, FIOASYNC, &on),
or you will never get a signal.

>This is not only much clearer and easier to read, it's also considerably
>faster.  And doesn't use gotos.

It may be clearer and easier to read, but it is also more dangerous.
Doing I/O in a signal handler is considerably harder than polling for
input at `safe' places.  If the input is to do almost anything useful,
you have created a critical section, which requires blocking and
releasing signals.  The trivial if unclear `goto' variant has been
replaced by a more powerful, more efficient (perhaps*), but much harder
to code correctly, asynchronous variant.

-----
*If the signal blocking and releasing has much overhead, it may be
less efficient than the polling variant.  Fortunately one can cheat
and move the work into the io signal handler, using semaphore variables.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

nather@ut-sally.UUCP (Ed Nather) (04/23/88)

In article <993@micomvax.UUCP>, ray@micomvax.UUCP (Ray Dunn) writes:

[... much very sensible discussion deleted ...]

> a "soap-box" forum.  A poster *must* realize that (s)he is exposing himself
                                                    ^^^^^             ^^^^^^^
Twisting the language to become gender-free is not so easily done, as this
example demonstrates.  You have to change *all* references to a variable,
not just some of them, if the code is to work.
-- 
Ed Nather
Astronomy Dept, U of Texas @ Austin
{allegra,ihnp4}!{noao,ut-sally}!utastro!nather
nather@astro.AS.UTEXAS.EDU

henry@utzoo.uucp (Henry Spencer) (04/24/88)

> You probably don't believe in "register" or "char ***", either.

I use the former frequently and would use the latter if it seemed indicated,
although I don't recall ever needing it.

> A language feature is there for a reason...

Language designers and standardizers do have to consider badly-written
existing code as such a reason, remember.

> ...308 "goto"'s in the UNIX kernel. (I checked... NONE were comments)...
> I thinks this adequately justifies the use of "goto"'s in commercial
> programming...

Believe it or not, some of us do not consider the Unix kernel a shining
example of wonderful programming (although it is mostly okay, and it does
work pretty well).

> Try the following some time.  Replace all your "nifty" flags with "goto"
> statements, and profile both versions of the code...

If you read the paper by Geoff Collyer and myself in last year's winter
Usenix proceedings, I think you will realize that I know how to profile
things, and also how to make them run fast without assembler or gotos
(C News contains neither).

> then, disassemble
> both versions and grep for all branch instructions.  Which has more
> REAL "goto"'s?

Personally, I don't care diddly-squat about how ugly the code coming out
of the compiler is.  I don't usually read it.  What I care about is the
cleanliness of the source code, which I do have to read, and the speed and
correctness of the object code.  Turning clean human-readable notation into
ugly fast code is the compiler's *JOB*.

> ... If you use "goto"'s in place of flags
> which are modified in one place only for the express purpose of avoiding a
> "goto", you certainly clean up the assembly code, as well.

If you use neither, the source code generally looks still better, and the
assembler might well improve too (if you care).  I'm not sure I've ever
used a flag just to avoid a goto; certainly I haven't done it recently.
I believe in treating the disease, not the symptoms.

> The use of the "goto" statement is much profaned by ex-Pascal programmers
> who have almost, but not quite, seen the light...

Well, speaking for myself, I've never programmed in Pascal.  I suppose I may
not have seen the light yet; I've only programmed in C for 13 years.
-- 
"Noalias must go.  This is           |  Henry Spencer @ U of Toronto Zoology
non-negotiable."  --DMR              | {ihnp4,decvax,uunet!mnetor}!utzoo!henry

g-rh@cca.CCA.COM (Richard Harter) (04/24/88)

	I suppose there is some justification for the recurring issue
of gotos -- it usually raises some interesting issues of coding technique.
It's not a profound topic, but it's fun for all concerned.  It seems to me
that the profit, if any, in these exercises is to analyze these little
difficulties and spot where the problem is and what a good resolution is.

	In the case in hand we have a very common task -- there are a
series of actions.  After each action we check to see if a certain thing
has happened -- if it has we cease stepping through the actions and go
on to the next stage.  The proposed techniques include

a)	Use goto's at each checkpoint which branch to a common label

b)	Fake it with a block and break statements

c)	Use nested if's

d)	Use a signal handler.

The signal handler approach is pretty, but it isn't general, and doesn't
really work right in this case.  The nested if's approach is, in my view,
worse than using goto's -- it buries the essential structure of the task
rather than explicates it.  Block and break is fine as long as it is con-
venient to put all the tests at the first level.  So far, however, nobody
has really made a good case for not using goto's for this kind of task,
as far as I can see, other than it is naughty to use goto's.  Here are
some more alternatives:

e)	Put the sequence of actions in a function and get out with return
	statements.  Much the same as block and break, except that you
	can do deep level escapes.

f)	Put the test condition in a while statement and step through the
	actions [somehow].  Unfortunately, I don't see a nice way to do
	this in C.  The thought that first occurs to one is something like

for (step=0,done=0;!done;step++) {
  switch(step) {
    case 0:  action_0;
             break;
    case 1:  action_1;
             break;
    ......
    default: done = 1;
             break;
    }
  if (!done && test_condition) done=1;
  }

which is all very well in its way (there is now only one expression of
the test condition) but does look remarkably clumsy and is a maintenance
problem (what happens when you want to insert a new action?).  Perhaps
someone else has a neater way to do it.

In assembly language this type of situation is a natural for threaded code.
The labels for the action sequences go on a stack.  After each action you
branch to the test code, which in turn pops the next action label.  All
very straightforward, but I don't really see a nice way to implement threaded
code in C without using function arrays.
-- 

In the fields of Hell where the grass grows high
Are the graves of dreams allowed to die.
	Richard Harter, SMDS  Inc.

flaps@dgp.toronto.edu (Alan J Rosenthal) (04/24/88)

In article <1464@hubcap.UUCP> hutch@hubcap.UUCP (David Hutchens) writes:
>Indeed, in my implementation I may call keypressed a second
>time after I've already received a true response.  This could be
>fixed easily enough with another local variable, but that would just
>make it harder to understand.

Better yet, if keypressed() is considered part of the i/o library, it
could keep its own local flag, if the following two changes were made:

-> When keypressed() is called, if the flag is set, just return true;
   else actually look for a keypress and if there is one then set the
   flag and return true.

-> All other input functions clear the flag if they do actual input.
   As an optimization, perhaps ungetc() sets the flag (scanf() too if
   applicable).

In fact, keypressed() probably already works like this.  If not, you
can certainly wrap your own routine around it, or write your
mykeypressed() routine that keeps a flag and does the low-level gunge
itself.

ajr

peter@sugar.UUCP (Peter da Silva) (04/24/88)

I think you're both hosed...

In article ... campbell@maynard.BSW.COM (Larry Campbell) writes:
> In article <2200@louie.udel.EDU> new@udel.EDU (Darren New) writes:
> <>How about: (pseudocode)
> <>   for (i = 0; i < max_in_table && key != name[i]; ++i) 
> <>      if (keypressed()) goto handle_key;
	...
> <>   handle_key:
> <>   c = wait_for_key_then_read_it();
> <>   switch (c) {

> Use a signal handler.  Example:

> handle_key()
> {
> c = wait_for_key_then_read_it();
> switch (c)
>     {
	...
> ... main body of code:

>     signal(SIGIO, handler);
>     for (i = 0; i < max_in_table && key != name[i]; ++i) 
>         ;

Who's got SIGIO?

And why do you need SIGIO?

Instead of
	if(key_pressed()) goto handle_key;

You can do
	if(key_pressed()) handle_key();

Personally I'd do this in a real operating system that supports lightweight
processes, like AmigaDOS, instead of an old monolithic monitor :->.
-- 
-- Peter da Silva      `-_-'      ...!hoptoad!academ!uhnix1!sugar!peter
-- "Have you hugged your U wolf today?" ...!bellcore!tness1!sugar!peter
-- Disclaimer: These aren't mere opinions, these are *values*.

daveb@geac.UUCP (David Collier-Brown) (04/25/88)

>In article <451@goofy.megatest.UUCP> djones@megatest.UUCP (Dave Jones) writes:
>>Mr Spencer, Mr. David Brown, and the loquacious Mr. Gwyn all say straight 
>>out that I am an advocate of the use of the goto statement.
>>But I never once in any of my postings endorsed the use of the goto 
>>statement!  You may verify as much if you will reread the postings.

Point of fact:
   My name is Collier-Brown (just ask Joyce!).
Point of fact:
   I'm the guy who said Dave Jones condoned gotos, and said Henry
Spencer could fine me when I used them.

Point of order:
   Its OK to get mad at me, I have a relatively thick skin.  (I have
to, I still use gotos for things (:-)).

--dave (My first language was FORTRAN II) c-b
-- 
 David Collier-Brown.                 {mnetor yunexus utgpu}!geac!daveb
 Geac Computers International Inc.,   |  Computer Science loses its
 350 Steelcase Road,Markham, Ontario, |  memory (if not its mind) 
 CANADA, L3R 1B3 (416) 475-0525 x3279 |  every 6 months.

dg@lakart.UUCP (David Goodenough) (04/25/88)

In article <2200@louie.udel.EDU> new@udel.EDU (Darren New) writes:
>How about: (pseudocode)
>   for (i = 0; i < max_in_table && key != name[i]; ++i) 
>      if (keypressed()) goto handle_key;
>   seek(helpfile, offset[i]);
>   if (keypressed()) goto handle_key;
>   linecount = 0;
>   do {
>      read_line_from_file();
>      ++linecount;
>      if (keypressed()) goto handle_key;
>      if (read_line[0] == special_flag_char) goto handle_key;
>      insert_spaces_and_color_codes();
>      if (keypressed()) goto handle_key;
>      display_text_line();
>      if (keypressed()) goto handle_key;
>      } while (linecount < 24);
>   handle_key:
>   c = wait_for_key_then_read_it();
>   switch (c) {
>      case 'A': ...
>       ...
>      }

This is about the same:

    for (i = j = 0; i < max_in_table && key != name[i] && !j; ++i) 
	if (j = keypressed())
	    break;
    if (!j)
    {
	seek(helpfile, offset[i]);
	linecount = 0;
	while (!keypressed() && linecount < 24)
	{
	    read_line_from_file();
	    ++linecount;
	    if (keypressed() || read_line[0] == special_flag_char)
		break;
	    insert_spaces_and_color_codes();
	    if (keypressed())
		break;
	    display_text_line();
	}
    }
    c = wait_for_key_then_read_it();
    switch (c)
    {
	case 'A': ...
		...
    }

I grant that j could be renamed to (say) key_press_seen, but choice of
long / short variable names belongs in a whole different discussion.
However, I ask, where did all those goto's go to?? :-)

The ONLY time I use a goto is because C doesn't have a 'break 2' construct:

	for (;;)
	{
	    while (...)
	    {
		code .....

		if (condition)
		    break 2;
		
		more code .....
	    }
	}
	/* break 2 exits to here */

Maybe someone should suggest it to the ANSI crowd - it can't be that hard to do.
--
	dg@lakart.UUCP - David Goodenough		+---+
							| +-+-+
	....... !harvard!adelie!cfisun!lakart!dg	+-+-+ |
						  	  +---+

garys@bunker.UUCP (Gary M. Samuelson) (04/26/88)

In article <2200@louie.udel.EDU> new@udel.EDU (Darren New) writes:
>How about: (pseudocode)

For pseudocode it looks a lot like C.

The easy way: replace "goto handle_key" with "return."
Then after the call to this function, add a call to handle_key().
You have too much going on for it to be one function anyway.

What you really want is to get an interrupt if a key is pressed.
If you can do that, then the code becomes much simpler.  If you
can't get either a "key pressed" interrupt or an interval timer
interrupt, then use a state machine.  (Credit has to go to Dave
Burton; although I frequently use state machines, I hadn't thought of it
in the previous case.)

while( state != done ) {

/* Instead of 'state', 'next_thing_to_do' might be better */

	switch( state ) {
	case readingfile:
		...
		if( read_line[0] == special_flag_char )
			state = done;
		else
			state = inserting_spaces_and_color_codes;
		break;
	case inserting_spaces_and_color_codes:
		...
		state = displaying_text_line;
		break;
	...
	case last_thing_to_do:
		state = done;
		break;

	} /* end of switch (state) */

	if( keypressed() )
		state = done;
} /* end of while( state != done ) */

c = wait_for_key_then_read_it();
switch (c) {
      case 'A': ...
       ...
}

It still reads sequentially, but now "if keypressed" is isolated,
which makes it less cluttered, and easier to change if (no, when)
it becomes necessary to do any of the following:
	1. pass an argument to keypressed();
	2. check something else periodically;
	3. add or delete points at which the check is made;

>I would like to see a goto-less version of this that is easier to understand.

I hope you think I have done so.

Gary Samuelson

mls@whutt.UUCP (SIEMON) (04/26/88)

In article <11352@ut-sally.UUCP+, nather@ut-sally.UUCP (Ed Nather) writes:
+ In article <993@micomvax.UUCP>, ray@micomvax.UUCP (Ray Dunn) writes:
+ 
+ [... much very sensible discussion deleted ...]
+ 
+ > a "soap-box" forum.  A poster *must* realize that (s)he is exposing himself
+                                                     ^^^^^             ^^^^^^^
+ Twisting the language to become gender-free is not so easily done, as this
+ example demonstrates.  You have to change *all* references to a variable,
+ not just some of them, if the code is to work.

Yes; as a good rule of thumb, it is MUCH easier to recast your sentences into
plural forms (where English makes no gender distinctions) than to go into
contortions to "fix" a sentence you have already warped by using the singular.
The pluralizing tactic will almost always work (outside of specific references
to individuals, where acknowledging gender is usually innocuous.)

This is a nice analogue of the problems with "go to" in programming languages;
the occurence of the deprecated form is a good sign (with some rare exceptions,
as has been mentioned in this discussion) that you have probably not thought
out the problem first.

-- 
Michael L. Siemon
contracted to AT&T Bell Laboratories
ihnp4!mhuxu!mls
standard disclaimer

terry@wsccs.UUCP (Every system needs one) (04/28/88)

In article <1988Apr24.012322.3951@utzoo.uucp>, henry@utzoo.uucp (Henry Spencer) writes:
> > A language feature is there for a reason...
> 
> Language designers and standardizers do have to consider badly-written
> existing code as such a reason, remember.

Standardizers, yes; designers, no.  If you degisign a language, then there is
not existing code.  ANSI isn't considering "badly written" code, aparrently,
although defining "badly written" in a standard that makes something badly
written is begging the question.

> 
> > ...308 "goto"'s in the UNIX kernel. (I checked... NONE were comments)...
> > I thinks this adequately justifies the use of "goto"'s in commercial
> > programming...
> 
> Believe it or not, some of us do not consider the Unix kernel a shining
> example of wonderful programming (although it is mostly okay, and it does
> work pretty well).

It would be slower in a number of cases without the construction it has...
consider the generation of "init", fo instance.  I wasn't saying it was
wonderful; simply adequate, and in some cases more efficient due to it's
use of goto's...

> > Try the following some time.  Replace all your "nifty" flags with "goto"
> > statements, and profile both versions of the code...
> 
> If you read the paper by Geoff Collyer and myself in last year's winter
> Usenix proceedings, I think you will realize that I know how to profile
> things, and also how to make them run fast without assembler or gotos
> (C News contains neither).

There are some cases where goto's *SHOULD* be used for efficiency where the
compiler or optimizer doesn't have a snowball's chance in hell of figuring
out what I wrote for itself.  Better to hit it over the head with what you
consider a hammer than to be less efficient.

> > then, disassemble
> > both versions and grep for all branch instructions.  Which has more
> > REAL "goto"'s?
> 
> Personally, I don't care diddly-squat about how ugly the code coming out
> of the compiler is.  I don't usually read it.  What I care about is the
> cleanliness of the source code, which I do have to read, and the speed and
> correctness of the object code.  Turning clean human-readable notation into
> ugly fast code is the compiler's *JOB*.

You don't agree that less of the same instructions == faster code?

Goto's are not the unclean, wearing the red mask of death and knocking at your
door.  Are you trying to tell us that you have *NEVER* used a goto?

How does a goto differ from a break statement when used to exit a for statement
to the statement immediately after it... pages of code later?  Why can't goto's
be used, in your book, to handle non-standard conditions?

> 
> > ... If you use "goto"'s in place of flags
> > which are modified in one place only for the express purpose of avoiding a
> > "goto", you certainly clean up the assembly code, as well.
> 
> If you use neither, the source code generally looks still better, and the
> assembler might well improve too (if you care).

	I agree with this, it's just that sometimes fugly code must be written
to do something fast and elegantly.  I simply think that a goto is less fugly
than an equivalent failure-loop construct, and beats indenting (or worse, NOT
indenting) everything.  I happen to write code that uses

	for( ;;) {
	}

instead of

	while( 1) {
	}

too, as I need the best speed out of the hardware I can get and the 'for'
avoids a test instruction being generated.  Certainly, the 'while' is better
at self-documenting, but it isn't the right tool for the job.

> I'm not sure I've ever used a flag just to avoid a goto; certainly I haven't
> done it recently.

	[...]

> I've only programmed in C for 13 years.

What do you write?

> "Noalias must go.  This is           |  Henry Spencer @ U of Toronto Zoology
> non-negotiable."  --DMR              | {ihnp4,decvax,uunet!mnetor}!utzoo!henry

For someone as vehnemently against 'noalias' as your .sig implies, how can
you berate a current language feature?  And how can you respect DMR's concept
of C enough to quote him on it, but not respect his decision to include the
'goto' statement?  Your appeal to his authority is a little inconsistent.


| Terry Lambert           UUCP: ...{ decvax, ihnp4 } ...utah-cs!century!terry |
| @ Century Software        OR: ...utah-cs!uplherc!sp7040!obie!wsccs!terry    |
| SLC, Utah                                                                   |
|                   These opinions are not my companies, but if you find them |
|                   useful, send a $20.00 donation to Brisbane Australia...   |
| 'Admit it!  You're just harrasing me because of the quote in my signature!' |

cl@datlog.co.uk (Charles Lambert) (04/28/88)

In article <27310@cca.CCA.COM> g-rh@CCA.CCA.COM.UUCP (Richard Harter) writes:
>
>f)	Put the test condition in a while statement and step through the
>	actions [somehow].  Unfortunately, I don't see a nice way to do
>	this in C.  The thought that first occurs to one is something like
>
>for (step=0,done=0;!done;step++) {
>  switch(step) {
>    case 0:  action_0;
>             break;
>    case 1:  action_1;
>             break;
>    ......
>    default: done = 1;
>             break;
>    }
>  if (!done && test_condition) done=1;
>  }

This is almost a finite-state machine, and state machine programming is an
accepted idiom. Generalise it as follows:

state=STAT0;
while ( state != STATE_DONE ) {
    switch (state) {

    STATE0: action_0();
	    if (exit_condition_0)
		state = STATE_DONE;
	    else
		state=STATE1;
	    break;
    STATE1: action_1();
	    if (exit_condition_1)
		state = STATE_DONE;
	    else
		state = STATE2;
	    break;
    .
    .
    .
    }
}

Note that with this model,  states may occur in any order and even
repetitively.  The "if...goto" construct is simply a sequential case of the
general state machine.

-----------------
Charles Lambert

terry@wsccs.UUCP (Every system needs one) (04/30/88)

In article <3490@bunker.UUCP>, garys@bunker.UUCP (Gary M. Samuelson) writes:
[...]
> What you really want is to get an interrupt if a key is pressed.
> If you can do that, then the code becomes much simpler.  If you
> can't get either a "key pressed" interrupt or an interval timer
> interrupt, then use a state machine.  (Credit has to go to Dave
> Burton; although I frequently use state machines, I hadn't thought of it
> in the previous case.)

how's about:

extern volatile key_interrupt;

for( ;;) {

	switch( whatever) {
	case 1:
	...
	case 2:
	...
	default:
	...
	}
	if( key_interrupt)
		break;
}


| Terry Lambert           UUCP: ...{ decvax, ihnp4 } ...utah-cs!century!terry |
| @ Century Software        OR: ...utah-cs!uplherc!sp7040!obie!wsccs!terry    |
| SLC, Utah                                                                   |
|                   These opinions are not my companies, but if you find them |
|                   useful, send a $20.00 donation to Brisbane Australia...   |
| 'Admit it!  You're just harrasing me because of the quote in my signature!' |

chris@mimsy.UUCP (Chris Torek) (04/30/88)

>>Personally, I don't care diddly-squat about how ugly the code coming out
>>of the compiler is.  I don't usually read it.  What I care about is the
>>cleanliness of the source code, which I do have to read, and the speed and
>>correctness of the object code.  Turning clean human-readable notation into
>>ugly fast code is the compiler's *JOB*.  [Henry Spencer]

In article <504@wsccs.UUCP> terry@wsccs.UUCP (Every system needs one) writes:
>You don't agree that less of the same instructions == faster code?

I imagine he does.  What do goto statements have with fewer
instructions in the machine code?  Answer: very little.  Indeed, in a
straightforward compiler `goto's produce branch instructions, which
must be executed in addition to the inline instructions at the label to
which the branch branches.  So using `goto's often means executing
*more* instructions, not fewer.  Also note that in some architectures,
branches are quite a bit slower than `regular' instructions; that one
extra branch to merge with common code may take as much time as ten or
fifteen of the instructions at the common code point.

>How does a goto differ from a break statement when used to exit a for
>statement to the statement immediately after it... pages of code later?

`goto' statements have the `come-from' problem.  (Fortunately, and
especially with well-chosen labels, this problem is small enough in C,
given a decent editor.)  As an example, recently I was fixing various
bugs in the 4BSD Vax peephole optimiser (see comp.bugs.4bsd).  This
thing is full of `goto's; in several instances I had to verify that the
only way to reach some particular label was from one nearby `goto'.  It
is by no means obvious, given the ~400 line---and ugly multi-statement
lines at that---`bmove' routine.

Personally, I have little trouble with an occasional `goto', but I
have noticed that use of `goto's tends to coincide with other practises
that, all together, reduce readability and maintainability.

As an aside, Terry mentions that [edited somewhat]

>I happen to write code that uses
>	for( ;;) {
>instead of
>	while( 1) {
>as I need the best speed out of the hardware I can get and the 'for'
>avoids a test instruction being generated.

Any compiler that generates a `test 1' instruction for the while(1)
loop should not be discarded lightly.  It should be thrown away with
great force.  Great grief!, even PCC does not test constants!

>Certainly, the 'while' is better at self-documenting,

Is it?  I happen to prefer `for (;;)'---to me this is an idiomatic
expression for `forever'.  (Using

	#define EVER ;;
	for (EVER)

however, is tacky :-) .)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

henry@utzoo.uucp (Henry Spencer) (05/01/88)

> > Language designers and standardizers do have to consider badly-written
> > existing code...
> 
> Standardizers, yes; designers, no.  If you degisign a language, then there is
> not existing code.

Only if you are designing a totally new language, as opposed to one like C++
that is upward-compatible with an existing language to some degree.  In real
situations as opposed to classroom exercises, upward-compatible extensions
are rather more common than from-scratch designs.

> ANSI isn't considering "badly written" code, aparrently...

Not true, actually.  X3J11 does not feel *compelled* to consider badly-
written existing code.  Sometimes it does, though; there are concessions
to such pragmatic issues here and there, where it doesn't do too much
violence to other objectives.

> although defining "badly written" in a standard that makes something badly
> written is begging the question.

Only if you believe that no previous standard existed, which is wrong.  There
was no *formal* prior standard, and this caused a lot of fuzziness, but there
was consensus on most things.  (Otherwise formal consensus standardization
like X3J11 would be impossible, after all.)  In the absence of a carefully-
written formal standard, there is more room for debate about whether specific
code is badly written, but the term remains meaningful.

> > ... Turning clean human-readable notation into
> > ugly fast code is the compiler's *JOB*.
> 
> You don't agree that less of the same instructions == faster code?

IF other things are equal (they usually aren't), and IF the generated code
is in fact different (it often isn't), then it is faster code.  So what?
Remember, I do not advocate bashing code after the fact to remove gotos;
my experience is that well-organized code never needs them in the first
place, so efficiency comparisons between goto code and bashed versions of
it are irrelevant.

> ...  Are you trying to tell us that you have *NEVER* used a goto?

Disregarding maintenance of goto-containing existing code, which sometimes
is done under time-and-effort constraints that make major cleanup impossible,
I haven't used one in quite a few years.  I wouldn't say "never", but I
don't recall the last occasion.

> How does a goto differ from a break statement when used to exit a for
> statement to the statement immediately after it... pages of code later? ...

If you write such things, I suppose the answer is "not much".  Personally,
I consider *any* form of exit (except a function return) that goes to a
point pages later to be a serious botch.

> Why can't goto's be used, in your book, to handle non-standard conditions?

Because there are better ways.

> > I'm not sure I've ever used a flag just to avoid a goto; certainly I haven't
> > done it recently.	...
> > I've only programmed in C for 13 years.
> 
> What do you write?

Everything from small patches for existing code to quite large programs.
The one major gap in my experience is not much involvement in huge multi-
programmer multi-year projects... which in my opinion are doomed anyway
unless they can be split into manageable pieces.

> For someone as vehnemently against 'noalias' as your .sig implies, how can
> you berate a current language feature? ...

Criticism of new mistakes does not require embracing old ones.  Do remember,
also, that I berate human use of the feature, not its existence -- I have no
quarrel with its use in mechanically-generated code, for example.

> And how can you respect DMR's concept
> of C enough to quote him on it, but not respect his decision to include the
> 'goto' statement?  Your appeal to his authority is a little inconsistent.

Even if one ignores some of the considerations mentioned above, it is quite
possible to respect Dennis's overall concept of the language and his views
on certain specific issues while disagreeing with him on others.
-- 
NASA is to spaceflight as            |  Henry Spencer @ U of Toronto Zoology
the Post Office is to mail.          | {ihnp4,decvax,uunet!mnetor}!utzoo!henry

levy@ttrdc.UUCP (Daniel R. Levy) (05/02/88)

Henry,

If you really, truly believe that "properly designed" code practically never
needs a goto, you ought to write a book on the subject.  I mean this in all
seriousness.  Just lording it over the "unenlightened" masses (actually,
people who program AT ALL aren't a dumb bunch) without sharing the full secrets
of your wisdom is tantamount to being smart alecky.
-- 
|------------Dan Levy------------|  Path: ihnp4,<most AT&T machines>!ttrdc!levy
|              AT&T              |  Weinberg's Principle:  An expert is a
|       Data Systems Group       |  person who avoids the small errors while
|--------Skokie, Illinois--------|  sweeping on to the grand fallacy.

bts@sas.UUCP (Brian T. Schellenberger) (05/03/88)

In article <64@lakart.UUCP> dg@lakart.UUCP (David Goodenough) writes:
|
|The ONLY time I use a goto is because C doesn't have a 'break 2' construct:
|Maybe someone should suggest it to the ANSI crowd - it can't be that hard to do.

I submit that goto's are clearer than "break 2", and that the sentiment to
add "break n" in order to purge gotos is a sign of people who have gotten so
wrapped up a particular manifestation (gotos) of a problem (obscure code) that
they are moved to ask for treatment for the symptoms even when they make the
disease worse.

This reminds me of the military, which is always fighting the previous war.

(I would, however, support "break loop" for the special case of breaking out
of a while/do/for loop from inside of a nested "switch".  I find the inability
to get out of there cleanly very annoying.)
-- 
                                                         --Brian.
(Brian T. Schellenberger)				 ...!mcnc!rti!sas!bts

. . . now at 2400 baud, so maybe I'll stop bothering to flame long includes.

peter@athena.mit.edu (Peter J Desnoyers) (05/04/88)

In article <490@sas.UUCP> bts@sas.UUCP (Brian T. Schellenberger) writes:
>(I would, however, support "break loop" for the special case of breaking out
>of a while/do/for loop from inside of a nested "switch".  I find the inability
>to get out of there cleanly very annoying.)
>-- 
>                                                         --Brian.
>(Brian T. Schellenberger)				 ...!mcnc!rti!sas!bts

I would consider the semantics of the switch statement to be the worst
botch in the C language, obviously induced by reading lots of
assembler code. Not to say that it's horrible, or anything, but 95% of
the time I use a switch statement I don't use cases that fall through;
whereas I find myself wishing I could use a switch to figure out how
to break out of a loop a lot more than 5% of the time. (So far I've
used gotos for this.) I would rather that the switch construct was
used in the following way:

   switch (n)
   {
     case foo:
       statement_or_block
     case bar:
   }

rather than overloading 'break' with two different meanings - one for
switches, and another for do, while, and for loops.  I would accept
the use of 'continue' to fall through, even though the net aesthetic
improvement would be zero. Of course, we can't change it now, and it's
not too broken to use by any means...

				Peter Desnoyers
				peter@athena.mit.edu

daveb@laidbak.UUCP (Dave Burton) (05/04/88)

In article <2639@ttrdc.UUCP> levy@ttrdc.UUCP (Daniel R. Levy) writes:
|Henry,
|If you really, truly believe that "properly designed" code practically never
|needs a goto, you ought to write a book on the subject.  I mean this in all
|seriousness.  Just lording it over the "unenlightened" masses (actually,
|people who program AT ALL aren't a dumb bunch) without sharing the full secrets
|of your wisdom is tantamount to being smart alecky.

Such a book already exists: _Software Tools_ by Kernighan & Plauger (and
its sister, _Software Tools in Pascal_). This book provide an excellent
example of 'good code', without using (any?) gotos. By extending FORTRAN
to include control flow constructs besides the goto, K&P were able to write
some moderately sophisticated programs (a roff-like text formatter, a text
editor, and a ratfor preprocessor) without gotos.

I would bet that most of you have at least heard of these books, which makes
me wonder why nobody seems to acknowledge their existence, especially in
light of all the recent 'what constitutes a good program' discussion. I have
found them invaluable.

terry@wsccs.UUCP (Every system needs one) (05/14/88)

In article <1988Apr30.230243.15728@utzoo.uucp>, henry@utzoo.uucp (Henry Spencer) writes:
> > > Language designers and standardizers do have to consider badly-written
> > > existing code...
> > 
> > Standardizers, yes; designers, no.  If you design a language, then there
> > is not existing code.
> 
> Only if you are designing a totally new language, as opposed to one like C++
> that is upward-compatible with an existing language to some degree.  In real
> situations as opposed to classroom exercises, upward-compatible extensions
> are rather more common than from-scratch designs.

This has no application to the subject of ANSI C introducing incompatibilities,
unless you are implying that ANSI C is an upward compatible language rather
than the standardization of an existing one.

> > ANSI isn't considering "badly written" code, aparrently...
> 
> Not true, actually.  X3J11 does not feel *compelled* to consider badly-
> written existing code.  Sometimes it does, though; there are concessions
> to such pragmatic issues here and there, where it doesn't do too much
> violence to other objectives.

Hmmm... this seems to lend even more creedence to the idea that what ANSI is
doing is designing, not standardizing, when added to your prior statement.

> > although defining "badly written" in a standard that makes something badly
> > written is begging the question.
> 
> Only if you believe that no previous standard existed, which is wrong.  There
> was no *formal* prior standard, and this caused a lot of fuzziness, but there
> was consensus on most things.  (Otherwise formal consensus standardization
> like X3J11 would be impossible, after all.)  In the absence of a carefully-
> written formal standard, there is more room for debate about whether specific
> code is badly written, but the term remains meaningful.

Yes, but if the the code was not defined as "badly written" before the informal
standard is "formalized" and is defined as "badly written" afterward, then
the formalization has changed the definition and can not truly be considered
to be "standardization".  It reminds me of that Bill Cosby routine where
Noah tells God "You change one of them".

> > > ... Turning clean human-readable notation into
> > > ugly fast code is the compiler's *JOB*.
> > 
> > You don't agree that less of the same instructions == faster code?
> 
> IF other things are equal (they usually aren't), and IF the generated code
> is in fact different (it often isn't), then it is faster code.  So what?

Well, that "so what?" kind of put a damper on any of the reasonable arguments
I could have used to refute the implication that slow code is a bad idea when
compared to a trivial difference in coding style.

> Remember, I do not advocate bashing code after the fact to remove gotos;
> my experience is that well-organized code never needs them in the first
> place, so efficiency comparisons between goto code and bashed versions of
> it are irrelevant.

Never, huh?  Are you saying that everybody who has ever used a goto in the
first place is, in fact, writing badly organized code?  This is ridiculous.
Am I expected to apply this to all languages?  What do I use instead of a
branch instruction in assembly?  Repeated instructions?

> > ...  Are you trying to tell us that you have *NEVER* used a goto?
> 
> Disregarding maintenance of goto-containing existing code, which sometimes
> is done under time-and-effort constraints that make major cleanup impossible,
> I haven't used one in quite a few years.  I wouldn't say "never", but I
> don't recall the last occasion.
> 
> > How does a goto differ from a break statement when used to exit a for
> > statement to the statement immediately after it... pages of code later? ...
> 
> If you write such things, I suppose the answer is "not much".  Personally,
> I consider *any* form of exit (except a function return) that goes to a
> point pages later to be a serious botch.

For complicated algorythms which defy simplification, this makes for a great
deal of pushing and popping, as well as greatly complicating the use of
for statements, which must have an additional test to check to see if the
flag is set.

> > Why can't goto's be used, in your book, to handle non-standard conditions?
> 
> Because there are better ways.

Such as?  Consider that you have a bunch of non-global fd's which have to
be closed prior to exiting.  In addition, each is required to have a byte
sequence that indicates "END-OF-DATA" for another program.  How is writing
this with a procedure that requires 1) making the fd's global or 2) passing
all of them, as well as generating 6 or so function references for the 6 or
so locations where program flow determines an exit should occurr intrinsically
better than simple goto statements to one location?

> > > I've only programmed in C for 13 years.
> > 
> > What do you write?
> 
> Everything from small patches for existing code to quite large programs.
> The one major gap in my experience is not much involvement in huge multi-
> programmer multi-year projects... which in my opinion are doomed anyway
> unless they can be split into manageable pieces.

How large is quite large?  How do you provide

	1) utility
	2) readability
	3) speed
	4) more speed

> Criticism of new mistakes does not require embracing old ones.  Do remember,
> also, that I berate human use of the feature, not its existence -- I have no
> quarrel with its use in mechanically-generated code, for example.

A mechanical code generator that can't generate code which fits into a
person's arbitrary standard of "goodness" is not a good thing, and therefore
should not be used.  Philosophically, this is why I believe there will
always be programmers.  Machines are too dumb to program well, and humans
are (mostly) too smart to program mechanically... among other reasons for
this being true is the simple, Darwinistic phrase "you're fired".  Bad
programmers "go away".


| Terry Lambert           UUCP: ...{ decvax, ihnp4 } ...utah-cs!century!terry |
| @ Century Software        OR: ...utah-cs!uplherc!sp7040!obie!wsccs!terry    |
| SLC, Utah                                                                   |
|                   These opinions are not my companies, but if you find them |
|                   useful, send a $20.00 donation to Brisbane Australia...   |
| 'Admit it!  You're just harrasing me because of the quote in my signature!' |

bill@proxftl.UUCP (T. William Wells) (05/20/88)

Under ordinary circumstances, there is exactly one place where a
human C coder might use a goto.  This is to implement multi-level
breaks and continues.

I say this, having managed (and written huge chunks of) a 17,000
line software system (and that is only the part we sell, and does
not include development tools).  I have programmed in C for six
years now and have NEVER used a goto.  We have uncounted
megabytes of C code written in-house.  None of it (to my
knowledge) contains a goto.  The closest thing we have to a goto
is setjmp/longjmp, used to implement a multi-level return (and
that is a recent change, one whose contemplation caused much
debate).

With that aside, let me explain why the goto discussion is really
fruitless.  People have observed that gotos are used in a lot of
bad code.  From this it is concluded that gotos are bad.  This is
really bad logic.  Try this: programmers have been observed to
write bad code; therefore, programmers are bad!

THERE IS NOTHING WRONG WITH GOTO.  (And how do I reconcile with
my mouthing off above?  Wait and see...) The thing that is
screwed up is the control structures being implemented with the
gotos.

The whole point of the structured programming debate is this:
every program has a control structure; some of these control
structures are better than others.  Whether you use gotos or some
other language feature to implement the control structure does
not change what the control structure is nor does it affect the
goodness of the control structure.

The quality of your program is strongly influenced by the quality
of its control structures.  Furthermore, you want that control
structure to be obvious and understandable to the reader of the
program.  This implies that you use language features that make
your use of a control structure obvious.

So, the first question should be: what are the good control
structures?

The second question should be: given a particular language, how
should the control structures be implemented?

Ok, so what makes a control structure good? Well, the basic
answers are: a control structure is good if it is

    1) appropriate to solving programming problems.
    2) easy to write.
    3) easy to understand.
    4) easy to maintain.
    5) ... add your own as long as they do not contradict the above

There are obviously lots of control structures that meet these
requirements and you do not have to use all of them.  In fact,
you should pick a set of those which are most appropriate for
your programming environment and use them.  This set should be,
in some sense, a minimum one; for example, if you have two
control structures which can accomplish the same thing, but one
is easier to use than the other (for you), pick the easier one
and forget the other.  All other things being equal, a smaller
number of control structures helps make your program easier to
understand.

Now, I hope my claim about our C programs is understandable.  But
if not, here is what it amounts to: I have chosen a set of
control structures which is appropriate to programming in C, for
the kind of programming tasks that I do.  It happens that, while
my set of control structures includes multi-level breaks and
continues (which would be implemented with a goto), I have never
had need of one.  Given the amount of code I write, it seems to
me that one might never need to use an explicit goto in C code.

Now that I think of it, here is a reason to avoid naked gotos in
C code: for all other constructs, the control structure being
implemented is obvious from the keywords employed.  This is not
true for goto.  Therefore, supposing that you have found a
control structure that you have to implement using gotos in C,
you should dress the goto up.  As an example, suppose that you
are using the state machine control structure.  I normally code
it as:

	state = STATE_INIT;
	while (state != STATE_DONE) {
		switch (state) {
		case STATE_INIT:
		...
		}
	}

However, this is not the most efficient way to do it.  You could
also implement it as:

/* Wherever you see the macros state and nextstate being used,
   you will be seeing a state machine.  The state macro defines
   the start of a state.  The nextstate macro causes a transfer
   of control to another state of the same machine.  A state
   machine starts at a #define of statepref and ends with
   state(DONE).  */

#define dummy(x)        x
#define state(x)        dummy(statepref)x
#define nextstate(x)    goto dummy(statepref)x

#ifdef statepref
#undef statepref
#endif
#define statepref       STATE_
	state(INIT):
		... code for this state
		nextstate(DONE);
	... more states with the appropriate code
	state(DONE):
	... code after the state machine

(N.B.  I am aware that not all preprocessors will do what I want
here; for real portability, you would explicitly write the
prefixes.  Also, this method fails for nested state machines,
something I have occasionally had need of.)

Some of you will no doubt be thinking: but why should I go to all
this effort when I could just use the goto directly?  Well, if
this was all you did with goto, I don't really see any reason why
not (but I do think your program should include a comment saying
that you use goto for state machines and describes how you
structure it).  If, however, you have more than one way of using
goto, you should clothe the gotos somehow so that the reader of
the program knows what control structure your goto belongs to.
(After all, a while is just a disguised goto :-)