I have a set of target macros for which I want to generate aliases based on a choosing macro, like so:
Choosing macro:
#define I2C_MODULE 1
Alias macros (conceptual form):
#define I2C_MODULE_BASE I2C<Value of I2C_MODULE>_BASE
#define I2C_MODULE_NVIC INT_I2C<Value of I2C_MODULE>
Target macros (from an external file out of my control):
#define INT_I2C0 24
#define INT_I2C1 53
...
#define I2C0_BASE 0x40020000
#define I2C1_BASE 0x40021000
...
I wanted to have the preprocessor generate the alias macros I2C_MODULE_BASE
and I2C_MODULE_NVIC
based on the
choosing macro I2C_MODULE
, but after much reading Q1, P1 and many other references I lost track of, I ended up hard-coding their values. Below I show my current working definitions, and then my last failed attempts at generating the macros:
What works:
#define I2C_MODULE 1
#define I2C_MODULE_BASE I2C1_BASE
#define I2C_MODULE_NVIC INT_I2C1
what did not work:
#define I2C_MODULE 1
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
/* Attempt 1 */
#define I2C_MODULE_BASE "I2C" STR(I2C_MODULE) "_BASE"
#define I2C_MODULE_NVIC "INT_I2C" STR(I2C_MODULE)
/* Attempt 2 */
#define _I2C_MODULE_BASE "I2C" STR(I2C_MODULE) "_BASE"
#define _I2C_MODULE_NVIC "INT_I2C" STR(I2C_MODULE)
#define I2C_MODULE_BASE _I2C_MODULE_BASE
#define I2C_MODULE_NVIC _I2C_MODULE_NVIC
EDIT: I expanded upon the accepted answer to get to where I wanted, as follows:
#define PASTE2(a, b) a ## b
#define PASTE3(a, b, c) a ## b ## c
#define _I2C_MODULE_BASE(x) PASTE3(I2C, x, _BASE)
#define _I2C_MODULE_NVIC(x) PASTE2(INT_I2C, x)
#define I2C_MODULE_BASE _I2C_MODULE_BASE(I2C_MODULE)
#define I2C_MODULE_NVIC _I2C_MODULE_NVIC(I2C_MODULE)
This seems to work:
#define I2C_MODULE 1
//Alias macros (conceptual form):
//#define I2C_MODULE_BASE I2C<Value of I2C_MODULE>_BASE
//#define I2C_MODULE_NVIC INT_I2C<Value of I2C_MODULE>
//Target macros (from an external file out of my control):
#define INT_I2C0 24
#define INT_I2C1 53
#define I2C0_BASE 0x40020000
#define I2C1_BASE 0x40021000
#define PASTE2(a, b) a ## b
#define PASTE3(a, b, c) a ## b ## c
#define I2C_MODULE_BASE(x) PASTE3(I2C, x, _BASE)
#define I2C_MODULE_NVIC(x) PASTE2(INT_I2C, x)
extern int i2c_module_base = I2C_MODULE_BASE(I2C_MODULE);
extern int i2c_module_nvic = I2C_MODULE_NVIC(I2C_MODULE);
extern int i2c_module_base_0 = I2C_MODULE_BASE(0);
extern int i2c_module_nvic_0 = I2C_MODULE_NVIC(0);
extern int i2c_module_base_1 = I2C_MODULE_BASE(1);
extern int i2c_module_nvic_1 = I2C_MODULE_NVIC(1);
Sample output (from cpp
):
# 1 "xx.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "xx.c"
# 21 "xx.c"
extern int i2c_module_base = 0x40021000;
extern int i2c_module_nvic = 53;
extern int i2c_module_base_0 = 0x40020000;
extern int i2c_module_nvic_0 = 24;
extern int i2c_module_base_1 = 0x40021000;
extern int i2c_module_nvic_1 = 53;
It is closely based on my answer to C preprocessor and token concatenation.
There are undoubtedly other ways that the I2C_MODULE_BASE
and I2C_MODULE_NVIC
macros could be written, but the key points are:
##
token pasting operator (not the #
stringifying operator).I2C_MODULE_BASE
and PASTE3
).