This is some poor man's code generation, for when integrating another tool to the project is overkill.
Define a macro like this, expanding for your needs:
#define NESTED /* Comment out instead of backslash new lines.
*/ /*
*/ UNDEF REPLACED /*
*/ /*
*/ IFDEF CONDITION /*
*/ DEFINE REPLACED 1 /*
*/ ELSE /*
*/ DEFINE REPLACED 0 /*
*/ ENDIF
Your version of NESTED
can be a function-like macro, and REPLACED
can have a more elaborated body.
Leave CONDITION
and the directive named macros without a definition.
DEFINE CONDITION
to control which value NESTED
gets on compilation, similarly to normal #ifdef
usage:
DEFINE CONDITION
NESTED
int i = REPLACED; //i == 1
UNDEF CONDITION
NESTED
int z = REPLACED; //z == 0
Source code that uses NESTED
and the other macros will not compile. To generate a .c
or .cpp
file that you can compile with your chosen options, do this:
gcc -E -CC source.c -o temporary.c
gcc -E \
-DDEFINE=\#define -DUNDEF=\#undef \
-DIFDEF=\#ifdef -DELSE=\#else -DENDIF=\#endif \
temporary.c -o usableFile.c
rm temporary.c #remove the temporary file
-E
means preprocess only, not compile. The first gcc
command expands NESTED
and all normally defined macros from the source. As DEFINE
, IFDEF
, etc. are not defined, they and their future arguments remain as literal text in the temporary.c
file.
-CC
makes the comments be preserved in the output file. After the preprocessor replaces NESTED
by its body, temporary.c
contains the directive macros in separate lines, with the comments. When the comments are removed on the next gcc command, the line breaks remain by the standard.
#
is accepted in the body of a macro that takes no arguments. However, unlike macros, directives are not rescaned and executed on expansion, so you need another preprocessor pass to make nested defines work. All preprocessing related to the delayed defines needs to be delayed too, and made available to the preprocessor at once. Otherwise, directives and arguments needed in a later pass are consumed and removed from the code in a previous one.
The second gcc
command replaces the -D
macros by the delayed directives, making all of them available to the preprocessor starting on the next pass. The directives and their arguments are not rescaned in the same gcc command, and remain as literal text in usableFile.c
.
When you compile usableFile.c
, the preprocessor executes the delayed directives.