From: David Gibson Date: Tue, 26 Jan 2016 09:51:57 +0000 (+1100) Subject: cppmagic: New module X-Git-Url: http://git.ozlabs.org/?p=ccan;a=commitdiff_plain;h=ff71198b4e75fcaaedad34a4e362a3982a936e3e cppmagic: New module 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 --- diff --git a/ccan/cppmagic/LICENSE b/ccan/cppmagic/LICENSE new file mode 120000 index 00000000..2354d129 --- /dev/null +++ b/ccan/cppmagic/LICENSE @@ -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 index 00000000..aad394b9 --- /dev/null +++ b/ccan/cppmagic/_info @@ -0,0 +1,30 @@ +#include "config.h" +#include +#include + +/** + * 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 index 00000000..f29e0ec6 --- /dev/null +++ b/ccan/cppmagic/cppmagic.h @@ -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 index 00000000..0ed830d8 --- /dev/null +++ b/ccan/cppmagic/test/run.c @@ -0,0 +1,34 @@ +#include "config.h" + +#include + +#include +#include + +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(); +}