I have a list of functions generated in a Makefile and dumped into a file that looks something like:
DEF(foo)
DEF(bar)
DEF(baz)
The intent is that this file will be used like so to define a list of functions:
#define DEF(name) void name();
#include "generated_list.inc"
The complication is that I want to have a few exceptions to the generated list.
I want to do something like:
#define DONT_DEF_baz
And this would cause the name baz
to just be ignored from the above.
If the preprocessor could be recursive, this would be something like:
#define DEF(name) \
#ifndef DONT_DEF_ ## name \
void name(); \
#endif \
But of course this is not possible in C.
Is there a way to get the same effect somehow?
something like:
Then use something like:
// if true:
#define DONT_DEF_baz(...)
// if false:
#define DONT_DEF_baz(...) __VA_ARGS__
And use:
#define DEF(name) DONT_DEF_##name(void name();)
If you are up for an adventure and you want to detect undefined, we would have to complicate a bit. See https://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments/ .
#define COMMA() ,
#define EXPAND(...) __VA_ARGS__
#define IGNORE(...)
#define IFNDEF_N2(_2,_1,N,...) N
#define IFNDEF_N(...) IFNDEF_N2(__VA_ARGS__)
#define IFNDEF(name, ...) IFNDEF_N(COMMA name (), IGNORE, EXPAND)(__VA_ARGS__)
#define DEF(name) IFNDEF(DONT_DEF_##name, void name();)
#define DONT_DEF_baz
DEF(baz) // expands to nothing
DEF(foo) // expands to void foo();
how it works?
COMMA name ()
expands to COMMA DONT_DEF_baz ()
.DONT_DEF_baz
is defined to nothing
DONT_DEF_baz
is replaced to nothingCOMMA name ()
becomes COMMA ()
which expands to ,
IFNDEF_N
calls IFNDEF_N2(,, IGNORE, EXPAND)
, with arguments _2=/*nothing*/, _1=/*nothing*/, N=IGNORE, ...=EXPAND
IFNDEF_N2
expands to N
which is IGNORE
DEF(name)
becomes IGNORE(void name();)
which expands to nothing`DONT_DEF_baz
not defined
COMMA name ()
stays as COMMA DONT_DEF_baz ()
.IFNDEF_N
calls IFNDEF_N2(COMMA DONT_DEF_baz (), IGNORE, EXPAND)
, with arguments _2=COMMA DONT_DEF_baz (), _1=IGNORE, N=EXPAND
DEF(name)
becomes EXPAND(void name();)
which expands to the void name();
See the linked article above and Overloading Macro on Number of Arguments .
generated in a Makefile
Maintaining complicated C preprocessor scripts in the long run might be a maintainer burden and might get unreadable. Consider just using simpler templating language, like Jinja2 or m4 or php, for code generation and then compile that code. Also, Makefile is 50 years old with syntax written for an exercise - consider CMake.