Search code examples
cc-preprocessorstringification

How to make a -D value from cmd line become a string?


I'm facing a tricky problem. I'd like to forge a C source file content according to compiler command line. For example(using VC):

If I use command line

cl -c -E -Dfoo=rice test.c

I wish to get actual C content (after preprocessing):

char *s = "rice";

If I use command line

cl -c -E -Dfoo=ball test.c

I wish to get actual C source file content:

char *s = "ball";

Now finding a solution...

FIRST TRY:

// test.c
#define STRNAME(n) #n
char *s = STRNAME(foo);

-- No luck. No matter what foo is defined to be on command line, I always get

char *s = "foo"; // Oh no!

SECOND TRY (closest I can image, but still verbose):

// test.c
#define STRNAME(n) #n
char *s = foo;

This time, I have to change my command line verbosely:

cl -c -E -Dfoo=STRNAME(rice) test.c

Now I get

 char *s = "rice";

Is there a way to help me out of this verbosity?

BY the way: I really do not like to introduce quotes into command arguments (make them become part of argv[x], because you will not be able to write such command line reliably and portably on Windows CMD and Linux Bash -- I think.


Solution

  • You need an extra level of indirection in the preprocessor to expand your macro first. Something like:

    #define STRNAME1(n) #n
    #define STRNAME(n) STRNAME1(n)
    char *s = STRNAME(foo);
    

    This is a fairly common pattern, and results in your macro being expanded and then converted to a string, rather than just converted to a string.