ARPAVAX:UNKNOWN:G:elect (10/25/82)
For my two cents worth, I think the formatting
if (<condition>) {
<statements>;
:
:
}
is the most aesthetically pleasing. It does not seem that there's
any difference between this and the format where the closing brace
is lined up with the `if' as far as telling which block goes with
which conditional, as long as one sticks to one format throughout
a program. For this reason, I think putting rules like this into
a `style manual' is unnecessary. What do people think about some
people's practice of writing structure/union expressions like
structure . member = struct_pointer - > member;
with all the spaces? All of this discussion about style is probably
not going to have a hell of a lot of impact -- programmers as a
lot are rather headstrong. People are going to stick to whatever
style they like. As long as the programmer is consistent and
documents his style conventions (to the extent that, say, identifiers
with all majuscule characters are `defined' constants and so on),
which means he's probably half-way serious about making his code
readable and maintainable, I don't see any problem with style. If
someone is simply messy, no style manual is going to change things.
As far as big projects, of course, some convention should be
established for the sake of communication and productivity among
the many programmers who may be involved.
Harry
ARPAnet: G.antares@Berkeley
LBLG!Harry#pdm@LBL-Unix
UUCP: ...!ucbvax!G:antares
jeff@isi-vaxa.ARPA (Jeffery A. Cavallaro) (08/23/86)
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
toma@killer.UUCP (Tom Armistead) (08/27/86)
In article <3253@brl-smoke.ARPA>, jeff@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@umcp-cs.UUCP (Chris Torek) (08/30/86)
>In article <3253@brl-smoke.ARPA> jeff@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 <264@killer.UUCP> toma@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: chris@mimsy.umd.edu
cjl@iuvax.UUCP (09/02/86)
> /* ---------- "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
karl@haddock (09/11/86)
killer!toma (Tom Armistead) writes: >In article <3253@brl-smoke.ARPA>, jeff@isi-vaxa.ARPA writes: >>[code deleted] >>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. > >There is always the use of setjmp and longjmp ...: [code deleted] >This will accomplish the same thing and possibly not affend the goto haters, Mother of swapper! A longjmp is *worse* than a goto. It's just a goto that doesn't respect function boundaries! Anyone who disapproves of goto but considers longjmp acceptable is objecting to the keyword rather than the concept ("I know goto is bad because my teacher said so"). (I'm not flaming Tom; his posting did not imply approval.) Lest you misunderstand me -- I am not a "goto hater". There are three valid uses of goto, one of which is error handling. Jeff, your program is a good example of proper goto usage. Leave it that way, but learn why it's right. Karl W. Z. Heuer (ima!haddock!karl; karl@haddock.isc.com), The Walking Lint