Reputation: 275
I am trying to create a C macro table that takes a series of C function macros and turns it into a list of one of the parameters of the C function macro if another parameter of the C function macro satisfies some condition.
For instance, define a database in FancyPantsTable.h:
#if defined (MY_FANCY_PANTS_TABLE)
FANCY_PANTS_DB( A, 123)
FANCY_PANTS_DB( B, 456)
FANCY_PANTS_DB( C, 456)
FANCY_PANTS_DB( D, 123)
#endif
Then, in FancyPants.c, import the FancyPantsTable.h everywhere you want to make a list.
#define numberSought 456
uint8 my456Array [] = {
#define FANCY_PANTS_DB( aUint8, num ) #if ( num == numberSought sought ) aUint8, #endif
#define MY_FANCY_PANTS_TABLE
#include "FancyPantsTable.h"
#undef MY_FANCY_PANTS_TABLE
};
#define numberSought 123
uint8 my123Array [] = {
#define FANCY_PANTS_DB( aUint8, num ) #if ( num == numberSought sought ) aUint8, #endif
#define MY_FANCY_PANTS_TABLE
#include "FancyPantsTable.h"
#undef MY_FANCY_PANTS_TABLE
};
C macro templates are pain to debug; right at the #if, I get an error that says 'expected a macro parameter name.'
Is what I am doing possible. How can I fix it?
Upvotes: 2
Views: 348
Reputation: 70472
Since your fancy table header file has to be aware of all the numbers, define a default macro for each number that blanks out the arguments.
#if defined (MY_FANCY_PANTS_TABLE)
// PREAMBLE
#ifndef FANCY_PANTS_DB_ENTRY_123
#define FANCY_PANTS_DB_ENTRY_123(...)
#endif
#ifndef FANCY_PANTS_DB_ENTRY_456
#define FANCY_PANTS_DB_ENTRY_456(...)
#endif
#define FANCY_PANTS_DB(X, Y) \
FANCY_PANTS_DB_ENTRY_##Y(X,)
FANCY_PANTS_DB( A, 123)
FANCY_PANTS_DB( B, 456)
FANCY_PANTS_DB( C, 456)
FANCY_PANTS_DB( D, 123)
// EPILOGUE
#undef FANCY_PANTS_DB_ENTRY_123
#undef FANCY_PANTS_DB_ENTRY_456
#undef FANCY_PANTS_DB
#endif
Then, before you include the file, you define the appropriate entry macro to emit its argument.
uint8 my456Array [] = {
#define FANCY_PANTS_DB_ENTRY_456(...) __VA_ARGS__
#define MY_FANCY_PANTS_TABLE
#include "FancyPantsTable.h"
#undef MY_FANCY_PANTS_TABLE
};
uint8 my123Array [] = {
#define FANCY_PANTS_DB_ENTRY_123(...) __VA_ARGS__
#define MY_FANCY_PANTS_TABLE
#include "FancyPantsTable.h"
#undef MY_FANCY_PANTS_TABLE
};
You can probably hide the PREAMBLE and EPILOGUE portions of the header file into separate header files that are generated from a script.
Upvotes: 0
Reputation: 9173
Remember, a macro cannot define another one. So lines like
#define FANCY_PANTS_DB( aUint8, num ) #if ( num == numberSought sought ) aUint8, #endif
are invalid. Pre-processor only passes once, so you cannot use something like this.
If I'm not mistakes, you can write it like this if you like:
FancyPantsTable.h:
#if MY_FANCY_PANTS_TABLE==123
A,
#endif
#if MY_FANCY_PANTS_TABLE==456
B,
C,
#endif
#if MY_FANCY_PANTS_TABLE==123
D,
#endif
FancyPants.c:
#define MY_FANCY_PANTS_TABLE 456
uint8 my456Array [] = {
#include "FancyPantsTable.h"
};
#undef MY_FANCY_PANTS_TABLE
#define MY_FANCY_PANTS_TABLE 123
uint8 my123Array [] = {
#include "FancyPantsTable.h"
};
#undef MY_FANCY_PANTS_TABLE
Even though I'm not sure if this is what you like.
Upvotes: 2