C preprocessor replace multiple arguments - c-preprocessor

I want FUNC(x1, x2, x3, etc..) to be replaced with
FUNC2(x1);
FUNC2(x2);
FUNC2(x3);
etc..
I tried but failed with varargs. Both FUNC and FUNC2 must be macros.

It's doable but non-trivial.
I'm using a BX_foreach(Joiner,Function,...) macro for this implemented as follows
(generated for about 8 arguments -- you should be able to figure out how to generated it for more):
#define BX_foreach(Join,What, ...) BX_foreach_(BX_argc(__VA_ARGS__), Join, What, __VA_ARGS__)
#define BX_foreach_(N, Join, What, ...) BX_paste(BX_cat(BX_foreach_, N)(Join, What, __VA_ARGS__))
#define BX_cat(X,Y) BX_cat_(X,Y) //{{{
#define BX_cat_(X,Y) X##Y //}}}
#define BX_call_first(Fn,...) Fn ( __VA_ARGS__ )
#define BX_paste(...) __VA_ARGS__
#define BX_argc(...) BX_argc_(X,__VA_ARGS__) //{{{
#define BX_argc_(...) BX_argc__(,__VA_ARGS__,8,7,6,5,4,3,2,1,0,0)
#define BX_argc__(_,_0,_1,_2,_3,_4,_5,_6,_7,_8,Cnt,...) Cnt //}}}
#define BX_foreach_1(Join, What, x) BX_call_first(What, x)
#define BX_foreach_2(Join, What, x,...)BX_call_first(What,x) Join BX_foreach_1(Join, What, __VA_ARGS__)
#define BX_foreach_3(Join, What, x,...)BX_call_first(What,x) Join BX_foreach_2(Join, What, __VA_ARGS__)
#define BX_foreach_4(Join, What, x,...)BX_call_first(What,x) Join BX_foreach_3(Join, What, __VA_ARGS__)
#define BX_foreach_5(Join, What, x,...)BX_call_first(What,x) Join BX_foreach_4(Join, What, __VA_ARGS__)
#define BX_foreach_6(Join, What, x,...)BX_call_first(What,x) Join BX_foreach_5(Join, What, __VA_ARGS__)
#define BX_foreach_7(Join, What, x,...)BX_call_first(What,x) Join BX_foreach_6(Join, What, __VA_ARGS__)
With it, you can do:
#define FUNC(X) foo(X)
BX_foreach(;,FUNC,x1,x2,x3)
and have it expand to
foo(x1) ; foo(x2) ; foo(x3)

Related

How does the C preprocessor go from a macro to a struct definition

