* Recursive variadic macros
@ 2020-11-06 19:51 newcomer
2020-11-07 6:11 ` Tadeus Prastowo
0 siblings, 1 reply; 2+ messages in thread
From: newcomer @ 2020-11-06 19:51 UTC (permalink / raw)
To: gcc-help
[-- Attachment #1: Type: text/plain, Size: 3735 bytes --]
Consider that I want to write a macro that, for a list of arguments, will
generate one (or more) lines of code for each argument. For example
[code]
#define STATES S0, WANTDIGIT, DIGIT, REJECTING, ENDNUMBER, WAVEFORM,
FINISH, ENDOFDATA, OUTPUT_STREAM_ID
typedef enum { STATES} States;
States state = S0;
void showState()
{
#define show1(x, ...) \
case x: Serial.println(#x); break; \
__VA_OPT__(show1(__VA_ARGS__))
switch(state)
{ /* state */
show1(STATES);
} /* state */
#undef show1
}
[/code]
What I expect to generate is
[code]
show1(S0, WANTDIGIT, DIGIT, REJECTING, ENDNUMBER, WAVEFORM, FINISH,
ENDOFDATA, OUTPUT_STREAM_ID)
[/code]
Which should give me
[code]
void showState()
{
switch(state)
{ /* state */
case S0: Serial.println("S0"); break;
case WANTDIGIT: Serial.println("WANTDIGIT"); break;
//..etc.
case OUTPUT_STREAM_ID: Serial.println("OUTPUT_STREAM_ID"); break;
} /* state */
} // showState
[/code]
What I get, though, is
[code]
C:\Users\admin\OneDrive\Projects\Oscilloscope Tests\PWM_test\PWM_test.ino:
In function 'void showState()':
PWM_test:39:19: error: expected ':' before ',' token
39 | #define STATES S0, WANTDIGIT, DIGIT, REJECTING, ENDNUMBER,
WAVEFORM, FINISH, ENDOFDATA, OUTPUT_STREAM_ID
| ^
C:\Users\admin\OneDrive\Projects\Oscilloscope
Tests\PWM_test\PWM_test.ino:48:10: note: in definition of macro 'show1'
48 | case x: Serial.println(#x); break; \
| ^
C:\Users\admin\OneDrive\Projects\Oscilloscope
Tests\PWM_test\PWM_test.ino:52:12: note: in expansion of macro 'STATES'
52 | show1(STATES);
| ^~~~~~
PWM_test:39:19: error: expected primary-expression before ',' token
39 | #define STATES S0, WANTDIGIT, DIGIT, REJECTING, ENDNUMBER,
WAVEFORM, FINISH, ENDOFDATA, OUTPUT_STREAM_ID
| ^
C:\Users\admin\OneDrive\Projects\Oscilloscope
Tests\PWM_test\PWM_test.ino:48:10: note: in definition of macro 'show1'
48 | case x: Serial.println(#x); break; \
| ^
C:\Users\admin\OneDrive\Projects\Oscilloscope
Tests\PWM_test\PWM_test.ino:52:12: note: in expansion of macro 'STATES'
52 | show1(STATES);
| ^~~~~~
C:\Users\admin\OneDrive\Projects\Oscilloscope
Tests\PWM_test\PWM_test.ino:50:11: warning: enumeration value 'WANTDIGIT'
not handled in switch [-Wswitch]
50 | switch(state)
| ^
C:\Users\admin\OneDrive\Projects\Oscilloscope
Tests\PWM_test\PWM_test.ino:50:11: warning: enumeration value 'DIGIT' not
handled in switch [-Wswitch]
C:\Users\admin\OneDrive\Projects\Oscilloscope
Tests\PWM_test\PWM_test.ino:50:11: warning: enumeration value 'REJECTING'
not handled in switch [-Wswitch]
C:\Users\admin\OneDrive\Projects\Oscilloscope
Tests\PWM_test\PWM_test.ino:50:11: warning: enumeration value 'ENDNUMBER'
not handled in switch [-Wswitch]
C:\Users\admin\OneDrive\Projects\Oscilloscope
Tests\PWM_test\PWM_test.ino:50:11: warning: enumeration value 'WAVEFORM' not
handled in switch [-Wswitch]
C:\Users\admin\OneDrive\Projects\Oscilloscope
Tests\PWM_test\PWM_test.ino:50:11: warning: enumeration value 'FINISH' not
handled in switch [-Wswitch]
C:\Users\admin\OneDrive\Projects\Oscilloscope
Tests\PWM_test\PWM_test.ino:50:11: warning: enumeration value 'ENDOFDATA'
not handled in switch [-Wswitch]
C:\Users\admin\OneDrive\Projects\Oscilloscope
Tests\PWM_test\PWM_test.ino:50:11: warning: enumeration value
'OUTPUT_STREAM_ID' not handled in switch [-Wswitch]
exit status 1
expected ':' before ',' token
[/code]
What is going wrong here?
[-- Attachment #2: image001.gif --]
[-- Type: image/gif, Size: 92 bytes --]
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: Recursive variadic macros
2020-11-06 19:51 Recursive variadic macros newcomer
@ 2020-11-07 6:11 ` Tadeus Prastowo
0 siblings, 0 replies; 2+ messages in thread
From: Tadeus Prastowo @ 2020-11-07 6:11 UTC (permalink / raw)
To: newcomer; +Cc: gcc-help
On Fri, Nov 6, 2020 at 8:52 PM <newcomer@flounder.com> wrote:
>
> Consider that I want to write a macro that, for a list of arguments, will
> generate one (or more) lines of code for each argument. For example
>
>
>
> [code]
>
> #define STATES S0, WANTDIGIT, DIGIT, REJECTING, ENDNUMBER, WAVEFORM,
> FINISH, ENDOFDATA, OUTPUT_STREAM_ID
>
>
>
> typedef enum { STATES} States;
>
>
>
>
>
> States state = S0;
>
>
>
> void showState()
>
> {
>
> #define show1(x, ...) \
>
> case x: Serial.println(#x); break; \
>
> __VA_OPT__(show1(__VA_ARGS__))
>
>
>
> switch(state)
>
> { /* state */
>
> show1(STATES);
>
> } /* state */
>
> #undef show1
>
> }
>
> [/code]
>
> What I expect to generate is
>
> [code]
>
> show1(S0, WANTDIGIT, DIGIT, REJECTING, ENDNUMBER, WAVEFORM, FINISH,
> ENDOFDATA, OUTPUT_STREAM_ID)
>
> [/code]
>
> Which should give me
>
> [code]
>
> void showState()
> {
>
> switch(state)
> { /* state */
>
> case S0: Serial.println("S0"); break;
> case WANTDIGIT: Serial.println("WANTDIGIT"); break;
>
> //..etc.
>
> case OUTPUT_STREAM_ID: Serial.println("OUTPUT_STREAM_ID"); break;
>
> } /* state */
>
> } // showState
>
> [/code]
>
>
>
> What I get, though, is
>
> [code]
>
> C:\Users\admin\OneDrive\Projects\Oscilloscope Tests\PWM_test\PWM_test.ino:
> In function 'void showState()':
>
> PWM_test:39:19: error: expected ':' before ',' token
>
> 39 | #define STATES S0, WANTDIGIT, DIGIT, REJECTING, ENDNUMBER,
> WAVEFORM, FINISH, ENDOFDATA, OUTPUT_STREAM_ID
>
> | ^
>
> C:\Users\admin\OneDrive\Projects\Oscilloscope
> Tests\PWM_test\PWM_test.ino:48:10: note: in definition of macro 'show1'
>
> 48 | case x: Serial.println(#x); break; \
>
> | ^
>
> C:\Users\admin\OneDrive\Projects\Oscilloscope
> Tests\PWM_test\PWM_test.ino:52:12: note: in expansion of macro 'STATES'
>
> 52 | show1(STATES);
>
> | ^~~~~~
>
> PWM_test:39:19: error: expected primary-expression before ',' token
>
> 39 | #define STATES S0, WANTDIGIT, DIGIT, REJECTING, ENDNUMBER,
> WAVEFORM, FINISH, ENDOFDATA, OUTPUT_STREAM_ID
>
> | ^
>
> C:\Users\admin\OneDrive\Projects\Oscilloscope
> Tests\PWM_test\PWM_test.ino:48:10: note: in definition of macro 'show1'
>
> 48 | case x: Serial.println(#x); break; \
>
> | ^
>
> C:\Users\admin\OneDrive\Projects\Oscilloscope
> Tests\PWM_test\PWM_test.ino:52:12: note: in expansion of macro 'STATES'
>
> 52 | show1(STATES);
>
> | ^~~~~~
>
> C:\Users\admin\OneDrive\Projects\Oscilloscope
> Tests\PWM_test\PWM_test.ino:50:11: warning: enumeration value 'WANTDIGIT'
> not handled in switch [-Wswitch]
>
> 50 | switch(state)
>
> | ^
>
> C:\Users\admin\OneDrive\Projects\Oscilloscope
> Tests\PWM_test\PWM_test.ino:50:11: warning: enumeration value 'DIGIT' not
> handled in switch [-Wswitch]
>
> C:\Users\admin\OneDrive\Projects\Oscilloscope
> Tests\PWM_test\PWM_test.ino:50:11: warning: enumeration value 'REJECTING'
> not handled in switch [-Wswitch]
>
> C:\Users\admin\OneDrive\Projects\Oscilloscope
> Tests\PWM_test\PWM_test.ino:50:11: warning: enumeration value 'ENDNUMBER'
> not handled in switch [-Wswitch]
>
> C:\Users\admin\OneDrive\Projects\Oscilloscope
> Tests\PWM_test\PWM_test.ino:50:11: warning: enumeration value 'WAVEFORM' not
> handled in switch [-Wswitch]
>
> C:\Users\admin\OneDrive\Projects\Oscilloscope
> Tests\PWM_test\PWM_test.ino:50:11: warning: enumeration value 'FINISH' not
> handled in switch [-Wswitch]
>
> C:\Users\admin\OneDrive\Projects\Oscilloscope
> Tests\PWM_test\PWM_test.ino:50:11: warning: enumeration value 'ENDOFDATA'
> not handled in switch [-Wswitch]
>
> C:\Users\admin\OneDrive\Projects\Oscilloscope
> Tests\PWM_test\PWM_test.ino:50:11: warning: enumeration value
> 'OUTPUT_STREAM_ID' not handled in switch [-Wswitch]
>
> exit status 1
>
> expected ':' before ',' token
>
> [/code]
>
>
>
> What is going wrong here?
While the error can be fixed as follows, the C standard forbids a
recursive macro, and therefore, you must define separate macros as
many as there are levels of a recursion.
#define STATES S0, WANTDIGIT, DIGIT, REJECTING, ENDNUMBER, WAVEFORM,
FINISH, ENDOFDATA, OUTPUT_STREAM_ID
typedef enum { STATES} States;
States state = S0;
void showState()
{
#define show1(x, ...) case x: Serial.println(#x); break; \
__VA_OPT__(show1(__VA_ARGS__))
#define expand(fn_to_call, var_to_expand) \
fn_to_call(var_to_expand)
switch(state)
{ /* state */
expand(show1, STATES);
} /* state */
#undef expand
#undef show1
}
That said, your problem is off-topic for this mailing list because
your problem is a problem about using the C preprocessor, not GCC.
Please ask further questions related to using the C preprocessor
(including techniques to easily define different macros for different
levels of a recursion) in another place to get the best answers
possible.
--
Best regards,
Tadeus
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2020-11-07 6:11 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-06 19:51 Recursive variadic macros newcomer
2020-11-07 6:11 ` Tadeus Prastowo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).