Ultimately, what I want is this: first, have a list of variable names declared as a C preprocessor macro; say, in test_cpp.c:
#define VARLIST \
var_one, \
var_two, \
var_three, \
var_four
These would eventually be actual variable names in code - but, of course, the preprocessor does not know (or even has a concept of) that at this time.
To make sure the macro has been parsed correctly, I use this command (awk to get rid of the preamble defines in the gcc -E preprocessor output):
$ gcc -E -dD test_cpp.c | awk 'BEGIN{prn=0} /# 1 "test_cpp.c"/ {prn=1} prn==1 {print}'
# 1 "test_cpp.c"
#define VARLIST var_one, var_two, var_three, var_four
So far, so good.
Now: second, I'd like to use this list - that is, I'd like to (pre)process it - and prepend and append characters to each element (token) of the VARLIST, so that I end up with the equivalent of the following macros:
#define VARLIST_QUOTED "var_one", "var_two", "var_three", "var_four"
#define VARLIST_PTR &var_one, &var_two, &var_three, &var_four
... which I could ultimately use in code as, say:
char varnames[][16] = { VARLIST_QUOTED };
( ... which then would end up like this in compiled code, inspected in debugger:
(gdb) p varnames
$1 = {"var_one\000\000\000\000\000\000\000\000",
"var_two\000\000\000\000\000\000\000\000",
"var_three\000\000\000\000\000\000",
"var_four\000\000\000\000\000\000\000"}
)
I'm guessing, at this time the preprocessor wouldn't know & is intended to be an "address-of" operator, although I think it has special handling for double quotes.
In any case, I think that such "lists" in the preprocessor are handled via Variadic Macros (The C Preprocessor), where there is an identifier __VA_ARGS__. Unfortunately, I do not understand this very well: I tried the first thing that came to mind - again, test_cpp.c:
#define VARLIST \
var_one, \
var_two, \
var_three, \
var_four
#define do_prepend(...) &##__VA_ARGS__
#define VARLIST_PTR do_prepend(VARLIST)
void* vars_ptr[] = { VARLIST_PTR };
Then if I run the preprocessor, I get this:
$ gcc -E -dD test_cpp.c | awk 'BEGIN{prn=0} /# 1 "test_cpp.c"/ {prn=1} prn==1 {print}' | sed '/^$/d;G'
test_cpp.c:8:25: error: pasting "&" and "VARLIST" does not give a valid preprocessing token
8 | #define do_prepend(...) &##__VA_ARGS__
| ^
test_cpp.c:9:21: note: in expansion of macro 'do_prepend'
9 | #define VARLIST_PTR do_prepend(VARLIST)
| ^~~~~~~~~~
test_cpp.c:11:22: note: in expansion of macro 'VARLIST_PTR'
11 | void* vars_ptr[] = { VARLIST_PTR };
| ^~~~~~~~~~~
# 1 "test_cpp.c"
#define VARLIST var_one, var_two, var_three, var_four
#define do_prepend(...) & ##__VA_ARGS__
#define VARLIST_PTR do_prepend(VARLIST)
void* vars_ptr[] = { &var_one, var_two, var_three, var_four };
It does show an error - but ultimately, the preprocessor did prepend a single ampersand & to the first variable in the array vars_ptr, as I wanted it to ...
The question is, then: can it prepend an ampersand & to all the entries in the list VARLIST without errors (and likewise, can it both prepend and append a double quote " to all the entries in the list VARLIST without errors) - and if so, how?
Sounds like a job for X macros:
#include <stdio.h>
#define VARS \
X(var_one) \
X(var_two) \
X(var_three) \
X(var_four)
// Define all the variables as ints (just for the example)
#define X(V) int V=0;
VARS
#undef X
// Define the array of variable pointers
#define X(V) &V,
void* vars_ptr[] = { VARS };
#undef X
// Define the array of variable name strings
#define X(V) #V,
const char *var_names[] = { VARS };
#undef X
// Set a few variable values and print out the name/value of all variables
int main()
{
var_one = 9;
var_two = 2;
for(unsigned i = 0; i < sizeof(var_names)/sizeof(var_names[0]); i++)
{
printf("%s=%d\n", var_names[i], *(int *)vars_ptr[i]);
}
return 0;
}
Ok, seems I found an answer, mostly thanks to Is it possible to iterate over arguments in variadic macros? (see also Expand a macro in a macro); this is test_cpp.c:
#define VARLIST \
var_one, \
var_two, \
var_three, \
var_four
// Make a FOREACH macro
#define FE_0(WHAT)
#define FE_1(WHAT, X) WHAT(X)
#define FE_2(WHAT, X, ...) WHAT(X)FE_1(WHAT, __VA_ARGS__)
#define FE_3(WHAT, X, ...) WHAT(X)FE_2(WHAT, __VA_ARGS__)
#define FE_4(WHAT, X, ...) WHAT(X)FE_3(WHAT, __VA_ARGS__)
#define FE_5(WHAT, X, ...) WHAT(X)FE_4(WHAT, __VA_ARGS__)
//... repeat as needed
#define GET_MACRO(_0,_1,_2,_3,_4,_5,NAME,...) NAME
#define FOR_EACH(action,...) \
GET_MACRO(_0,__VA_ARGS__,FE_5,FE_4,FE_3,FE_2,FE_1,FE_0)(action,__VA_ARGS__)
#define XSTR(x) STR(x)
#define STR(x) #x
// original: https://stackoverflow.com/a/11994395
//#define QUALIFIER(X) X::
//#define QUALIFIED(NAME,...) FOR_EACH(QUALIFIER,__VA_ARGS__)NAME
#define POINTERER(X) &X,
#define POINTERIFIED(NAME,...) FOR_EACH(POINTERER,__VA_ARGS__)NAME
// leave first argument (from original QUALIFIED) empty here!
#define vptrs POINTERIFIED(,VARLIST)
void* vars_ptr[] = { vptrs };
//#define DQUOTE " // no need for DQUOTE;
// if we just use the number/hash sign, X gets automatically quoted with double quotes!
// (don't forget the comma at the end!)
#define DQUOTERER(X) #X,
#define DQUOTERIFIED(NAME,...) FOR_EACH(DQUOTERER,__VA_ARGS__)NAME
// leave first argument (from original QUALIFIED) empty here!
#define vnames DQUOTERIFIED(,VARLIST)
char vars_names[][16] = { vnames };
... and this is the output of the preprocessor:
$ gcc -E -dD test_cpp.c | awk 'BEGIN{prn=0} /# 1 "test_cpp.c"/ {prn=1} prn==1 {print}' | sed '/^$/d;G'
# 1 "test_cpp.c"
#define VARLIST var_one, var_two, var_three, var_four
#define FE_0(WHAT)
#define FE_1(WHAT,X) WHAT(X)
#define FE_2(WHAT,X,...) WHAT(X)FE_1(WHAT, __VA_ARGS__)
#define FE_3(WHAT,X,...) WHAT(X)FE_2(WHAT, __VA_ARGS__)
#define FE_4(WHAT,X,...) WHAT(X)FE_3(WHAT, __VA_ARGS__)
#define FE_5(WHAT,X,...) WHAT(X)FE_4(WHAT, __VA_ARGS__)
#define GET_MACRO(_0,_1,_2,_3,_4,_5,NAME,...) NAME
#define FOR_EACH(action,...) GET_MACRO(_0,__VA_ARGS__,FE_5,FE_4,FE_3,FE_2,FE_1,FE_0)(action,__VA_ARGS__)
#define XSTR(x) STR(x)
#define STR(x) #x
#define POINTERER(X) &X,
#define POINTERIFIED(NAME,...) FOR_EACH(POINTERER,__VA_ARGS__)NAME
#define vptrs POINTERIFIED(,VARLIST)
void* vars_ptr[] = { &var_one,&var_two,&var_three,&var_four, };
#define DQUOTERER(X) #X,
#define DQUOTERIFIED(NAME,...) FOR_EACH(DQUOTERER,__VA_ARGS__)NAME
#define vnames DQUOTERIFIED(,VARLIST)
char vars_names[][16] = { "var_one","var_two","var_three","var_four", };
So, ultimately, I got my output as desired - and no preprocessor errors/warnings, as far as I can tell:
void* vars_ptr[] = { &var_one,&var_two,&var_three,&var_four, };
char vars_names[][16] = { "var_one","var_two","var_three","var_four", };
As already mentioned, you are more or less literally describing the purpose of "X macros".
An alternative, arguably somewhat more readable way of writing them is to first declare a macro list, then pass a macro to that list. As in
"here is a function-like macro, run it with all the arguments listed", rather than
"here is the function-like macro X, run macro X with all the arguments listed".
This allows you to give macros meaningful names, optionally group all macros belonging to the list somewhere, and it eliminates the need to #undef.
#include <stdio.h>
// note the absence of commas
#define VARLIST(X) \
X(var_one) \
X(var_two) \
X(var_three) \
X(var_four) \
int main (void)
{
char varnames[][16] =
{
#define VARLIST_QUOTED(name) #name, /* "stringification operator" */
VARLIST(VARLIST_QUOTED) /* no semicolon or comma here */
};
#define VARLIST_DECL_VARS(name) int name; /* declare a bunch of int */
VARLIST(VARLIST_DECL_VARS)
int* const pointers[] =
{
#define VARLIST_PTR(name) &name, /* declare an array of pointers to previous ints */
VARLIST(VARLIST_PTR)
};
var_two = 123;
printf("%s has value %d and address %p\n",
varnames[1],
var_two,
pointers[1]);
}
During the developing of static library I met the necessity to test the library functions.
The functions checks are not the problem. The main problem is to test every macro definition that the library provides.
I've started with the code like
/* For non-vital macro (OS/WORDSIZE detections) */
# if defined(BXI_ARCH_X32)
printf(" defined : BXI_ARCH_X32\n");
# endif
# if defined(BXI_ARCH_X64)
printf(" defined : BXI_ARCH_X64\n");
# endif
<...>
/* For vital macro */
#if defined(BXI_OS)
printf(" defined : BXI_OS : \"%s\"\n", BXI_OS);
#else
print_failed();
#endif
#if defined(BXI_BITS)
printf(" defined : BXI_BITS: %d\n", BXI_BITS);
#else
print_failed();
#endif
#if defined(BXI_ARCH)
printf(" defined : BXI_ARCH: \"%s\"\n", BXI_ARCH);
#else
print_failed();
#endif
That was cool, but very time-consuming. I wanted a tool that will generate the code for me, or some trick that will allow me to autogenerate the tests via macro like this
TEST_MACRO(BXI_OS)
But, as you know, macro definitions can't generate #if/#else/#endif directives.
I needed a solution that will not only check if the macro defined at runtime, but also print its value to output.
I've met a simillar problem and found another nice trick to implement your TEST_BXI_MACRO_EXISTS with no string.h and extra function calls:
#define STRINGIZE_I(x) #x
#define TEST_BXI_MACRO_EXISTS(name) (#name [0] != STRINGIZE_I(name) [0])
This trick uses the same assumption that stringized value of defined macro does not match stringized name of that macro. But for my case I only needed to check if macro is defined as a numeric constant, string literal or empty value. No function-like macros and other stuff.
This is how it works:
#define MACRO "Content"
TEST_BXI_MACRO_EXISTS(MACRO)
// translates to ("MACRO"[0] != "\"Content\""[0])
// first letter of a valid macro name can never be equal to '"'
#define MACRO 3.14
TEST_BXI_MACRO_EXISTS(MACRO)
// translates to ("MACRO"[0] != "3.14"[0])
// first letter of a valid macro name can never be equal to a digit
#define MACRO
TEST_BXI_MACRO_EXISTS(MACRO)
// translates to ("MACRO"[0] != ""[0])
// first letter of a valid macro name can never be equal to a '\0'
This approach can also be easily used to test whether macro defines a numeric constant, string literal or empty value like your approach does by checking the value of STRINGIZE_I(name) [0].
So far I have no idea how to test function-like macros this way, but I thought sharing this with others could be useful anyway.
But, as this is Q&A-style article, I've found the solution.
The final result looks as follows:
TEST_BXI_MACRO_STRING(BXI_OS);
TEST_BXI_MACRO_STRING(BXI_ARCH);
TEST_BXI_MACRO_I32 (BXI_BITS);
TEST_BXI_MACRO_EXISTS_WEAK(BXI_ARCH_X32); // _WEAK as we don't need to fail
TEST_BXI_MACRO_EXISTS_WEAK(BXI_ARCH_X64);
The result:
Let us see every one of them closely
TEST_BXI_MACRO_STRING
This one is pretty simple:
#define TEST_BXI_MACRO_STRING(name) \
do \
{ \
print_macro_name(#name); \
if (!TEST_BXI_MACRO_DEFINED(#name, name(1))) \
print_macro_undefined_exit(); \
if (strlen(name "") == 0) \
print_macro_undefined_exit(); \
print_macro_value_string(name ""); \
} \
while (0)
We just using the idea that C allows const strings auto-concatenation. So when the macro exists we will receive
#define MACRO "Content"
"Content" "" = "Content"
and when it doesn't
"" = ""
Then we look at the length of the resulting string, and when it's 0 - bingo, macro is not defined. This will NOT work for "" macro, but this special case could be checked with TEST_BXI_MACRO_EXISTS
TEST_BXI_MACRO_I32
#define TEST_BXI_MACRO_I32(name) \
do \
{ \
print_macro_name(#name); \
if (!TEST_BXI_MACRO_DEFINED(#name, name(1))) \
print_macro_undefined_exit(); \
if ((5 * name + 1) == 5) \
print_macro_undefined_exit(); \
print_macro_value_signed(name + 0); \
} \
while (0)
NOTE: you can similarly create ...MACRO_U32 version just by replacing the printer formatter.
Here we use the fact that '+' operator could be unary AND binary.
Let us simulate three cases:
#define MACRO (10)
In this case the complete formula will look as follows:
5 * 10 + 1 => 50 + 1 => 51
#define MACRO (0)
In this case the multiplication fades out:
5 * 0 + 1 => 0 + 1 => 1
In some cases you can use this for additional check if the defined macro is 0 (like for preprocessing options and stuff)
#define MACRO
This case shows some math magic:
5 * + 1 => 5 * (+1) => 5 * 1 => 5
As +1 is interpreted as simple 1 we receive 5.
TEST_BXI_MACRO_EXISTS
#define TEST_BXI_MACRO_DEFINED_I(strstr, fnc) (strcmp(#fnc, strstr "(1)"))
#define TEST_BXI_MACRO_DEFINED(str, fnc) TEST_BXI_MACRO_DEFINED_I(str, fnc)
#define TEST_BXI_MACRO_EXISTS(name) \
do \
{ \
print_macro_name(#name); \
if (!TEST_BXI_MACRO_DEFINED(#name, name(1))) \
print_macro_undefined_exit(); \
else \
print_macro_defined(); \
} \
while (0)
This implementation uses the fact that the string value of macro should not expand same as its name (as #define A A is useles)
Additional functions
For those who want the printing functions, here they are:
void print_macro_name(const char * name)
{
printf(" checking: %-20s: ", name);
}
void print_macro_undefined_exit(void)
{
printf("\033[1;31mUNDEFINED\033[0m\n");
exit(1);
}
void print_macro_defined(void)
{
printf("\033[1;33mDEFINED\033[0m\n");
}
void print_macro_undefined(void)
{
printf("\033[1;32mUNDEFINED\033[0m\n");
}
void print_macro_value_string(const char * value)
{
printf("\"%s\"\n", value);
}
void print_macro_value_signed(i32 value)
{
printf("%d\n", value);
}
void print_macro_value_unsigned(u32 value)
{
printf("%u\n", value);
}
#define SET_NONEMPTY(x) { const NString& var = r->hdrs->get_##x(); \
if (!var.empty()) { \
set_##x_for_serving(r->request, var.data(), var.length()); \
} \
}
The above macro tries to set a request member if it is not empty, but I get this following
error: 'set_x_for_serving' was not declared in this scope while I use this macro.
What is wrong in the above macro?
You need the token-pasting operator on both sides of x in order to get it to substitute correctly.
#define SET_NONEMPTY(x) { const NString& var = r->hdrs->get_##x(); \
if (!var.empty()) { \
set_##x##_for_serving(r->request, var.data(), var.length()); \
} \
}
It looks like inside a macro call of SET_NONEMPTY(foobar), you expect that set_##x_for_serving will expand to set_foobar_for_serving.
Is that correct?
If so, the phrase x_for_serving is a single token and the x will not be seen by the preprocessor as an item to replace.
I think you want set_##x##_for_serving instead:
#define SET_NONEMPTY(x) { const NString& var = r->hdrs->get_##x(); \
if (!var.empty()) { \
set_##x##_for_serving(r->request, var.data(), var.length()); \
} \
}
A while ago, I wrote a set of X-macros for a largish project. I needed to maintain coherent lists of both strings and enumerated references/hash values/callback functions etc. Here is what the function callback looks like
#define LREF_LOOKUP_TABLE_TEXT_SIZE 32
#define _LREF_ENUM_LIST(_prefix,_ref,...) _prefix ## _ ## _ref,
#define _LREF_BASE_STRUCT_ENTRY(_prefix,_ref) .text= #_ref "\0", .position= _LREF_ENUM_LIST(_prefix, _ref)
#define _LREF_FUNCTION_STRUCT_LIST(_prefix,_ref,...) {_LREF_BASE_STRUCT_ENTRY(_prefix,_ref) _prefix ## _ ## _ref ## _callback},
#define _LREF_ENUM_TYPEDEF(_prefix) \
typedef enum _prefix \
{ \
_ ## _prefix ## s(_prefix,_LREF_ENUM_LIST) \
_LREF_ENUM_LIST(_prefix,tblEnd) \
} e_ ## _prefix
#define _LREF_LOOKUP_TABLE_TYPEDEF(_prefix, _extras) \
typedef struct _prefix ## _lookup \
{ \
const char text[LREF_LOOKUP_TABLE_TEXT_SIZE]; \
e_ ## _prefix position; \
_extras \
} _prefix ##_lookup_t
#define LREF_GENERIC_LOOKUP_TABLE(_prefix, _type, _tabledef, _listdef, _extras) \
_LREF_ENUM_TYPEDEF(_prefix); \
_LREF_LOOKUP_TABLE_TYPEDEF(_prefix,_tabledef); \
_extras \
_LREF_LOOKUP_TABLE_DECLARATION(_prefix,_listdef, _type)
#define LREF_FUNCTION_LOOKUP_TABLE(_prefix, _type) \
_ ## _prefix ## s(_prefix, _LREF_FUNCTION_DEF ) \
LREF_GENERIC_LOOKUP_TABLE( _prefix, \
_type, \
void* (*function) (void*);, \
_LREF_FUNCTION_STRUCT_LIST, )
This sits in a header file and allows me to write things like:
#define _cl_tags(x,_) \
_(x, command_list) \
_(x, command) \
_(x, parameter) \
_(x, fixed_parameter) \
_(x, parameter_group) \
_(x, group) \
_(x, map) \
_(x, transform)
LREF_FUNCTION_LOOKUP_TABLE(cl_tag, static);
This keeps processing routines short. For example, loading a configuration file with the above tags is simply:
for (node_tag = cl_tag_lookup_table; node_tag->position != cl_tag_tblEnd; node_tag++)
{
if (strcasecmp(test_string, node_tag->text) == 0)
{
func_return = node_tag->function((void*)m_parser);
}
}
My question is this: I hate that I have to include the second parameter in my #define. I want to be able to write #define _cl_tags(_) instead of #define _cl_tags(x,_). As you can see, the x is only used to pass the prefix (cl_tag) down. But this is superfluous as the prefix is a parameter to the initial macro.
The solution to this would be easy if my preprocessor would expand the outer-most macros first. Unfortunately, GCC's preprocessor works through the inner-most macros, i.e. parameter values, before expanding the outermost macro.
I am using gcc 4.4.5
Clarification
By C89 (and C99) standard, the following definitions
#define plus(x,y) add(y,x)
#define add(x,y) ((x)+(y))
with the invocation
plus(plus(a,b),c)
should yield
plus(plus(a,b),c)
add(c,plus(a,b))
((c)+(plus(a,b))
((c)+(add(b,a))
((c)+(((b)+(a))))
gcc 4.4.5 gives
plus(plus(a,b),c)
plus(add(b,a),c)
plus(((b)+(a)),c)
add(c,((b)+(a)))
((c)+(((b)+(a))))
Here's what I would do (have done similarly):
Put these in a utility header file:
/*
* Concatenate preprocessor tokens A and B without expanding macro definitions
* (however, if invoked from a macro, macro arguments are expanded).
*/
#define PPCAT_NX(A, B) A ## B
/*
* Concatenate preprocessor tokens A and B after macro-expanding them.
*/
#define PPCAT(A, B) PPCAT_NX(A, B)
Then define this before including your LREF macro header file:
#define LREF_TAG cl_tag
Then, in your LREF macro header file,
#define LREF_PFX(x) PPCAT(LREF_TAG, x)
#define LREF_SFX(x) PPCAT(x, LREF_TAG)
Then replace every instance of _prefix ## foo with LREF_PFX(foo) and foo ## _prefix with LREF_SFX(foo).
(When pasting more than two tokens together, just use nested PPCAT's.)
Your invocation would become
#define LREF_TAG cl_tag
#define _cl_tags(_) \
_(command_list) \
_(command) \
_(parameter) \
_(fixed_parameter) \
_(parameter_group) \
_(group) \
_(map) \
_(transform)
LREF_FUNCTION_LOOKUP_TABLE(static);
This answer just addresses the 'clarification'. Here is the correct behaviour:
#define plus(x,y) add(y,x)
#define add(x,y) ((x)+(y))
Initial: plus(plus(a,b),c)
Pass 1a: plus(add(b,a),c)
Pass 1b: add(c,add(b,a))
Pass 2a: add(c,((b)+(a)))
Pass 2b: ((c)+(((b)+(a))))
The rules are that each macro is replaced once non-recursively (starting from the inner-most when they are nested); and then a new pass (aka. "rescan") happens repeating the same procedure, this continues until a pass performs no replacement.
I'm not sure what point you were trying to make though, as you give the same final conclusion for both GCC and what you expected to happen.