/* MIT (BSD) license - see LICENSE file for details */ #ifndef CCAN_CPPMAGIC_H #define CCAN_CPPMAGIC_H /** * CPPMAGIC_NOTHING - expands to nothing */ #define CPPMAGIC_NOTHING() /** * CPPMAGIC_STRINGIFY - convert arguments to a string literal */ #define _CPPMAGIC_STRINGIFY(...) #__VA_ARGS__ #define CPPMAGIC_STRINGIFY(...) _CPPMAGIC_STRINGIFY(__VA_ARGS__) /** * CPPMAGIC_GLUE2 - glue arguments together * * CPPMAGIC_GLUE2(@a_, @b_) * expands to the expansion of @a_ followed immediately * (combining tokens) by the expansion of @b_ */ #define _CPPMAGIC_GLUE2(a_, b_) a_##b_ #define CPPMAGIC_GLUE2(a_, b_) _CPPMAGIC_GLUE2(a_, b_) /** * CPPMAGIC_1ST - return 1st argument * * CPPMAGIC_1ST(@a_, ...) * expands to the expansion of @a_ */ #define CPPMAGIC_1ST(a_, ...) a_ /** * CPPMAGIC_2ND - return 2nd argument * * CPPMAGIC_2ST(@a_, @b_, ...) * expands to the expansion of @b_ */ #define CPPMAGIC_2ND(a_, b_, ...) b_ /** * CPPMAGIC_ISZERO - is argument '0' * * CPPMAGIC_ISZERO(@a) * expands to '1' if @a is '0', otherwise expands to '0'. */ #define _CPPMAGIC_ISPROBE(...) CPPMAGIC_2ND(__VA_ARGS__, 0) #define _CPPMAGIC_PROBE() $, 1 #define _CPPMAGIC_ISZERO_0 _CPPMAGIC_PROBE() #define CPPMAGIC_ISZERO(a_) \ _CPPMAGIC_ISPROBE(CPPMAGIC_GLUE2(_CPPMAGIC_ISZERO_, a_)) /** * CPPMAGIC_NONZERO - is argument not '0' * * CPPMAGIC_NONZERO(@a) * expands to '0' if @a is '0', otherwise expands to '1'. */ #define CPPMAGIC_NONZERO(a_) CPPMAGIC_ISZERO(CPPMAGIC_ISZERO(a_)) /** * CPPMAGIC_NONEMPTY - does the macro have any arguments? * * CPPMAGIC_NONEMPTY() * expands to '0' * CPPMAGIC_NONEMPTY(@a) * CPPMAGIC_NONEMPTY(@a, ...) * expand to '1' */ #define _CPPMAGIC_EOA() 0 #define CPPMAGIC_NONEMPTY(...) \ CPPMAGIC_NONZERO(CPPMAGIC_1ST(_CPPMAGIC_EOA __VA_ARGS__)()) /** * CPPMAGIC_ISEMPTY - does the macro have no arguments? * * CPPMAGIC_ISEMPTY() * expands to '1' * CPPMAGIC_ISEMPTY(@a) * CPPMAGIC_ISEMPTY(@a, ...) * expand to '0' */ #define CPPMAGIC_ISEMPTY(...) \ CPPMAGIC_ISZERO(CPPMAGIC_NONEMPTY(__VA_ARGS__)) /* * CPPMAGIC_IFELSE - preprocessor conditional * * CPPMAGIC_IFELSE(@cond)(@if)(@else) * expands to @else if @cond is '0', otherwise expands to @if */ #define _CPPMAGIC_IF_0(...) _CPPMAGIC_IF_0_ELSE #define _CPPMAGIC_IF_1(...) __VA_ARGS__ _CPPMAGIC_IF_1_ELSE #define _CPPMAGIC_IF_0_ELSE(...) __VA_ARGS__ #define _CPPMAGIC_IF_1_ELSE(...) #define _CPPMAGIC_IFELSE(cond_) CPPMAGIC_GLUE2(_CPPMAGIC_IF_, cond_) #define CPPMAGIC_IFELSE(cond_) \ _CPPMAGIC_IFELSE(CPPMAGIC_NONZERO(cond_)) /** * CPPMAGIC_EVAL - force multiple expansion passes * * Forces macros in the arguments to be expanded repeatedly (up to * 1024 times) even when CPP would usually stop expanding. */ #define CPPMAGIC_EVAL1(...) __VA_ARGS__ #define CPPMAGIC_EVAL2(...) \ CPPMAGIC_EVAL1(CPPMAGIC_EVAL1(__VA_ARGS__)) #define CPPMAGIC_EVAL4(...) \ CPPMAGIC_EVAL2(CPPMAGIC_EVAL2(__VA_ARGS__)) #define CPPMAGIC_EVAL8(...) \ CPPMAGIC_EVAL4(CPPMAGIC_EVAL4(__VA_ARGS__)) #define CPPMAGIC_EVAL16(...) \ CPPMAGIC_EVAL8(CPPMAGIC_EVAL8(__VA_ARGS__)) #define CPPMAGIC_EVAL32(...) \ CPPMAGIC_EVAL16(CPPMAGIC_EVAL16(__VA_ARGS__)) #define CPPMAGIC_EVAL64(...) \ CPPMAGIC_EVAL32(CPPMAGIC_EVAL32(__VA_ARGS__)) #define CPPMAGIC_EVAL128(...) \ CPPMAGIC_EVAL64(CPPMAGIC_EVAL64(__VA_ARGS__)) #define CPPMAGIC_EVAL256(...) \ CPPMAGIC_EVAL128(CPPMAGIC_EVAL128(__VA_ARGS__)) #define CPPMAGIC_EVAL512(...) \ CPPMAGIC_EVAL256(CPPMAGIC_EVAL256(__VA_ARGS__)) #define CPPMAGIC_EVAL1024(...) \ CPPMAGIC_EVAL512(CPPMAGIC_EVAL512(__VA_ARGS__)) #define CPPMAGIC_EVAL(...) CPPMAGIC_EVAL1024(__VA_ARGS__) /** * CPPMAGIC_DEFER1, CPPMAGIC_DEFER2 - defer expansion */ #define CPPMAGIC_DEFER1(a_) a_ CPPMAGIC_NOTHING() #define CPPMAGIC_DEFER2(a_) a_ CPPMAGIC_NOTHING CPPMAGIC_NOTHING()() /** * CPPMAGIC_MAP - iterate another macro across arguments * @m: name of a one argument macro * * CPPMAGIC_MAP(@m, @a1, @a2, ... @an) * expands to the expansion of @m(@a1) , @m(@a2) , ... , @m(@an) */ #define _CPPMAGIC_MAP_() _CPPMAGIC_MAP #define _CPPMAGIC_MAP(m_, a_, ...) \ m_(a_) \ CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__)) \ (, CPPMAGIC_DEFER2(_CPPMAGIC_MAP_)()(m_, __VA_ARGS__)) \ () #define CPPMAGIC_MAP(m_, ...) \ CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__)) \ (CPPMAGIC_EVAL(_CPPMAGIC_MAP(m_, __VA_ARGS__))) \ () /** * CPPMAGIC_2MAP - iterate another macro across pairs of arguments * @m: name of a two argument macro * * CPPMAGIC_2MAP(@m, @a1, @b1, @a2, @b2, ..., @an, @bn) * expands to the expansion of * @m(@a1, @b1) , @m(@a2, @b2) , ... , @m(@an, @bn) */ #define _CPPMAGIC_2MAP_() _CPPMAGIC_2MAP #define _CPPMAGIC_2MAP(m_, a_, b_, ...) \ m_(a_, b_) \ CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__)) \ (, CPPMAGIC_DEFER2(_CPPMAGIC_2MAP_)()(m_, __VA_ARGS__)) \ () #define CPPMAGIC_2MAP(m_, ...) \ CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__)) \ (CPPMAGIC_EVAL(_CPPMAGIC_2MAP(m_, __VA_ARGS__))) \ () /** * CPPMAGIC_JOIN - separate arguments with given delimiter * @d: delimiter * * CPPMAGIC_JOIN(@d, @a1, @a2, ..., @an) * expands to the expansion of @a1 @d @a2 @d ... @d @an */ #define _CPPMAGIC_JOIN_() _CPPMAGIC_JOIN #define _CPPMAGIC_JOIN(d_, a_, ...) \ a_ \ CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__)) \ (d_ CPPMAGIC_DEFER2(_CPPMAGIC_JOIN_)()(d_, __VA_ARGS__)) \ () #define CPPMAGIC_JOIN(d_, ...) \ CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__)) \ (CPPMAGIC_EVAL(_CPPMAGIC_JOIN(d_, __VA_ARGS__))) \ () #endif /* CCAN_CPPMAGIC_H */