As I was searching for a way to do reflection in C, I found this answer https://stackoverflow.com/a/31908340/6784916.
In his answer, he refers to the metaresc library and he shows an example how to use it:
TYPEDEF_STRUCT (point_t,
double x,
double y
);
int main (int argc, char * argv[])
{
point_t point = {
.x = M_PI,
.y = M_E,
};
...
}
TYPEDEF_STRUCT is defined on line 237 of https://github.com/alexanderchuranov/Metaresc/blob/master/src/metaresc.h
I tried extracting the source of the macro but I'm not sure if I missed something because it's so complex.
#define TYPEDEF_STRUCT(...) P00_TYPEDEF (STRUCT, __VA_ARGS__)
#ifndef MR_MODE
#define MR_MODE_UNDEFINED
#define MR_MODE PROTO
#endif
#include <mr_protos.h>
#ifdef MR_MODE_UNDEFINED
#undef MR_MODE_UNDEFINED
#undef MR_MODE
#endif
#define MR_IS_MR_MODE_EQ_MR_MODE 0
#define P00_TYPEDEF(...) \
MR_IF_ELSE (MR_PASTE2 (MR_IS_MR_MODE_EQ_, MR_MODE)) \
(P00_TYPEDEF_MODE (MR_MODE, __VA_ARGS__)) \
(P00_TYPEDEF_MODE (PROTO, __VA_ARGS__) P00_TYPEDEF_MODE (DESC, __VA_ARGS__))
#define MR_IGNORE(...)
#define MR_IDENT(...) __VA_ARGS__
#define MR_IF_ELSE_CASE_0(...) __VA_ARGS__ MR_IGNORE
#define MR_IF_ELSE_CASE_1(...) MR_IDENT
#define MR_IF_ELSE(...) MR_PASTE2 (MR_IF_ELSE_CASE_, MR_IS_EQ_0 (__VA_ARGS__))
#define MR_PASTE2(...) MR_PASTE2_ (__VA_ARGS__)
#define MR_PASTE2_(_0, _1) _0 ## _1
#define MR_IS_0_EQ_0 ,
#define MR_IS_EQ_0_CASE_011 ,
#define MR_GET_SECOND(_0, ...) __VA_ARGS__
#define MR_IS_EQ_0(...) MR_IS_EQ_0_ (__VA_ARGS__) /* evaluate arguments */
#define MR_IS_EQ_0_(...) MR_IS_EQ_0__ ((__VA_ARGS__), (MR_PASTE2 (MR_IS_0_EQ_, __VA_ARGS__)))
#define MR_IS_EQ_0__(ARGS, ARGS_EQ_0) \
MR_HAS_COMMA (MR_PASTE4 (MR_IS_EQ_0_CASE_, \
/* test if there is just one argument, eventually a zero */ \
MR_HAS_COMMA ARGS, \
/* test if MR_IS_0_EQ_ together with the argument adds a comma */ \
MR_HAS_COMMA ARGS_EQ_0, \
/* test that there is nothing after comma */ \
MR_IS_EMPTY (MR_GET_SECOND ARGS_EQ_0)))
#define P00_TYPEDEF_MODE(P00_MODE, P00_TYPE, ...) \
P00_TYPEDEF_MODE_ (P00_MODE, P00_TYPE, \
ATTRIBUTES (P00_GET_ATTRIBUTES (__VA_ARGS__)), \
P00_GET_NON_ATTRIBUTES (__VA_ARGS__))
#define P00_TYPEDEF_MODE_(...) P00_TYPEDEF_MODE__ (__VA_ARGS__)
#define P00_TYPEDEF_MODE__(P00_MODE, P00_TYPE, ATTR_META_RES, ...) \
#define P00_GET_ATTRIBUTES(...) MR_FOREACH (P00_EXTRACT_ATTRIBUTES, __VA_ARGS__)
#define P00_GET_NON_ATTRIBUTES(...) MR_FOREACH (P00_EXTRACT_NON_ATTRIBUTES, __VA_ARGS__)
#define MR_FOREACH(X, ...) MR_PASTE2 (MR_FOREACH, MR_NARG (__VA_ARGS__)) (X, __VA_ARGS__)
#define MR_FOR(NAME, N, OP, FUNC, ...) MR_PASTE2 (MR_FOR, N) (NAME, OP, FUNC, __VA_ARGS__)
#define P00_TYPEDEF_ATTR_STRUCT TYPEDEF_ATTR
#define P00_TYPEDEF_ATTR_UNION TYPEDEF_ATTR
#define P00_TYPEDEF_ATTR_ENUM TYPEDEF_ATTR
#define P00_TYPEDEF_ATTR_CHAR_ARRAY(P00_MODE, P00_TYPE, ATTR_META_RES, P00_TYPE_NAME, SIZE, ...) MR_PASTE2 (MR_TYPEDEF_CHAR_ARRAY_, P00_MODE) (P00_TYPE_NAME, SIZE, MR_PASTE2 (P00_REMOVE_, ATTR_META_RES), __VA_ARGS__)
#define P00_TYPEDEF_ATTR_FUNC(P00_MODE, P00_TYPE, ATTR_META_RES, RET_TYPE, P00_TYPE_NAME, ARGS, ...) MR_PASTE2 (MR_TYPEDEF_FUNC_, P00_MODE) (RET_TYPE, P00_TYPE_NAME, ARGS, MR_PASTE2 (P00_REMOVE_, ATTR_META_RES), __VA_ARGS__)
#define P00_UNFOLD(PREFIX, P00_TYPE, P00_MODE, ...) MR_PASTE4 (PREFIX, P00_TYPE, _, P00_MODE) (__VA_ARGS__)
#define TYPEDEF_ATTR(P00_MODE, P00_TYPE, ATTR_META_RES, P00_TYPE_NAME, ...) \
P00_UNFOLD (MR_TYPEDEF_, P00_TYPE, P00_MODE, P00_TYPE_NAME, MR_PASTE2 (P00_GET_FIRST_, ATTR_META_RES)) \
MR_FOR ((P00_MODE, P00_TYPE_NAME), MR_NARG (__VA_ARGS__), MR_SER, MR_PASTE3 (P00_, P00_TYPE, _HANDLER), __VA_ARGS__) \
P00_UNFOLD (MR_END_, P00_TYPE, P00_MODE, P00_TYPE_NAME, MR_PASTE2 (P00_GET_OTHER_, ATTR_META_RES))
# define P00_IS_ATTRIBUTES_EQ_ATTRIBUTES(...) 0 /* help macro for ATTRIBUTES test IF clause */
#define P00_REMOVE_ATTRIBUTES(...) __VA_ARGS__
#define P00_GET_FIRST_ATTRIBUTES(FIRST, ...) FIRST /* extract typedef attributes */
#define P00_GET_OTHER_ATTRIBUTES(FIRST, ...) __VA_ARGS__ /* extract typedef meta information */
All I want to know is how can a macro call such as
TYPEDEF_STRUCT (point_t,
double x,
double y
);
expand to that
typedef struct point_t {
double x;
double y;
} point_t;
I'm not sure why do you want to decouple headers from the rest of the library. Probably first 700 lines of metaresc.h are used in TYPEDEF_STRUCT, so you will need most of this file. Even though it will not help you, just because result of the macro is typedef + meta-data required for serialization. Serialization functions are implemented in the library, so there is no sense to decouple meta-data generation from the code that uses this meta-data.
You could run example through preprocessor and evaluate outcome. This will give you and idea what do I mean as meta-data.
If you are really interested in understanding of TYPEDEF_STRUCT macro implementation details, then get ready for 100+ layers of nested macros. As a first exercises you could start here https://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments/ and continue with other macro tricks from https://p99.gforge.inria.fr/

