0

i would like to pass a string via a preprocessor macro to my source code.

The desired output is something like this:

$ cc -DFOO="hello world" test.c test
$ ./test
foo says: hello world
$ cc -DFOO="GNU/linux" test.c test
$ ./test
foo says: GNU/linux

my code looks like this:

#include <stdio.h>

#define STR(s) #s
#define STRINGIFY(s) STR(s)

int main() {
  const char*foo = STRINGIFY(FOO);
  printf("foo says: %s\n", foo);
  return 0;
}

This works nicely for many strings:

$ cc -DFOO="hello world" test.c test
$ ./test
foo says: hello world

Unfortunately, the strings i need to pass contain words that are already defined by my compiler, notably "linux" (on my Linux system, obviously). in this case, the double macro expansion for the stringification will first expand any tokens that are defined as a macro:

$ cc -DFOO="GNU/linux" test.c test
$ ./test
foo says: GNU/1

the expansion works recursively as well:

$ cc -DX="linux" -DFOO="GNU/X" test.c test
$ ./test
foo says: GNU/1

not surprisingly, it only expands full words

$ cc -DFOO="linuxers use linux" test.c test
$ ./test
foo says: linuxers use 1

So: how can i stringify a macro that contains words that are defined otherwhere, without expanding these words?

note: my build-system is automake (so I try to avoid doing too much quoting).

note2: the actual strings i'm trying to pass are filename components. so why they won't contain any whitespace or slashes, I cannot really mangle them on the C-side (e.g. passing -DFOO=LINUX and then lowercasing the term won't work; also, I cannot be sure that nobody will put a #define LINUX 42 somewhere)

umläute
  • 28,885
  • 9
  • 68
  • 122
  • Does https://stackoverflow.com/questions/14735631/is-partial-macro-application-currying-possible-in-the-c-preprocessor answer your question? – KamilCuk Jun 14 '23 at 10:53

1 Answers1

0

how can i stringify a macro that contains words that are defined otherwhere, without expanding these words?

You can't. Use a different preprocessor.

the actual strings i'm trying to pass are filename components

Pass them as strings in the first place.

cc -DFOO="\"a string\""

note: my build-system is automake

I know close to nothing about automake, you can use xxd -i to convert any string to 0xAB, 0xCD C source code.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111