]> git.ozlabs.org Git - ccan/blobdiff - ccan/cppmagic/cppmagic.h
cppmagic: Allow multiple and deferred evaluation
[ccan] / ccan / cppmagic / cppmagic.h
index f29e0ec6cee39b39114f3849dadce50d00a2f6e3..8acbba71a68d4e97c849831f7b5abd55bcc4f1fe 100644 (file)
  */
 #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()()
+
 #endif /* CCAN_CPPMAGIC_H */