Collecting a list of function pointers and other ancillary data via distinct macro invocations

I want to declare a number of functions with the same signature, possibly spread across different header files, and then use the preprocessor to collect into an array pointers all such functions, and also create an an array of corresponding function names.
So, for example, assuming the common signature is int func(int x) I could have the following declarations:
FUNC(a) {
return x + x;
}
FUNC(b) {
return x >> 1;
}
FUNC(c) {
return x ^ 123;
}
... and the through some macro magic, I would end with something after preprocessing that looks like:
int a(int x) {
return x + x;
}
int b(int x) {
return x >> 1;
}
int c(int x) {
return x ^ 123;
}
typedef int (*intfunc_t)(int)
const intfunc_t func_ptrs[] = { &a, &b, &c };
const char *func_names[] = { "a", "b", "c" };
A worse version of this is possible using x-macros, but this requires a list like:
#define X_MACRO \
X(a) \
X(b) \
X(c)
This duplicates the information already encoded in the FUNC(a) definitions and makes it tough use this approach with an unknown number of functions spread across many headers, since this central list always needs to be kept in sync.
So I'm hoping there is some way to have the FUNC macro automatically generate the lists.
It doesn't have to compile-time constructed arrays as shown, either. Anything that allows me to iterate over the function pointers, and get their name and possibly other ancillary information (added via additional args to FUNC) could work, e.g., a linked list initialized at startup. You can assume all the FUNC macros appear in the same compilation unit.
While I'm not interested in gcc-specific solutions like __attribute__((constructor)).
Here is my attempt to mostly solve your problem.
It is just a minimal adaptation of the x-macros.
But the difference might just make it useable for you:
The actual functional code stays in distributed headers.
The core list only needs to be adapted to total number of such functions
(and their names, if they are not single letter alphabet),
i.e. it does not mirror the functionality.
That adapation to number of functions does not require editing the core implementation.
Here is the code, all in one "file", with hints where the files are split.
/* content of distributed header a.h */
#define FUNC_a_Implementation() \
{ \
return x+x; \
}
/* content of distributed header b.h */
#define FUNC_b_Implementation() \
{ \
return x>>1 ; \
}
/* content of distributed header c.h */
#define FUNC_c_Implementation() \
{ \
return ParCode; \
}
/* content of core editable header */
/* #include here the headers a.h, b.h c.h
potentially d.h, e.h and f.h in the future
*/
#define MAGIC_LIST(ParFlavor) \
ENTRY_##ParFlavor(a) \
ENTRY_##ParFlavor(b) \
ENTRY_##ParFlavor(c) \
/* add these when needed
ENTRY_##ParFlavor(d) \
ENTRY_##ParFlavor(e) \
ENTRY_##ParFlavor(f) \
*/
/* content of core implementation */
/* include editable core header */
#define ENTRY_Implementation(ParId) \
int Func##ParId (int x) \
FUNC_##ParId##_Implementation()
#define ENTRY_Pointer(ParId) \
&Func##ParId,
#define ENTRY_Name(ParId) \
"Func"#ParId,
MAGIC_LIST(Implementation)
const intfunc_t func_ptrs[] = {
MAGIC_LIST(Pointer)
NULL
}
const char *func_names[] = {
MAGIC_LIST(Name)
""
}
When preprocessing this, the result is:
$MinGW\bin\gcc -E macros.c
# 1 "macros.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "macros.c"
# 50 "macros.c"
int Funca (int x) { return x+x; } int Funcb (int x) { return x>>1 ; } int Funcc (int x) { return x^123; }
const intfunc_t func_ptrs[] = {
&Funca, &Funcb, &Funcc,
NULL
}
const char *func_names[] = {
"Func""a", "Func""b", "Func""c",
""
}
I added a final entry to the arrays, to avoid their intialisation ending in ",". But I think most compilers will actually allow that.
I expect compilers to replace "Func""a" with "Funca". I do not like short identifiers. If your compiler does not do as expected, remove the "Func" everywhere and require the Ids to be long enough.
Expanded macros will never have pretty indentation...
I'd have a header with a function typedef and the prototypes:
//the_header.h
typedef int intfunc_t(int); /*function not function pointer*/
intfunc_t a,b,c; /*prototypes*/
include it in each implementation file, and then have one file with:
#include "the_header.h"
const intfunc_t *func_ptrs[] = { a,b,c };
const char *func_names[] = { "a","b","c" };
While it is possible to remove the a,b,c duplication and have something like:
//the_header.h
typedef int intfunc_t(int); /*function not function pointer*/
#define FUNC a,b,c
intfunc_t FUNCS; /*prototypes*/
//collector.c
#include "the_header.h"
const intfunc_t *func_ptrs[] = { FUNCS };
const char *func_names[] = { STRINGIFY_EACH(FUNCS) };
Implementing STRINGIFY_EACH would require some dark macro magic (AFAIK), such as:
#define STRINGIFY_EACH(...) MC_foreachc(MC_str, __VA_ARGS__)
#define MC_str(_d) MC_str_impl_(_d)
#define MC_str_impl_(s) #s
#define MC_foreachc(What, ...) MC_foreachc_(MC_argc(__VA_ARGS__), What, __VA_ARGS__)
/* MC_foreachc(foo, a,b,c) foo(a), foo(b), foo(c); */
#define MC_foreachc_0( What, x, ...)
#define MC_foreachc_1( What, x, ...) What(x)
#define MC_foreachc_2( What, x, ...) What(x) , MC_expand(MC_foreachc_1( What, __VA_ARGS__))
#define MC_foreachc_3( What, x, ...) What(x) , MC_expand(MC_foreachc_2( What, __VA_ARGS__))
#define MC_foreachc_4( What, x, ...) What(x) , MC_expand(MC_foreachc_3( What, __VA_ARGS__))
#define MC_foreachc_5( What, x, ...) What(x) , MC_expand(MC_foreachc_4( What, __VA_ARGS__))
#define MC_foreachc_6( What, x, ...) What(x) , MC_expand(MC_foreachc_5( What, __VA_ARGS__))
#define MC_foreachc_7( What, x, ...) What(x) , MC_expand(MC_foreachc_6( What, __VA_ARGS__))
#define MC_foreachc_8( What, x, ...) What(x) , MC_expand(MC_foreachc_7( What, __VA_ARGS__))
#define MC_foreachc_9( What, x, ...) What(x) , MC_expand(MC_foreachc_8( What, __VA_ARGS__))
#define MC_foreachc_10( What, x, ...) What(x) , MC_expand(MC_foreachc_9( What, __VA_ARGS__))
#define MC_foreachc_11( What, x, ...) What(x) , MC_expand(MC_foreachc_10( What, __VA_ARGS__))
#define MC_foreachc_12( What, x, ...) What(x) , MC_expand(MC_foreachc_11( What, __VA_ARGS__))
#define MC_foreachc_13( What, x, ...) What(x) , MC_expand(MC_foreachc_12( What, __VA_ARGS__))
#define MC_foreachc_14( What, x, ...) What(x) , MC_expand(MC_foreachc_13( What, __VA_ARGS__))
#define MC_foreachc_15( What, x, ...) What(x) , MC_expand(MC_foreachc_14( What, __VA_ARGS__))
#define MC_foreachc_16( What, x, ...) What(x) , MC_expand(MC_foreachc_15( What, __VA_ARGS__))
#define MC_foreachc_17( What, x, ...) What(x) , MC_expand(MC_foreachc_16( What, __VA_ARGS__))
#define MC_foreachc_18( What, x, ...) What(x) , MC_expand(MC_foreachc_17( What, __VA_ARGS__))
#define MC_foreachc_19( What, x, ...) What(x) , MC_expand(MC_foreachc_18( What, __VA_ARGS__))
#define MC_foreachc_20( What, x, ...) What(x) , MC_expand(MC_foreachc_19( What, __VA_ARGS__))
#define MC_foreachc_21( What, x, ...) What(x) , MC_expand(MC_foreachc_20( What, __VA_ARGS__))
#define MC_foreachc_22( What, x, ...) What(x) , MC_expand(MC_foreachc_21( What, __VA_ARGS__))
#define MC_foreachc_23( What, x, ...) What(x) , MC_expand(MC_foreachc_22( What, __VA_ARGS__))
#define MC_foreachc_24( What, x, ...) What(x) , MC_expand(MC_foreachc_23( What, __VA_ARGS__))
#define MC_foreachc_25( What, x, ...) What(x) , MC_expand(MC_foreachc_24( What, __VA_ARGS__))
#define MC_foreachc_26( What, x, ...) What(x) , MC_expand(MC_foreachc_25( What, __VA_ARGS__))
#define MC_foreachc_27( What, x, ...) What(x) , MC_expand(MC_foreachc_26( What, __VA_ARGS__))
#define MC_foreachc_28( What, x, ...) What(x) , MC_expand(MC_foreachc_27( What, __VA_ARGS__))
#define MC_foreachc_29( What, x, ...) What(x) , MC_expand(MC_foreachc_28( What, __VA_ARGS__))
#define MC_foreachc_30( What, x, ...) What(x) , MC_expand(MC_foreachc_29( What, __VA_ARGS__))
#define MC_foreachc_31( What, x, ...) What(x) , MC_expand(MC_foreachc_30( What, __VA_ARGS__))
#define MC_foreachc_32( What, x, ...) What(x) , MC_expand(MC_foreachc_31( What, __VA_ARGS__))
#define MC_foreachc_(N, What, ...) MC_expand(MC_cat(MC_foreachc_, N)( What, __VA_ARGS__))

