Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

C-STYLE (goto?)

1 view
Skip to first unread message

Jeffery A. Cavallaro

unread,
Aug 22, 1986, 5:41:05 PM8/22/86
to
I am sure that this case of style has been brought up before. It has been
bothering me for awhile.

Support a particular routine is supposed to perform N steps, where each step
is performed dependent on the success of the previous step, i.e., if any
step fails, then you want to clean up and return.

I realize that:

if (
( (status = step_1()) == SUCCESS) &&
( (status = step_2()) == SUCCESS) &&
.
.
.
( (status = step_3()) == SUCCESS)
);
cleanup();
return (status);

accomplishes this, but significantly ups the routine count. Some refer to this
as good programming practice, but I tend to think of it as overkill for simple
jobs - especially when each routine requires a long header block as may be
required by various programming standards imposed upon (but maybe not accepted
by) the programmer.

Of course, there is the massively nested "if" string, but I can't stand that
style. I tend to really get lost in such bird nests.

The way I like to do it is:

setup_step_1;
if ( (status = step_1()) == FAILURE )
goto abort_operation;

setup_step_2;
if ( (status = step_2()) == FAILURE )
goto abort_operation;

.
.
.

setup_step_n;
if ( (status = step_n()) == FAILURE )
goto abort_operation;

abort_operation:

cleanup();
return (status);

Now, I know a lot of people detest this because of the use of goto's, but this
seems the nicest way to perform this function. I really have nothing against
goto's if they are directed to the same spot (i.e., don't jump back and forth)
and enhance the readability of the code.

Any comments? I am willing to adapt to another reasonable style for such
cases (if anyone really cared).

Thanx for any and all responses (even rude ones),
Jeff

Tom Armistead

unread,
Aug 27, 1986, 1:16:47 PM8/27/86
to
In article <32...@brl-smoke.ARPA>, je...@isi-vaxa.ARPA writes:
> I am sure that this case of style has been brought up before. It has been
> bothering me for awhile.
>
> The way I like to do it is:
>
> setup_step_1;
> if ( (status = step_1()) == FAILURE )
> goto abort_operation;
>
> setup_step_2;
> if ( (status = step_2()) == FAILURE )
> goto abort_operation;
>
> .
> .
> .
>
> setup_step_n;
> if ( (status = step_n()) == FAILURE )
> goto abort_operation;
>
> abort_operation:
>
> cleanup();
> return (status);
>
> Now, I know a lot of people detest this because of the use of goto's, but this
> seems the nicest way to perform this function. I really have nothing against
> goto's if they are directed to the same spot (i.e., don't jump back and forth)
> and enhance the readability of the code.
>
> Any comments? I am willing to adapt to another reasonable style for such
> cases (if anyone really cared).

There is always the use of setjmp and longjmp to acomplish this task,
sometging like this:

#include <setjmp.h>
#define FAILURE 1 /* cannot == 0, due to setjmp conventions */

routine()
{
jmp_buf env; /* envireoment for setjmp,lonjmp */
int val, /* used in return to setjmp */
status;

if (setjmp(env) == FAILURE) /* if abort return, cleanup and exit */
{
cleanup();
return(status);
}
/* setup_step_1 */
if ((status = step_1()) == FAILURE)
longjmp(env,FAILURE); /* return to setjmp call w/FAILURE */

/* setup_step_2 */
if ((status = step_2()) == FAILURE)
longjmp(env,FAILURE); /* return to setjmp call w/FAILURE */

.
.
.

/* setup_step_n */
if ((status = step_n()) == FAILURE)
longjmp(env,FAILURE); /* return to setjmp call w/failure */

.
.
.

/* continue on from here ... */
}

This will accomplish the same thing and possibly not affend the goto haters,
although it is somewhat harder to follow if you are no farmiliar with
setjmp() and lonjmp().

Tom
---
UUCP:
ihnp4\
\killer!toma
/
drillsys!infoswx!convex!dj3b1/

Tom Armistead

Chris Torek

unread,
Aug 30, 1986, 8:47:46 AM8/30/86
to
>In article <32...@brl-smoke.ARPA> je...@isi-vaxa.ARPA writes:
>> setup_step_1;
>> if ( (status = step_1()) == FAILURE )
>> goto abort_operation;
...

>> setup_step_n;
>> if ( (status = step_n()) == FAILURE )
>> goto abort_operation;
>>
>>abort_operation:
>>
>> cleanup();
>> return (status);

>>Now, I know a lot of people detest this because of the use of goto's ....

In article <2...@killer.UUCP> to...@killer.UUCP (Tom Armistead) replies:
>There is always the use of setjmp and longjmp to acomplish this task ....
[example deleted]


>This will accomplish the same thing and possibly not affend the goto haters,
>although it is somewhat harder to follow if you are no farmiliar with
>setjmp() and lonjmp().

Alas, longjmp() is nothing more than goto in disguise. Indeed,
this is a far more powerful version of goto than the `plain C'
goto, and should by rights be correspondingly more offensive to
goto haters. In general, when choosing between two existing
primitives, if one is less powerful but does what you need, use
that. When designing primitives, the choice is more difficult:
something that does less is easier to understand, but you may need
too many of those things, making the whole harder to comprehend.

As to a specific solution to the original problem above, I think
there is no `best' answer, at least not without more information.
I happen to like the pointer table method proposed by grt@twitch;
it can be expanded in a useful way for recovery and/or error
explanation:

int dostep1(), dostep2(), dostep3(), dostep4();
int fix1or3(), fix2();

struct step {
char *s_name; /* name of this step */
int (*s_func)(); /* function that implements it */
int (*s_fixup)(); /* repair after error */
} steps[] = {
{ "step1", dostep1, fix1or3 },
{ "step2", dostep2, fix2 },
{ "step3", dostep3, fix1or3 },
{ "step4", dostep4, 0 },
0 /* marks end of table */
};

f()
{
register struct step *s;
int status;

for (s = steps; s->s_func != NULL; s++) {
if ((status = (*s->s_func)()) != SUCCESS) {
if (s->s_fixup == NULL ||
(*s->s_fixup)(status) != SUCCESS) {
fprintf(stderr, "\
Unrecoverable failure in %s, code %d\n",
s->s_name, status;
break;
}
}
}
return (status);
}

There may be cases, however, where a direct-coded state machine
with a `switch' statement would be better; and there may be cases
where the original code runs fastest and/or is clearest (whichever
is more important to the coder/maintainer and user).
--
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1516)
UUCP: seismo!umcp-cs!chris
CSNet: chris@umcp-cs ARPA: ch...@mimsy.umd.edu

c...@iuvax.uucp

unread,
Sep 2, 1986, 4:48:00 PM9/2/86
to

> /* ---------- "C-STYLE (goto?)" ---------- */
> ....


>
> Now, I know a lot of people detest this because of the use of goto's, but this
> seems the nicest way to perform this function. I really have nothing against
> goto's if they are directed to the same spot (i.e., don't jump back and forth)
> and enhance the readability of the code.
>
> Any comments? I am willing to adapt to another reasonable style for such
> cases (if anyone really cared).

The principle of exception handling in software engineering is
well accepted and practiced today, especially through the direct support of
Ada language. You shall find more and more people start to feel
comfortable with this disciplined use of goto.


C.J.Lo
Dept. of CIS, IUPUI
UUCP : ...!iuvax!cjl
ARPA : cjl@Indiana@CSNet-Relay

0 new messages