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 :)
Related
I'm initializing an array of structures with the help of a define like this:
#define FLAGCODE(name) { #name, MNT_ ## name }
struct {
const char *name;
uint64_t flag;
} flagcodes[] = {
FLAGCODE(ACLS),
FLAGCODE(ASYNC),
...
This works nicely, and now I'd like to add a check, whether each flag (such as MNT_ACLS) is defined without inserting an #ifdef and #endif for each symbol by hand?
That is, I want the macro FLAGCODE(name) to expand into (an equivalent of):
#ifdef MNT_ ##name
{ # name, MNT_ ##name },
#endif
Exempli gratia, if name is NOATIME, the code shall become:
#ifdef MNT_NOATIME
{ "NOATIME", MNT_NOATIME },
#endif
Yes, I realize, that this would mean double pass through preprocessor, and so is unlikely to be possible -- without a custom code-generator... But still...
There is a solution but highly not recommended! You could do funny things with C-preprocessor (cf. Macro to replace nested for loops and links in the question). But I repeat it: Don't do it. It is a cpp abuse.
In two words, you have to create your own #ifdef with macro. In the code below, ISDEF is an "operator" to check if the flag is defined and #if has been redefined: IIF (To understand, all explanations are here: https://github.com/pfultz2/Cloak/wiki/C-Preprocessor-tricks,-tips,-and-idioms)
#define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__
#define COMMA ,
#define IIF(c) PRIMITIVE_CAT(IIF_, c)
#define IIF_0(t, ...) __VA_ARGS__
#define IIF_1(t, ...) t
#define CHECK_N(x, n, ...) n
#define CHECK(...) CHECK_N(__VA_ARGS__, 0,)
#define PROBE(x) x, 1,
#define ISDEF(x) CHECK(PRIMITIVE_CAT(ISDEF_, x))
#define ISDEF_ PROBE(~)
#define FLAGCODE(name) IIF(ISDEF(name))({ #name COMMA MNT_ ## name }COMMA)
#define ACLS
#define FLAGDEFINED
int main()
{
struct {
const char *name;
uint64_t flag;
} flagcodes[] = {
FLAGCODE(ACLS)
FLAGCODE(ASYNC)
FLAGCODE(FLAGDEFINED)
FLAGCODE(FLAGNOTDEFINED)
...
You could also do a list with your flags (cf. MAP part in http://jhnet.co.uk/articles/cpp_magic).
Enjoy but do not go overboard with preprocessor.
Following the very good comment of Chris Dodd,
1 : This tricks works if the flag is define as empty (#define FLAGDEFINED). It does not work with, for example, #define FLAGDEFINED 1 or #define FLAGDEFINED xxx.
2 : CPP_ prefix has been added and name is changed by CPP_FLAG
#define CPP_PRIMITIVE_CAT(CPP_a, ...) CPP_a ## __VA_ARGS__
#define CPP_COMMA ,
#define CPP_IIF(CPP_c) CPP_PRIMITIVE_CAT(CPP_IIF_, CPP_c)
#define CPP_IIF_0(CPP_t, ...) __VA_ARGS__
#define CPP_IIF_1(CPP_t, ...) CPP_t
#define CPP_CHECK_N(CPP_x, CPP_n, ...) CPP_n
#define CPP_CHECK(...) CPP_CHECK_N(__VA_ARGS__, 0,)
#define CPP_PROBE(CPP_x) CPP_x, 1,
#define CPP_ISDEF(CPP_x) CPP_CHECK(CPP_PRIMITIVE_CAT(CPP_ISDEF_, CPP_x))
#define CPP_ISDEF_ CPP_PROBE(~)
#define CPP_FLAGCODE(CPP_FLAG) CPP_IIF(CPP_ISDEF(CPP_FLAG))({ #CPP_FLAG CPP_COMMA MNT_ ## CPP_FLAG }CPP_COMMA)
#define ACLS
#define FLAGDEFINED
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/
I'd like to know how to apply a unary function (or another macro) to variadic arguments of a macro, like
int f(int a);
#define apply(args...) <the magic>
apply(a, b, c)
which unrolls
f(a)
f(b)
f(c)
Note that the number of arguments is unknown.
The code below is working for what you've asked for with up to 1024 arguments and without using additional stuff like boost. It defines an EVAL(...) and also a MAP(m, first, ...) macro to do recursion and to use for each iteration the macro m with the next parameter first.
With the use of that, your apply(...) looks like: #define apply(...) EVAL(MAP(apply_, __VA_ARGS__)).
It is mostly copied from C Pre-Processor Magic. It is also great explained there. You can also download these helper macros like EVAL(...) at this git repository, there are also a lot of explanation in the actual code. It is variadic so it takes the number of arguments you want.
But I changed the FIRST and the SECOND macro as it uses a Gnu extension like it is in the source I've copied it from. This is said in the comments below by #HWalters:
Specifically, 6.10.3p4: "Otherwise [the identifier-list ends in a ...] there shall be more arguments in the invocation than there are parameters in the macro definition (excluding the ...)".
Main function part:
int main()
{
int a, b, c;
apply(a, b, c) /* Expands to: f(a); f(b); f(c); */
return 0;
}
Macro definitions:
#define FIRST_(a, ...) a
#define SECOND_(a, b, ...) b
#define FIRST(...) FIRST_(__VA_ARGS__,)
#define SECOND(...) SECOND_(__VA_ARGS__,)
#define EMPTY()
#define EVAL(...) EVAL1024(__VA_ARGS__)
#define EVAL1024(...) EVAL512(EVAL512(__VA_ARGS__))
#define EVAL512(...) EVAL256(EVAL256(__VA_ARGS__))
#define EVAL256(...) EVAL128(EVAL128(__VA_ARGS__))
#define EVAL128(...) EVAL64(EVAL64(__VA_ARGS__))
#define EVAL64(...) EVAL32(EVAL32(__VA_ARGS__))
#define EVAL32(...) EVAL16(EVAL16(__VA_ARGS__))
#define EVAL16(...) EVAL8(EVAL8(__VA_ARGS__))
#define EVAL8(...) EVAL4(EVAL4(__VA_ARGS__))
#define EVAL4(...) EVAL2(EVAL2(__VA_ARGS__))
#define EVAL2(...) EVAL1(EVAL1(__VA_ARGS__))
#define EVAL1(...) __VA_ARGS__
#define DEFER1(m) m EMPTY()
#define DEFER2(m) m EMPTY EMPTY()()
#define IS_PROBE(...) SECOND(__VA_ARGS__, 0)
#define PROBE() ~, 1
#define CAT(a,b) a ## b
#define NOT(x) IS_PROBE(CAT(_NOT_, x))
#define _NOT_0 PROBE()
#define BOOL(x) NOT(NOT(x))
#define IF_ELSE(condition) _IF_ELSE(BOOL(condition))
#define _IF_ELSE(condition) CAT(_IF_, condition)
#define _IF_1(...) __VA_ARGS__ _IF_1_ELSE
#define _IF_0(...) _IF_0_ELSE
#define _IF_1_ELSE(...)
#define _IF_0_ELSE(...) __VA_ARGS__
#define HAS_ARGS(...) BOOL(FIRST(_END_OF_ARGUMENTS_ __VA_ARGS__)())
#define _END_OF_ARGUMENTS_() 0
#define MAP(m, first, ...) \
m(first) \
IF_ELSE(HAS_ARGS(__VA_ARGS__))( \
DEFER2(_MAP)()(m, __VA_ARGS__) \
)( \
/* Do nothing, just terminate */ \
)
#define _MAP() MAP
#define apply_(x) f(x);
#define apply(...) EVAL(MAP(apply_, __VA_ARGS__))
To test macro expansion it is useful to use gcc with the command line argument -E:
$ gcc -E srcFile.c
because your're getting concrete error messages and understand what's going on.
Everything is possible in C if you throw enough ugly macros at it. For example, you can have an ugly function-like macro:
#include <stdio.h>
int f (int a)
{
printf("%d\n", a);
}
#define SIZEOF(arr) (sizeof(arr) / sizeof(*arr))
#define apply(...) \
{ \
int arr[] = {__VA_ARGS__}; \
for(size_t i=0; i<SIZEOF(arr); i++) \
{ \
f(arr[i]); \
} \
}
int main (void)
{
apply(1, 2, 3);
}
Notice that 1) This would be much better off as a variadic function, and 2) it would be even better if you get rid of the variadic nonsense entirely and simply make a function such as
int f (size_t n, int array[n])
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__))
I am trying to write a macro which counts the number of specific elements in a sequence. E.g. for the sequence (A)(B)(A) I want to get the count 2 for A.
Now taking the approach from https://stackoverflow.com/a/12540675/2525536 I end up with this code:
#define CAT(x, ...) CAT1(x, __VA_ARGS__)
#define CAT1(x, ...) CAT2(x, __VA_ARGS__)
#define CAT2(x, ...) x ## __VA_ARGS__
#define EXPAND(...) __VA_ARGS__
#define EAT(...)
#define DEFER(...) __VA_ARGS__ EAT()
#define OBSTRUCT(...) __VA_ARGS__ DEFER(EAT)()
#define SIZE(seq) CAT(SIZE_, SIZE_0 seq)
#define SIZE_0(...) SIZE_1
#define SIZE_1(...) SIZE_2
#define SIZE_2(...) SIZE_3
#define SIZE_3(...) SIZE_4
#define SIZE_SIZE_0 0
#define SIZE_SIZE_1 1
#define SIZE_SIZE_2 2
#define SIZE_SIZE_3 3
#define SIZE_SIZE_4 4
#define GET_FIRST(x) GET_FIRST2(GET_FIRST1 x)
#define GET_FIRST1(x) x, EAT()
#define GET_FIRST2(x) GET_FIRST3(x)
#define GET_FIRST3(x, ...) x
#define POP_FIRST(x) EAT x
#define EVAL(...) EVAL1(EVAL1(__VA_ARGS__))
#define EVAL1(...) EVAL2(EVAL2(__VA_ARGS__))
#define EVAL2(...) EVAL3(EVAL3(__VA_ARGS__))
#define EVAL3(...) EVAL4(EVAL4(__VA_ARGS__))
#define EVAL4(...) __VA_ARGS__
#define CHECK_N(x, n, ...) n
#define CHECK(...) CHECK_N(__VA_ARGS__, 0,)
#define CHECK_PROBE(x) x, 1,
#define NOT(x) CHECK(CAT(NOT_, x))
#define NOT_0 ~, 1,
#define COMPL(b) CAT(COMPL_, b)
#define COMPL_0 1
#define COMPL_1 0
#define BOOL(x) COMPL(NOT(x))
#define IIF(c) CAT(IIF_, c)
#define IIF_0(t, ...) __VA_ARGS__
#define IIF_1(t, ...) t
#define IF(c) IIF(BOOL(c))
#define WHEN(c) IF(c)(EXPAND, EAT)
#define INC(x) CAT(INC_, x)
#define INC_0 1
#define INC_1 2
#define INC_2 3
#define INC_3 4
#define INC_4 5
#define DEC(x) CAT(DEC_, x)
#define DEC_0 0
#define DEC_1 0
#define DEC_2 1
#define DEC_3 2
#define DEC_4 3
#define DEC_5 4
#define COUNT_IF(tpl, data, x) COUNT_IF1(0, SIZE(x), 0, tpl, data, x)
#define COUNT_IF1(i, n, count, tpl, data, x) \
IF(n) ( \
OBSTRUCT(CAT) ( \
COUNT_IF3_, \
tpl(i, data, GET_FIRST(x)) \
) ( \
OBSTRUCT(COUNT_IF2)() \
(INC(i), DEC(n), count, tpl, data, POP_FIRST(x)) /* call recursive */ \
) \
, count \
)
#define COUNT_IF2() COUNT_IF1
#define COUNT_IF3_0 EXPAND
#define COUNT_IF3_1 INC
#define A_EQUAL_A(...) 1
#define A_EQUAL_B(...) 0
#define COUNT_A(i, data, x) CAT(A_EQUAL_, x)(i)
EVAL(COUNT_IF(COUNT_A, ~, (A)))
EVAL(COUNT_IF(COUNT_A, ~, (B)))
EVAL(COUNT_IF(COUNT_A, ~, (A)(B)))
EVAL(COUNT_IF(COUNT_A, ~, (B)(A)))
EVAL(COUNT_IF(COUNT_A, ~, (A)(A)))
EVAL(COUNT_IF(COUNT_A, ~, (B)(B)))
EVAL(COUNT_IF(COUNT_A, ~, (A)(B)(A)))
This works already quite well for the first 4 examples but ends up with wrong macro name expandation for the others (where INC or EXPAND needs to be expanded more than once).
The reason for the is probably because macros are marked blue in C, which is why this works https://stackoverflow.com/a/11640759/2525536.
But I cannot find a workaround for this.
Anyone an idea?
As I already received some comments about using the C preprocessor for this task is not an appropiate way of handling this issue I still intent to go this way not only to minimize code dependencies but also to make the best out of what C offers in my code (which may not be obvious here).
Having this said I found out why the macro was not expanding correctly and also a way to make the preprocessor do this task correctly.
The issue was that the macro generated a construct like INC(EXPAND(INC(0))) from outside (first element) to inside (last element). The preprocessor tried to solve this while always only knowing all values until the current level/element. This turned into something like INC(COUNT_IF1(...)) on which point the preprocessor started to substitute INC for example.
The correct way of handling this was to make the preprocessor extend the macro from inside to outside.
Simplifying the code a little bit gives this solution:
#define CAT(x, ...) CAT1(x, __VA_ARGS__)
#define CAT1(x, ...) CAT2(x, __VA_ARGS__)
#define CAT2(x, ...) x ## __VA_ARGS__
#define EXPAND(...) __VA_ARGS__
#define EAT(...)
#define DEFER(...) __VA_ARGS__ EAT()
#define OBSTRUCT(...) __VA_ARGS__ DEFER(EAT)()
#define SIZE(seq) CAT(SIZE_, SIZE_0 seq)
#define SIZE_0(...) SIZE_1
#define SIZE_1(...) SIZE_2
#define SIZE_2(...) SIZE_3
#define SIZE_3(...) SIZE_4
#define SIZE_SIZE_0 0
#define SIZE_SIZE_1 1
#define SIZE_SIZE_2 2
#define SIZE_SIZE_3 3
#define SIZE_SIZE_4 4
#define GET_FIRST(x) GET_FIRST2(GET_FIRST1 x)
#define GET_FIRST1(x) x, EAT()
#define GET_FIRST2(x) GET_FIRST3(x)
#define GET_FIRST3(x, ...) x
#define POP_FIRST(x) EAT x
#define EVAL(...) EVAL1(EVAL1(__VA_ARGS__))
#define EVAL1(...) EVAL2(EVAL2(__VA_ARGS__))
#define EVAL2(...) EVAL3(EVAL3(__VA_ARGS__))
#define EVAL3(...) EVAL4(EVAL4(__VA_ARGS__))
#define EVAL4(...) __VA_ARGS__
#define CHECK_N(x, n, ...) n
#define CHECK(...) CHECK_N(__VA_ARGS__, 0,)
#define CHECK_PROBE(x) x, 1,
#define NOT(x) CHECK(CAT(NOT_, x))
#define NOT_0 ~, 1,
#define COMPL(b) CAT(COMPL_, b)
#define COMPL_0 1
#define COMPL_1 0
#define BOOL(x) COMPL(NOT(x))
#define IIF(c) CAT(IIF_, c)
#define IIF_0(t, ...) __VA_ARGS__
#define IIF_1(t, ...) t
#define IF(c) IIF(BOOL(c))
#define WHEN(c) IF(c)(EXPAND, EAT)
#define INC(x) CAT(INC_, x)
#define INC_0 1
#define INC_1 2
#define INC_2 3
#define INC_3 4
#define INC_4 5
#define DEC(x) CAT(DEC_, x)
#define DEC_0 0
#define DEC_1 0
#define DEC_2 1
#define DEC_3 2
#define DEC_4 3
#define DEC_5 4
#define IS_PAREN(x) CHECK(IS_PARENT1 x)
#define IS_PARENT1(...) CHECK_PROBE(~)
#define IS_COMPARABLE(x) IS_PAREN(CAT(COMPARE_, x)(()))
#define BITAND(lhs, rhs) CAT(CAT(CAT(BITAND_, lhs), _), rhs)
#define BITAND_0_0 0
#define BITAND_0_1 0
#define BITAND_1_0 0
#define BITAND_1_1 1
#define NOT_EQUAL(lhs, rhs) \
IIF(BITAND(IS_COMPARABLE(lhs), IS_COMPARABLE(rhs)))( \
NOT_EQUAL_HELPER, \
1 NULL \
)(lhs, rhs)
#define NOT_EQUAL_HELPER(lhs, rhs) IS_PAREN( \
CAT(COMPARE_, lhs)(CAT(COMPARE_, rhs))(()) \
)
#define EQUAL(lhs, rhs) COMPL(NOT_EQUAL(lhs, rhs))
#define COUNT_IF(match, x) COUNT_IF1(SIZE(x), match, 0, x)
#define COUNT_IF1(n, match, count, x) \
IF(n) ( \
OBSTRUCT(COUNT_IF2)()( \
DEC(n), \
match, \
IF(match(GET_FIRST(x)))(INC, EXPAND)(count), POP_FIRST(x) \
) /* call recursive */ \
, count \
)
#define COUNT_IF2() COUNT_IF1
#define COMPARE_A(x) x
#define EQUAL_A(x) EQUAL(x, A)
EVAL(COUNT_IF(EQUAL_A, (A)))
EVAL(COUNT_IF(EQUAL_A, (B)))
EVAL(COUNT_IF(EQUAL_A, (A)(B)))
EVAL(COUNT_IF(EQUAL_A, (B)(A)))
EVAL(COUNT_IF(EQUAL_A, (A)(A)))
EVAL(COUNT_IF(EQUAL_A, (B)(B)))
EVAL(COUNT_IF(EQUAL_A, (A)(B)(A)(A)))
P.S.: An 11 lines macro still seems simple enough to me to handle in terms of complexity and maintainability.