views:

726

answers:

10

Hello,

I have a C program with a lot of optimizations that can be enabled or disabled with #defines. When I run my program, I would like to know what macros has been defined at compile time.

So I am trying to write a macro function to print the actual value of a macro. Something like this :

SHOW_DEFINE(X){\
  if( IS_DEFINED(X) )\
      printf("%s is defined and as the value %d\n", #X, (int)X);\
  else\
      printf("%s is not defined\n", #X);\
}

However I don't know how to make it work and I suspect it is not possible, does anyone has an idea of how to do it ?

(Note that is must compile even when the macro is not defined !)

Thanks,

+1  A: 
#ifdef MYMACRO
  printf("MYMACRO defined: %d\r\n", MYMACRO);
#endif

I don't think what you are trying to do is possible. You are asking for info at runtime which has been processed before compilation. The string "MYMACRO" means nothing after CPP has expanded it to its value inside your program.

kjfletch
well, this is what I would like to avoid, since I have many of them with #ifdef #else #endif.
Ben
+3  A: 

Writing a MACRO that expands to another MACRO would require the preprocessor to run twice on it.
That is not done.

You could write a simple file,

// File check-defines.c
int printCompileTimeDefines()
{
#ifdef DEF1
  printf ("defined : DEF1\n");
#else // DEF1
  printf ("undefined: DEF1\n");
#endif // DEF1
// and so on...
}

Use the same Compile Time define lines on this file as with the other files.
Call the function sometime at the start.

If you have the #DEFINE lines inside a source file rather than the Makefile,
Move them to another Header file and include that header across all source files,
including this check-defines.c.

Hopefully, you have the same set of defines allowed across all your source files.
Otherwise, it would be prudent to recheck the strategy of your defines.


To automate generation of this function,
you could use the M4 macro language (or even an AWK script actually).
M4 becomes your pre-pre-processor.

nik
Accepted for the m4 answer. This become easy when you add another preprocessing step. I did SHOW_DEFINE(X,Y,Z ... ) which is even better. However it makes sens because I need m4 for other stuffs.
Ben
+1  A: 

You did not specify the compiler you were using. If this is gcc, gcc -E may help you, as it stops after the preprocessing stage, and prints the preprocessing result. If you diff a gcc -E result with the original file, you may get part of what you want.

Yuval F
+1  A: 

Why not simply testing it with the preprocessor ?

 #if defined(X)
      printf("%s is defined and as the value %d\n", #X, (int)X);
 #else
      printf("%s is not defined\n", #X);
 #endif

One can also embed this in another test not to print it everytime:

 #if define(SHOW_DEFINE)
 #if defined(X)
      printf("%s is defined and as the value %d\n", #X, (int)X);
 #else
      printf("%s is not defined\n", #X);
 #endif
 #endif
philippe
@philippe, Well, that's what I and kjfletch seem to have suggested. But he wants to avoid writing all that down, which is why I suggest M4 or AWK scripting.
nik
This is what I do now, the list is never up to date and it needs a special file just for this purpose :(
Ben
+1  A: 

Wave library from boost can be helpful also to do what you want. If your project is big enough, I think it is worth trying. It is a C++ preprocessor, but they are the same any way :)

AraK
+1  A: 

I believe what you are trying to do is not possible. If you are able to change the way your #defines work, then I suggest something like this:

#define ON 1
#define OFF 2

#define OPTIMIZE_FOO ON
#define OPTIMIZE_BAR OFF

#define SHOW_DEFINE(val)\
    if(val == ON) printf(#val" is ON\n");\
    else printf(#val" is OFF\n");
Clay
+1  A: 

It is not possible indeed, the problem being the "not defined" part. If you'd relied on the macro values to activate/deactivate parts of your code, then you could simply do:

#define SHOW_DEFINE(X) \
do { \
if (X > 0) \
 printf("%s %d\n", #X, (int)X);   \
else \
 printf("%s not defined\n", #X);   \
} while(0)
Frederik Deweerdt
+4  A: 

As long as you are willing to put up with the fact that SOMESTRING=SOMESTRING indicates that SOMESTRING has not been defined (view it as the token has not been redefined!?!), then the following should do:

#include <stdio.h>

#define STR(x)   #x
#define SHOW_DEFINE(x) printf("%s=%s\n", #x, STR(x))

#define CHARLIE -6
#define FRED 1
#define HARRY FRED
#define NORBERT ON_HOLIDAY
#define WALLY

int main()
{
    SHOW_DEFINE(BERT);
    SHOW_DEFINE(CHARLIE);
    SHOW_DEFINE(FRED);
    SHOW_DEFINE(HARRY);
    SHOW_DEFINE(NORBERT);
    SHOW_DEFINE(WALLY);

return 0;
}

The output is:

BERT=BERT
CHARLIE=-6
FRED=1
HARRY=1
NORBERT=ON_HOLIDAY
WALLY=
Dipstick
Nice !
Ben
And I just found a way to bypass the 15 chars comment limitation..
Ben
A: 

Based on Chrisharris, answer I did this. Though my answer is not very nice it is quite what I wanted.

#define STR(x)   #x
#define SHOW_DEFINE(x) printf("%s %s\n", #x, strcmp(STR(x),#x)!=0?"is defined":"is NOT    defined")

Only bug I found is the define must not be #define XXX XXX (with XXX equals to XXX).

Ben
A: 

This question is very close from Macro which prints an expression and evaluates it (with __STRING). Chrisharris' answer is very close from the answer to the previous question.

bortzmeyer