🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.std.c
Article #3507

Re: Multi-level break and elimination of GOTO

#3507
From: Ray Dunn
Date: Tue, 28 Nov 1995 17:06
138 lines
5350 bytes
In referenced article, Fredrik Bredberg says...
>Andrew Dunbar, he of the long rambling signature, writes:
>>     iteration-statement:
>>         while <loop-name> ( <expression> ) <statement> 
>>         do <statement> while <loop-name> ( <expression> ) ; 
>>         for <loop-name> ( <expression>opt ; <expression>opt ; 
>>                 <expression>opt ) <statement>
>>
>>     selection-statement: 
>>         switch <loop-name> ( <expression> ) <statement>
>> 
>>     jump-statement: 
>>         break <loop-name> ; 
>>         continue <loop-name> ;
>
>Make that:
>
>      selection-statement: 
>          switch <switch-name> ( <expression> ) <statement>
>  
>      jump-statement: 
>          break <loop-name | switch-name> ; 
>          continue <loop-name> ;
>
>And I'll be ready to use this any day.

I have to agree that this looks good even though it's a pity that the 
loop name in do...while has to be associated with the while.

[the following section is not really relevant to comp.std.c but only to 
comp.lang.c]

I've come into this thread late, and hope I'm not repeating any 
suggestion made by others - the following set of 5 simple macros 
implement an almost fully satisfactory method of achieving this ability 
in current 'C' without *overt* goto's (i.e. in the users code).  It's 
interesting that even though I "invented" this quite a few years back, 
I've had to use it very rarely in program design - but when it's 
needed, it's *really* needed!

It's not for those who dislike extending the language with macros, but 
it does work quite nicely, is very readable, and retains program 
structure without ad-hoc use of goto's.

/************ Ray's named loops and switches ************/

#define NamedLoop(name)   if (0) {                       \
                            break_loop_##name: break;    \
                            cont_loop_##name:  continue; \
                          }

#define NamedSwitch(name) if (0) {                       \
                            break_switch_##name: break;  \
                          } 

#define BreakNamedLoop(name)    goto break_loop_##name
#define ContinueNamedLoop(name) goto cont_loop_##name
#define BreakNamedSwitch(name)  goto break_switch_##name

/******* end named loops and switches definitions *******/

Capitalize the names if that is your convention for all macros.

NamedLoop can be called anywhere within the body of a loop, but by 
convention for most clarity, should be put as the first statement in 
the loop.

The NamedSwitch call should also be put at the start of the switch, 
before the first case statement (do any compilers complain about this? 
- it's legal Ansi 'C'as far as I can tell)

The false conditional round the body of NamedLoop and NamedSwitch 
ensure that no matter where put, they cannot affect the execution of 
the surrounding code.

BreakNamedLoop, ContinueNamedLoop and BreakNamedSwitch can be called 
from anywhere in the function - this of course is a disadvantage if 
used in a silly manner outside the context of the loop or switch, but 
when used sensibly, provide all the features being looked for here.
So for example:

  switch (control)
  { NamedSwitch(CONTROL);

    case 1:
    {
      for (row = 0;  row < ROWMAX;  row++)
      { NamedLoop(ROWS);

        for (col = 0;  col < COLMAX;  col++)
        {
          statements;
          if (condition1)
          {
            ContinueNamedLoop(ROWS);
          }

          if (condition2)
          {
            statements;
            BreakNamedLoop(ROWS);
          }
          statements;

          if (condition3)
            BreakNamedSwitch(CONTROL);
        }
      }
      break;
    }

    case 2:

    etc.
  }

Many compilers issue warnings for unreferenced labels, so, if you want 
to name *all* your loops, and avoid the warnings, you could define the 
naming macros as:

#define NamedLoop(name)   if (0) {                       \
                            break_loop_##name: break;    \
                            cont_loop_##name:  continue; \
                            goto break_loop_##name;      \
                            goto cont_loop_##name;       \
                          }

#define NamedSwitch(name) if (0) {                       \
                            break_switch_##name: break;  \
                            goto break_switch_##name;    \
                          } 

Whether some compilers might then complain about unreferenced code, 
I've no idea.  MS compilers quietly accept this.
-- 
Ray Dunn (opinions are my own) | Phone: (514) 938 9050
Montreal                       | Phax : (514) 938 5225
ray@ultimate-tech.com          | Home : (514) 630 3749
Technical Details
Message-ID: <49ffi3$jld@ns.RezoNet.NET>
Path: arc1-ca.pugleaf.net!Rezonet.net!news
References: <43pdut$hoh@galaxy.csc.calpoly.edu> <DF8FE3.97H@news.cern.ch> <rnb68gmqlpp.fsf@euax7i3c01.eua.ericsson.se>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!Rezonet.net!news
From: ray@ultimate-tech.com (Ray Dunn)
Newsgroups: comp.std.c,comp.lang.c
Subject: Re: Multi-level break and elimination of GOTO
Date: 28 Nov 1995 17:06:10 GMT
Organization: Ultimate Technographics Inc.
Message-ID: <49ffi3$jld@ns.RezoNet.NET>
References: <43pdut$hoh@galaxy.csc.calpoly.edu> <DF8FE3.97H@news.cern.ch> <rnb68gmqlpp.fsf@euax7i3c01.eua.ericsson.se>
NNTP-Posting-Host: 204.19.230.7
Mime-Version: 1.0
Content-Type: Text/Plain; charset=US-ASCII
X-Newsreader: WinVN 0.99.6