Rusty Russell
8 years ago
21 changed files with 392 additions and 100 deletions
@ -1,3 +1,3 @@ |
|||||
CCAN imported from http://ccodearchive.net. |
CCAN imported from http://ccodearchive.net. |
||||
|
|
||||
CCAN version: init-2207-ge0b86f0 |
CCAN version: init-2247-g5e37a0f |
||||
|
@ -0,0 +1 @@ |
|||||
|
../../licenses/BSD-MIT |
@ -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; |
||||
|
} |
@ -0,0 +1,191 @@ |
|||||
|
/* 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 */ |
@ -0,0 +1,92 @@ |
|||||
|
#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) |
||||
|
|
||||
|
#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(42); |
||||
|
|
||||
|
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"); |
||||
|
|
||||
|
CHECK1(CPPMAGIC_ISZERO(0), "1"); |
||||
|
CHECK1(CPPMAGIC_ISZERO(1), "0"); |
||||
|
CHECK1(CPPMAGIC_ISZERO(123), "0"); |
||||
|
CHECK1(CPPMAGIC_ISZERO(abc), "0"); |
||||
|
|
||||
|
CHECK1(CPPMAGIC_NONZERO(0), "0"); |
||||
|
CHECK1(CPPMAGIC_NONZERO(1), "1"); |
||||
|
CHECK1(CPPMAGIC_NONZERO(123), "1"); |
||||
|
CHECK1(CPPMAGIC_NONZERO(abc), "1"); |
||||
|
|
||||
|
CHECK1(CPPMAGIC_NONEMPTY(), "0"); |
||||
|
CHECK1(CPPMAGIC_NONEMPTY(0), "1"); |
||||
|
CHECK1(CPPMAGIC_NONEMPTY(a, b, c), "1"); |
||||
|
|
||||
|
CHECK1(CPPMAGIC_ISEMPTY(), "1"); |
||||
|
CHECK1(CPPMAGIC_ISEMPTY(0), "0"); |
||||
|
CHECK1(CPPMAGIC_ISEMPTY(a, b, c), "0"); |
||||
|
|
||||
|
CHECK1(CPPMAGIC_IFELSE(0)(abc)(def), "def"); |
||||
|
CHECK1(CPPMAGIC_IFELSE(1)(abc)(def), "abc"); |
||||
|
CHECK1(CPPMAGIC_IFELSE(not zero)(abc)(def), "abc"); |
||||
|
|
||||
|
CHECK1(TESTRECURSE(), "R R _TESTRECURSE ()()"); |
||||
|
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(); |
||||
|
} |
@ -0,0 +1 @@ |
|||||
|
../../licenses/CC0 |
Loading…
Reference in new issue