public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* 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).