Maister
Maister

Reputation: 5054

Generate #ifdef, #endif clause with another macro

I'm having a problem in a program I'm working on. I'm trying in --help to display which features are compiled in or not. However, there are quite alot of these and the "normal" way is too verbose. E.g.:

#ifdef HAVE_FOO
static const bool have_foo = true;
#else
static const bool have_foo = false;
#endif
printf("Support for foo: %s\n", have_foo ? "yes" : "no");

Now, since I have to do this basically for every feature, it will be loads of lines, which I do not want.

So I thought I'd write some macros for it:

#define _SUPP(X) #ifdef HAVE_##X \
static const bool _##X##_SUPP = true; \
#else \
static const bool _##X##_SUPP = false; \
#endif

#define _PRINTSUPP(var, name, desc) printf("\t%s - %s: %s\n", name, desc, _##var##_SUPP ? "yes" : "no")

However, there is an issue here. The macro will be expanded to a single line, and the preprocessor chokes on this. Is there a way to generate a macro with actual newlines inbetween, or is it possible to evaluate an #ifdef on a single line?

Upvotes: 1

Views: 1363

Answers (3)

Nikolai Fetissov
Nikolai Fetissov

Reputation: 84151

You cannot do this in C. The usual approach is to generate such a header from some textual description in, say, Perl or Python.

Upvotes: 2

Fred Foo
Fred Foo

Reputation: 363487

If, instead of not defining HAVE_FOO, you define it to 0, you can do:

const struct {
    bool present;
    const char *name;
} features[NFEATURES] = {
    {HAVE_FOO, "foo"},
    {HAVE_BAR, "bar"},
    ...
};

for (size_t i=0; i < NFEATURES; i++)
    if (features[i].present)
        printf(" ... and we've got: %s\n", features[i].name);

You'll have to check for #if HAVE_FOO instead of #ifdef HAVE_FOO then, and your --help message may be displayed a bit slower if your number of features runs in the zillions (in which case I'd recommend a different architecture anyway).

Upvotes: 3

John Bode
John Bode

Reputation: 123458

You cannot use a macro to create another preprocessing directive. All preprocessing directives are recognized before macro expansion begins, so your macro will be interpreted as erroneous C code.

Upvotes: 0

Related Questions