C: preprocessor macro to build and use string literals at compile time?

95 Views Asked by At

I have a C function I am using to format strings that has the following signature:

int
string_format
(   char*       dst
,   const char* fmt
,   ...
);

I usually call it like:

char buf[20];
const char* name = "Jeff";
string_format ( buf , "Hello %s!\n" , name );

I am now trying to work with colored text using ANSI color codes. Ideally, I want to use them in my string literals like this:

char buf[20];
const char* name = "Jeff";
string_format ( buf , COLOR_RED "Hello %s!\n" , name );

I wrote some macros to build these string literals, but I have done something wrong. For example, I tried:

#define ANSI_CC(color) "\033["#color"m"
#define ANSI_CC_FG_RED "91"

#define COLOR_RED (ANSI_CC(ANSI_CC_FG_RED))

But when I try to call string_format (buf, COLOR_RED "Hello world.\n""), I get a compiler error:

error: expected ')' before string constant
    |     COLOR_RED "Hello world.\n"
                    ^~~~~~~~~~~~~~~~

My thought was that the preprocessor would evaluate COLOR_RED down to this:

COLOR_RED                 =>
(ANSI_CC(ANSI_CC_FG_RED)) =>
"\033["ANSI_CC_FG_RED"m"  =>
"\033[""91""m"

But obviously it is doing something else instead, which I do not understand; I suspect I used the # stringify operator incorrectly. Could someone please explain what the preprocessor is doing with the macros I wrote? Also, if what I want to accomplish is possible, what do I need to change?

Thanks.

1

There are 1 best solutions below

0
gulpr On BEST ANSWER

Your macro will be expanded to:

string_format ( buf , ("\033[""ANSI_CC_FG_RED""m") "Hello %s!\n" , name );

You need to change the macro to:

#define ANSI_CC(color) "\033[" color "m"
#define ANSI_CC_FG_RED "91"

#define COLOR_RED ANSI_CC(ANSI_CC_FG_RED)

and it will be expanded to:

string_format ( buf , "\033[" "91" "m" "Hello %s!\n" , name );

https://godbolt.org/z/3oGzhhbYx