cppmagic: New module
authorDavid Gibson <david@gibson.dropbear.id.au>
Tue, 26 Jan 2016 09:51:57 +0000 (20:51 +1100)
committerDavid Gibson <david@gibson.dropbear.id.au>
Wed, 3 Feb 2016 22:44:13 +0000 (09:44 +1100)
A module for some of the awesome / horrifying techniques described at:
    http://jhnet.co.uk/articles/cpp_magic
    https://github.com/pfultz2/Cloak/wiki/C-Preprocessor-tricks,-tips,-and-idioms

Start off with just some simple things.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
ccan/cppmagic/LICENSE [new symlink]
ccan/cppmagic/_info [new file with mode: 0644]
ccan/cppmagic/cppmagic.h [new file with mode: 0644]
ccan/cppmagic/test/run.c [new file with mode: 0644]

diff --git a/ccan/cppmagic/LICENSE b/ccan/cppmagic/LICENSE
new file mode 120000 (symlink)
index 0000000..2354d12
--- /dev/null
@@ -0,0 +1 @@
+../../licenses/BSD-MIT
\ No newline at end of file
diff --git a/ccan/cppmagic/_info b/ccan/cppmagic/_info
new file mode 100644 (file)
index 0000000..aad394b
--- /dev/null
@@ -0,0 +1,30 @@
+#include "config.h"
+#include <stdio.h>
+#include <string.h>
+
+/**
+ * cppmagic - Abuse of the C preprocessor
+ *
+ * This contains a bunch of fancy macro techniques such as
+ * preprocessor-time evaluated conditionals and (quasi) recursion and
+ * iteration.
+ *
+ * It's based on these articles:
+ *  - http://jhnet.co.uk/articles/cpp_magic
+ *  - https://github.com/pfultz2/Cloak/wiki/C-Preprocessor-tricks,-tips,-and-idioms
+ * and code from the Boost C++ library.
+ *
+ * License: BSD-MIT
+ */
+int main(int argc, char *argv[])
+{
+       /* Expect exactly one argument */
+       if (argc != 2)
+               return 1;
+
+       if (strcmp(argv[1], "depends") == 0) {
+               return 0;
+       }
+
+       return 1;
+}
diff --git a/ccan/cppmagic/cppmagic.h b/ccan/cppmagic/cppmagic.h
new file mode 100644 (file)
index 0000000..f29e0ec
--- /dev/null
@@ -0,0 +1,42 @@
+/* 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_
+
+#endif /* CCAN_CPPMAGIC_H */
diff --git a/ccan/cppmagic/test/run.c b/ccan/cppmagic/test/run.c
new file mode 100644 (file)
index 0000000..0ed830d
--- /dev/null
@@ -0,0 +1,34 @@
+#include "config.h"
+
+#include <string.h>
+
+#include <ccan/cppmagic/cppmagic.h>
+#include <ccan/tap/tap.h>
+
+static inline void check1(const char *orig, const char *expand,
+                         const char *match)
+{
+       ok(strcmp(expand, match) == 0,
+          "%s => %s : %s", orig, expand, match);
+}
+
+#define CHECK1(orig, match) \
+       check1(#orig, CPPMAGIC_STRINGIFY(orig), match)
+
+int main(void)
+{
+       plan_tests(7);
+
+       CHECK1(CPPMAGIC_NOTHING(), "");
+       CHECK1(CPPMAGIC_GLUE2(a, b), "ab");
+
+       CHECK1(CPPMAGIC_1ST(a), "a");
+       CHECK1(CPPMAGIC_1ST(a, b), "a");
+       CHECK1(CPPMAGIC_1ST(a, b, c), "a");
+
+       CHECK1(CPPMAGIC_2ND(a, b), "b");
+       CHECK1(CPPMAGIC_2ND(a, b, c), "b");
+
+       /* This exits depending on whether all tests passed */
+       return exit_status();
+}