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

Pseudo subroutines with macros

18 views
Skip to first unread message

Anton Shepelev

unread,
Oct 8, 2023, 8:23:06 AM10/8/23
to
Hello, all

While comp.lang.c is being choked by spammers, let me ask it
in .c++ as well. Is it possible with the C preprocessor to
generate code patterns of the following form:

if( <expr_1> )
{ ret = 1;
goto PREPROC;
RET_1:
<stmt_1>;
return;
}
if( <expr_2> )
{ ret = 2;
goto PREPROC;
RET_2:
<stmt_2>;
return;
}
... // many lines of intermediate code
switch( ret )
{ case 1: goto RET_1; break;
case 2: goto RET_2; break;
...
}

where the programmer (more or less) only specifies the test
expressions and corresponding statements, e.g.:

#TEST( <expr_1> )
<stmt_1>; // may bec compund, many lines
#TEST( <expr_2> )
<stmt_2>;
#INTERMEDIATE
#TEST_END

--
() ascii ribbon campaign -- against html e-mail
/\ www.asciiribbon.org -- against proprietary attachments

Anton Shepelev

unread,
Oct 8, 2023, 8:48:08 AM10/8/23
to
I wrote:

> if( <expr_1> )
> { ret = 1;
> goto PREPROC;
> RET_1:
> <stmt_1>;
> }
> if( <expr_2> )
> { ret = 2;
> goto PREPROC;
> RET_2:
> <stmt_2>;
>
> }
> ...
> switch( ret )
> { case 1: goto RET_1; break;
> case 2: goto RET_2; break;
> ...
> }

In the code above, label PREPROC is missing. It should be
placed before the `switch' statement.

Pavel

unread,
Oct 8, 2023, 2:35:12 PM10/8/23
to
Anton Shepelev wrote:
> I wrote:
>
>> if( <expr_1> )
>> { ret = 1;
>> goto PREPROC;
>> RET_1:
>> <stmt_1>;
>> }
>> if( <expr_2> )
>> { ret = 2;
>> goto PREPROC;
>> RET_2:
>> <stmt_2>;
>>
>> }
>> ...
>> switch( ret )
>> { case 1: goto RET_1; break;
>> case 2: goto RET_2; break;
>> ...
>> }
>
> In the code above, label PREPROC is missing. It should be
> placed before the `switch' statement.
>
Straightforward following your description would give something like:

#define STRANGE_IF(n, e, s) if (e) { ret = n; goto PREPROC; RET_##n: s; }
STRANGE_IF(1, a==b, b=c)
STRANGE_IF(2, c==b, c=d)
..
#undef STUPID_IF
...
PREPROC:
switch(ret)
{
#define STRANGE_CASE(n) case n: goto RET_##n; break;
STRANGE_CASE(1)
STRANGE_CASE(2)
..
#endif STRANGE_CASE
}

Is this what you are looking to do?

HTH
-Pavel

Anton Shepelev

unread,
Oct 8, 2023, 3:10:55 PM10/8/23
to
Pavel:

> Straightforward following your description would give something like:
>
> #define STRANGE_IF(n, e, s) if (e) { ret = n; goto PREPROC; RET_##n: s; }
> STRANGE_IF(1, a==b, b=c)
> STRANGE_IF(2, c==b, c=d)
> ..
> #undef STUPID_IF
> ...
> PREPROC:
> switch(ret)
> {
> #define STRANGE_CASE(n) case n: goto RET_##n; break;
> STRANGE_CASE(1)
> STRANGE_CASE(2)
> ..
> #endif STRANGE_CASE
> }
>
> Is this what you are looking to do?

Yes, except I hoped for a less redundant way to specify this
code. You manually count from 1..n twice. If a better
version is impossible in C, then I think I will be going
that way.

Say! You forgot to rename into STRAGE one occurance
STUPID :-) Thank you, though.

Did you intentionally drop comp.lang.c ?

