Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stringify first level macro expansion C

Is it possible to stringify this C macro:

 #define GPIO_INT_PIN (GPIO_PORT_D|GPIO_PIN_IRQ_RISING|GPIO_PIN5)

using something like

 MY_STRINGFY(GPIO_INT_PIN) 

to get

"(GPIO_PORT_D|GPIO_PIN_IRQ_RISING|GPIO_PIN5)" ?

like image 744
Heeryu Avatar asked Jan 23 '14 13:01

Heeryu


2 Answers

If you have such two definitions

#define STRINGIFY(s) #s
#define MY_STRINGIFY(s) STRINGIFY(s)

MY_STRINGIFY does what you want - expands its argument and adds quotes after.

like image 94
Wojtek Surowka Avatar answered Sep 22 '22 15:09

Wojtek Surowka


Yes it is possible. Read about stringizing in GCC cpp documentation.

 #define STRINGIFY(It) #It
 #define MY_STRINGIFY(It) STRINGIFY(It)

I corrected my answer thanks to Wojtek Surowka's one

then use MY_STRINGIFY(GPIO_PORT_D|GPIO_PIN_IRQ_RISING|GPIO_PIN5) which would work much better if you use an enum to define the constants, e.g.

enum Gpio_stuff_en {
     GPIO_PORT_D=5,
     GPIO_PIN_IRQ_RISING=17,
     GPIO_PIN5=23
};

Of course that won't work as you want if you need GPIO_PORT_D to be a macro, .e.g. because it expands to some non-constant-literal expression (like a variable, or an access to a field of some global structure, etc....)

As a counter-example:

#define FOO 1
#define BAR 2
#define STRINGIFY(s) #s
#define MY_STRINGIFY(s) STRINGIFY(s)

MY_STRINGIFY(FOO|BAR)

is expanded to "1|2" not to "FOO|BAR", if your remove the two #define-s for FOO and for BAR and replace them with

enum {
  FOO=1,
  BAR=2 };

you really get the expansion "FOO|BAR" as you want. Check with gcc -C -E ...

Also:

enum {FOO=1, BAR=2};
#define FOOORBAR (FOO|BAR)
#define STRINGIFY(s) #s
#define MY_STRINGIFY(s) STRINGIFY(s)

MY_STRINGIFY(FOOORBAR)

is expanded as "(FOO|BAR)" . But if you use #define for FOO and for BAR you get the "(1|2)" expansion.

Maybe you could add in your own header, after including the external header defining GPIO_PORT_D etc... as a literal constants, something like :

enum {en_GPIO_PORT_D= GPIO_PORT_D,
      en_GPIO_PIN_IRQ_RISING= GPIO_PIN_IRQ_RISING,
      en_GPIO_PIN5= GPIO_PIN5};
#undef GPIO_PORT_D
#undef GPIO_PIN_IRQ_RISING 
#undef GPIO_PIN5
#define GPIO_PORT_D en_GPIO_PORT_D
#define GPIO_PIN_IRQ_RISING en_GPIO_PIN_IRQ_RISING
#define GPIO_PIN5 en_GPIO_PIN5

and then you'll get more readable stringified constants (but not exactly what you dream of).

like image 32
Basile Starynkevitch Avatar answered Sep 21 '22 15:09

Basile Starynkevitch