#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 */
#define TESTRECURSE() R CPPMAGIC_DEFER1(_TESTRECURSE)()()
#define _TESTRECURSE() TESTRECURSE
+#define TESTMAP1(x) <<x>>
+
+#define TESTMAP2(x) [[ x
+#define TESTMAP3(x) x ]]
+
+#define TEST2MAP(x, y) x ** y
+
int main(void)
{
- plan_tests(27);
+ plan_tests(42);
CHECK1(CPPMAGIC_NOTHING(), "");
CHECK1(CPPMAGIC_GLUE2(a, b), "ab");
CHECK1(CPPMAGIC_EVAL1(TESTRECURSE()), "R R R _TESTRECURSE ()()");
CHECK1(CPPMAGIC_EVAL2(TESTRECURSE()), "R R R R R _TESTRECURSE ()()");
+ CHECK1(CPPMAGIC_MAP(TESTMAP1), "");
+ CHECK1(CPPMAGIC_MAP(TESTMAP1, a), "<<a>>");
+ CHECK1(CPPMAGIC_MAP(TESTMAP1, a, b), "<<a>> , <<b>>");
+ CHECK1(CPPMAGIC_MAP(TESTMAP1, a, b, c), "<<a>> , <<b>> , <<c>>");
+
+ CHECK1(CPPMAGIC_2MAP(TEST2MAP), "");
+ CHECK1(CPPMAGIC_2MAP(TEST2MAP, a, 1), "a ** 1");
+ CHECK1(CPPMAGIC_2MAP(TEST2MAP, a, 1, b, 2), "a ** 1 , b ** 2");
+
+ CHECK1(CPPMAGIC_JOIN(;), "");
+ CHECK1(CPPMAGIC_JOIN(;, a), "a");
+ CHECK1(CPPMAGIC_JOIN(;, a, b), "a ; b");
+ CHECK1(CPPMAGIC_JOIN(;, a, b, c), "a ; b ; c");
+
+ /* Check chaining of MAPs */
+ CHECK1(CPPMAGIC_MAP(TESTMAP2, CPPMAGIC_MAP(TESTMAP3)), "");
+ CHECK1(CPPMAGIC_MAP(TESTMAP2, CPPMAGIC_MAP(TESTMAP3, a)), "[[ a ]]");
+ CHECK1(CPPMAGIC_MAP(TESTMAP2, CPPMAGIC_MAP(TESTMAP3, a, b)),
+ "[[ a ]] , [[ b ]]");
+ CHECK1(CPPMAGIC_MAP(TESTMAP2, CPPMAGIC_MAP(TESTMAP3, a, b, c)),
+ "[[ a ]] , [[ b ]] , [[ c ]]");
+
/* This exits depending on whether all tests passed */
return exit_status();
}