Alf P. Steinbach

unread,
Oct 8, 2023, 5:06:12 PM10/8/23
to
On 2023-10-08 2:22 PM, Anton Shepelev wrote:
> Hello, all
>
> While comp.lang.c is being choked by spammers, let me ask it
> in .c++ as well. Is it possible with the C preprocessor to
> generate code patterns of the following form:
>
> if( <expr_1> )
> { ret = 1;
> goto PREPROC;
> RET_1:
> <stmt_1>;
> return;
> }
> if( <expr_2> )
> { ret = 2;
> goto PREPROC;
> RET_2:
> <stmt_2>;
> return;
> }
> ... // many lines of intermediate code
PREPROC:
> switch( ret )
> { case 1: goto RET_1; break;
> case 2: goto RET_2; break;
> ...
> }
>
> where the programmer (more or less) only specifies the test
> expressions and corresponding statements, e.g.:
>
> #TEST( <expr_1> )
> <stmt_1>; // may bec compund, many lines
> #TEST( <expr_2> )
> <stmt_2>;
> #INTERMEDIATE
> #TEST_END
>

What's the purpose of the jumps to the `switch` and back? It does nothing.

- Alf

Anton Shepelev

unread,
Oct 8, 2023, 6:25:18 PM10/8/23
to
Alf P. Steinbach:

> What's the purpose of the jumps to the `switch` and back?
> It does nothing.

Shall I quote my entire code from the previous article, or
may I count on everybody's smart newsreaders that can step
up the thread at a single keystroke?

To answer your question, I was thinking of implementing a
state-machine, where the entire cycle or tick (entry, exit,
transition) is located in a single function and executed in
a single invocation of it. The transition-handling code is
specific for each transition leading out of the current
state. The exit-handling code is common to the state and
must be executed /before/ the transition-handling code, but
/only/ if a transition occurs, therefore:

if( trans_cond_1 )
{ ret = 1; /* a transition must be performed */
goto EXIT; /* but we must exit current state first */
TRANS_1:
/* transition-handler here */
return;
}
...
return; /* no transition */
switch( ret )
{ case 1: goto TRANS_1; break;
...
}

See what I mean?

Pavel

unread,
Oct 10, 2023, 10:56:42 PM10/10/23
to
Anton Shepelev wrote:
> Pavel:
>
>> Straightforward following your description would give something like:
>>
>> #define STRANGE_IF(n, e, s) if (e) { ret = n; goto PREPROC; RET_##n: s; }
>> STRANGE_IF(1, a==b, b=c)
>> STRANGE_IF(2, c==b, c=d)
>> ..
>> #undef STUPID_IF
>> ...
>> PREPROC:
>> switch(ret)
>> {
>> #define STRANGE_CASE(n) case n: goto RET_##n; break;
>> STRANGE_CASE(1)
>> STRANGE_CASE(2)
>> ..
>> #endif STRANGE_CASE
>> }
>>
>> Is this what you are looking to do?
>
> Yes, except I hoped for a less redundant way to specify this
> code. You manually count from 1..n twice. If a better
> version is impossible in C,
I saw some clever preprocessor tricks that avoid repetition in different
situations but I find these difficult to read so I try to avoid (in C++
I usually can). If you are determined to solve your problem with a
clever macro, take a look at

https://codereview.stackexchange.com/questions/237410/macro-to-generate-an-enum-and-an-array-of-strings

Vaguely speaking, this technique allows "defining many aspects of a
thing in one place" given a list of "things". That is, every one of many
"things" is mentioned only once. Maybe you can figure out how to use it
to your advantage.

HTH

> then I think I will be going
> that way.
>
> Say! You forgot to rename into STRAGE one occurance
> STUPID :-)
:-)

> Thank you, though.
You are welcome.

>
> Did you intentionally drop comp.lang.c ?
Yes. I guessed those spammers you mentioned select target thread by
activity, so decided to lay low.
0 new messages