How can I make a MAP(f, ...) macro treat the last value differently?

I've been using #WilliamSwanson MAP() macro suggestion which "applies" another macro, or function, to all other macro arguments, e.g.
MAP(foo, x, y, z)
expands to
foo(x) foo(y) foo(z)
Here's the code for what I have now:
#define EVAL0(...) __VA_ARGS__
#define EVAL1(...) EVAL0 (EVAL0 (EVAL0 (__VA_ARGS__)))
#define EVAL2(...) EVAL1 (EVAL1 (EVAL1 (__VA_ARGS__)))
#define EVAL3(...) EVAL2 (EVAL2 (EVAL2 (__VA_ARGS__)))
#define EVAL4(...) EVAL3 (EVAL3 (EVAL3 (__VA_ARGS__)))
#define EVAL(...) EVAL4 (EVAL4 (EVAL4 (__VA_ARGS__)))
#define MAP_END(...)
#define MAP_OUT
#define MAP_GET_END() 0, MAP_END
#define MAP_NEXT0(test, next, ...) next MAP_OUT
#define MAP_NEXT1(test, next) MAP_NEXT0 (test, next, 0)
#define MAP_NEXT(test, next) MAP_NEXT1 (MAP_GET_END test, next)
#define MAP0(f, x, peek, ...) f(x) MAP_NEXT (peek, MAP1) (f, peek, __VA_ARGS__)
#define MAP1(f, x, peek, ...) f(x) MAP_NEXT (peek, MAP0) (f, peek, __VA_ARGS__)
#define MAP(f, ...) EVAL (MAP1 (f, __VA_ARGS__, (), 0))
... and it works well for me. However, I want to add some separator macro between every such application, i.e. get
foo(x) bar foo(y) bar foo(z)
in the example above. How would I alter the macro to do what I want? I'm guessing it must be some replacement of the end test with a one-more-till-the-end test, but I can't quite get it right. If you have your own implementation of this functionality, I suppose that would work as well (although I kind of like this one, it's relatively short and neat).
Note: This is essentially equivalent to asking how to get MAP() to do something arbitrarily different with last element as opposed to all the rest.

Macro count params

In order to make compiler happy I have to count params passed to A(), otherwise gcc raises "warning: ISO C99 requires rest arguments to be used" when pedantic flag is on and only one param is passed
#include <stdio.h>
/* Count params */
#define N_ARGS(...) N_ARGS_IMPL(__VA_ARGS__,n,n,n,n,n,n,n,n,n,1,1)
#define N_ARGS_IMPL(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,N,...) N
#define A_fmt_void
#define A_arg_void
/* link */
#define A_fmt_link_1(fmt) " href=\""fmt"\""
#define A_fmt_link_n(fmt, ...) " href=\""fmt"\""
#define A_fmt_link_N(n, ...) A_fmt_link_##n(__VA_ARGS__)
#define A_fmt_link_X(n, ...) A_fmt_link_N(n,__VA_ARGS__)
#define A_fmt_link(...) A_fmt_link_X(N_ARGS(__VA_ARGS__), __VA_ARGS__)
#define A_arg_link_1(fmt)
#define A_arg_link_n(fmt, ...) , __VA_ARGS__
#define A_arg_link_N(n, ...) A_arg_link_##n(__VA_ARGS__)
#define A_arg_link_X(n, ...) A_arg_link_N(n,__VA_ARGS__)
#define A_arg_link(...) A_arg_link_X(N_ARGS(__VA_ARGS__), __VA_ARGS__)
/* text */
#define A_fmt_text_1(fmt) fmt
#define A_fmt_text_n(fmt, ...) fmt
#define A_fmt_text_N(n, ...) A_fmt_text_##n(__VA_ARGS__)
#define A_fmt_text_X(n, ...) A_fmt_text_N(n,__VA_ARGS__)
#define A_fmt_text(...) A_fmt_text_X(N_ARGS(__VA_ARGS__), __VA_ARGS__)
#define A_arg_text_1(fmt)
#define A_arg_text_n(fmt, ...) , __VA_ARGS__
#define A_arg_text_N(n, ...) A_arg_text_##n(__VA_ARGS__)
#define A_arg_text_X(n, ...) A_arg_text_N(n,__VA_ARGS__)
#define A_arg_text(...) A_arg_text_X(N_ARGS(__VA_ARGS__), __VA_ARGS__)
/* macro */
#define A(link, text) \
printf("<a"A_fmt_##link">"A_fmt_##text"</a>\n" A_arg_##link A_arg_##text)
int main(void)
{
A(link(), void);
A(void, text());
A(link("http://www.google.es"), void);
A(link("%s/%s", "http://www.google.es", "home"), text("Visit google"));
A(void, text("%s today", "Visit google"));
A(link("http://%s/%s", "www.google.es", "home"), text("%s today", "Visit google"));
A(void,void);
return 0;
}
With this implementation of N_ARGS I can use only 10 params, is there another way to check if there is more than one param without limit in macro?
I know , ## __VA_ARGS__ gcc extension but I want to avoid warnings
Finally I've fixed using __ extension__
#include <stdio.h>
#define A_fmt_void
#define A_arg_void
#define A_fmt_link(fmt, ...) " href=\""fmt"\""
#define A_arg_link(fmt, ...) , ## __VA_ARGS__
#define A_fmt_text(fmt, ...) fmt
#define A_arg_text(fmt, ...) , ## __VA_ARGS__
#define A(link, text) \
__extension__ printf("<a" A_fmt_##link ">" A_fmt_##text "</a>\n" A_arg_##link A_arg_##text)
int main(void)
{
A(
link("%s", "http://wwww.google.com"),
text("%s", "Visit google")
);
A(
link("http://wwww.google.com"),
void
);
A(
void,
text("Visit google")
);
A(
void,
void
);
return 0;
}
This prevents warnings when pedantic flag is on :)

C macro, wrong argument number returned

I have following macros:
#define CONCATENATE(arg1, arg2) arg1##arg2
#define FOR_EACH_1(what, x, ...) what(x)
#define FOR_EACH_2(what, x, ...) what(x) FOR_EACH_1(what, __VA_ARGS__)
#define FOR_EACH_3(what, x, ...) what(x) FOR_EACH_2(what, __VA_ARGS__)
#define FOR_EACH_4(what, x, ...) what(x) FOR_EACH_3(what, __VA_ARGS__)
#define FOR_EACH_5(what, x, ...) what(x) FOR_EACH_4(what, __VA_ARGS__)
#define FOR_EACH_6(what, x, ...) what(x) FOR_EACH_5(what, __VA_ARGS__)
#define FOR_EACH_7(what, x, ...) what(x) FOR_EACH_6(what, __VA_ARGS__)
#define FOR_EACH_8(what, x, ...) what(x) FOR_EACH_7(what, __VA_ARGS__)
#define FOR_EACH_NARG(...) FOR_EACH_NARG_(__VA_ARGS__, FOR_EACH_RSEQ_N())
#define FOR_EACH_NARG_(...) FOR_EACH_ARG_N(__VA_ARGS__)
#define FOR_EACH_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, N, ...) N
#define FOR_EACH_RSEQ_N() 8, 7, 6, 5, 4, 3, 2, 1, 0
#define FOR_EACH_(N, what, x, ...) CONCATENATE(FOR_EACH_, N)(what, x, __VA_ARGS__)
#define FOR_EACH(what, x, ...) FOR_EACH_(FOR_EACH_NARG(x, __VA_ARGS__), what, x, __VA_ARGS__)
These are my test cases:
// does not work as intended (with one argument)
#define SOME(x) int x;
FOR_EACH(SOME, y)
// fine with 2 and more
FOR_EACH(SOME, y1, y2);
FOR_EACH(SOME, y3, y4, y5, y6);
// works fine even for one argument
#define ONLY(x) x
int FOR_EACH(ONLY, x);
Could please someone explain to me what I'm doing wrong for the case with only one argument, #define SOME(x) int x??
Compile it with gcc -E macro.c -o macro.lol, gives result:
int y; int ; /* <-- that's wrong, why??? */
int y1; int y2;;
int y3; int y4; int y5; int y6;;
int x ; /* <-- works as supposed */
The problem is that when you pass two arguments to FOR_EACH (just the what and x), the __VA_ARGS__ expands to nothing, and you have a trailing comma in the call to FOR_EACH_NARG, so it expands to 2 and therefore expands FOR_EACH_2.
You want to get rid of that trailing comma. You can do that by either using the non-standard extension of using ##__VA_ARGS__ instead of __VA_ARGS__, which removes the comma before it only if __VA_ARGS__ is empty. For a more standards-compliant version, you can combine the x and __VA_ARGS__ into a single parameter:
#define FOR_EACH_(N, what, ...) CONCATENATE(FOR_EACH_, N)(what, __VA_ARGS__)
#define FOR_EACH(what, ...) FOR_EACH_(FOR_EACH_NARG(__VA_ARGS__), what, __VA_ARGS__)
You should have seen some warning from your compiler, that you failed to tell us about.
My guess would be that your macro here
#define FOR_EACH_1(what, x, ...) what(x)
is wrong because it never sees a __VA_ARGS__ part. I see two ways of healing that
#define FOR_EACH_1(what, ...) what(__VA_ARGS__)
#define FOR_EACH_1(what, x) what(x)
Another thing that could hurt you with such macros is the different counting of argument numbers than you are used to with C.
#define MUCH(...)
#define NONE()
NONE //<- this is considered receiving no argument
MUCH //<- this receives one argument, the empty token list
If you are doing this for learning the preprocessor, this is fine :) if you really what a generic solution for this kind of problems you could have a look into Boost (but this is mainly C++) and P99

Resources