2

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.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Jimm Chen
  • 3,411
  • 3
  • 35
  • 59
  • possible duplicate of [How to make a char string from a C macro's value?](http://stackoverflow.com/questions/195975/how-to-make-a-char-string-from-a-c-macros-value) – Georg Fritzsche Feb 07 '12 at 14:04

2 Answers2

6

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.

FatalError
  • 52,695
  • 14
  • 99
  • 116
  • Could someone pinpoint which statement in C99 spec clarify this behavior? The key point is **when does ``foo`` becomes ``ball``** and **when does ``#bar`` becomes "bar"** . I checked C99 sections around 6.10.3.2, but find it very difficult to understand. – Jimm Chen Feb 28 '15 at 01:30
3

Did you try passing a quoted string to the -D? You should be able to do that by properly escaping the quotes:

-D'foo="rice"'
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • This works on Linux Bash, but not on Windows CMD. On CMD, if that is argv[1], its value will be `-D'foo=rice'` , strlen(argv[1]) is 12. – Jimm Chen Feb 08 '12 at 00:38