http://www.perlmonks.org?node_id=1203133

afoken has asked for the wisdom of the Perl Monks concerning the following question:

Hi!

At work, I'm currently using x-macros to allow compile-time configuration of some filtering software. It boils down to a configuration file that roughly looks like this:

CFG_START() CFG_ADD(int, FOO, /* some more stuff */) CFG_ADD(short, BAR, /* some more stuff */) CFG_ADD(float, BAZ, /* some more stuff */) CFG_END()

This file generates some variables, and a meta-data table for the running software so it can know the types (int, short, float) for the variables associated with the identifiers (FOO, BAR, BAZ).

So far, no problems, just a little bit of creative usage of the C preprocessor.

The running software has to invoke qsort. qsort needs a compare function. The meta-data table contains pointers to the compare function matching the type, simply by appending the type name to a common prefix:

/* simplified */ MetaData_t metadata = { #define CFG_ADD(TYPE,NAME,STUFF) { .compFunc = compare_ ## TYPE; / +* and some more stuff */ } #include "configfile.h" #undef CFG_ADD }

My source contains a lot of compare functions for different types that could be used in the configuration file. But not all of the functions are actually used, because not all of the types are used in the configuration file. So, the compiler warns about some unused functions (e.g. compare_double() for the example shown above).

Yes, it is harmless, but ugly. Our code should compile without warnings. Disabling the warning is not an option. I would prefer to be able to hide unused functions from the C compiler.

Something like this (and yes, I know this won't work):

#define CFG_ADD(TYPE,NAME,STUFF) \ #ifndef USING_ ## TYPE /* does not work */ \ #define USING_ ## TYPE /* does not work */ \ #endif #include "configfile.h" #undef CFG_ADD /* and later: */ #ifdef USING_int static int compare_int(const void * a, const void * b); #endif #ifdef USING_double static int compare_double(const void * a, const void * b); #endif /* further down */ #ifdef USING_int static int compare_int(const void * a, const void * b) { /* ... */ } #endif #ifdef USING_double static int compare_double(const void * a, const void * b) { /* ... */ } #endif

Any clever ideas that I missed?

Environment: GCC 4.x cross-compiling for an embedded system (so code and data size might become a problem). GCC might be updated in the future, but switching to a different compiler is very unlikely. So a GCC-only solution is acceptable.

Alexander

--
Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)