1 | #define M_C2I(a, ...) a ## __VA_ARGS__
|
---|
2 | #define M_C(a, ...) M_C2I(a, __VA_ARGS__)
|
---|
3 | #define M_C3I(a, b, ...) a ## b ## __VA_ARGS__
|
---|
4 | #define M_C3(a, b, ...) M_C3I(a ,b, __VA_ARGS__)
|
---|
5 |
|
---|
6 | #define M_RETI_ARG2(a, b, ...) b
|
---|
7 | #define M_RET_ARG2(...) M_RETI_ARG2(__VA_ARGS__)
|
---|
8 | #define M_RETI_ARG27(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,aa, ...) aa
|
---|
9 | #define M_RET_ARG27(...) M_RETI_ARG27(__VA_ARGS__)
|
---|
10 |
|
---|
11 | #define M_TOBOOLI_0 1, 0,
|
---|
12 | #define M_BOOL(x) M_RET_ARG2(M_C(M_TOBOOLI_, x), 1, useless)
|
---|
13 |
|
---|
14 | #define M_IFI_0(true_macro, ...) __VA_ARGS__
|
---|
15 | #define M_IFI_1(true_macro, ...) true_macro
|
---|
16 | #define M_IF(c) M_C(M_IFI_, M_BOOL(c))
|
---|
17 |
|
---|
18 | #define M_FLAT(...) __VA_ARGS__
|
---|
19 | #define M_INVI_0 1
|
---|
20 | #define M_INVI_1 0
|
---|
21 | #define M_INV(x) M_C(M_INVI_, x)
|
---|
22 |
|
---|
23 | #define M_ANDI_00 0
|
---|
24 | #define M_ANDI_01 0
|
---|
25 | #define M_ANDI_10 0
|
---|
26 | #define M_ANDI_11 1
|
---|
27 | #define M_AND(x,y) M_C3(M_ANDI_, x, y)
|
---|
28 |
|
---|
29 | #define M_ORI_00 0
|
---|
30 | #define M_ORI_01 1
|
---|
31 | #define M_ORI_10 1
|
---|
32 | #define M_ORI_11 1
|
---|
33 | #define M_OR(x,y) M_C3(M_ORI_, x, y)
|
---|
34 |
|
---|
35 | #define M_COMMA_P(...) M_RET_ARG27(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, useless)
|
---|
36 |
|
---|
37 | #define M_EMPTYI_DETECT(...) 0, 1,
|
---|
38 | #define M_EMPTYI_P_C1(...) M_COMMA_P(M_EMPTYI_DETECT __VA_ARGS__ ())
|
---|
39 | #define M_EMPTYI_P_C2(...) M_COMMA_P(M_EMPTYI_DETECT __VA_ARGS__)
|
---|
40 | #define M_EMPTYI_P_C3(...) M_COMMA_P(__VA_ARGS__ () )
|
---|
41 | #define M_EMPTY_P(...) M_AND(M_EMPTYI_P_C1(__VA_ARGS__), M_INV(M_OR(M_OR(M_EMPTYI_P_C2(__VA_ARGS__), M_COMMA_P(__VA_ARGS__)),M_EMPTYI_P_C3(__VA_ARGS__))))
|
---|
42 | #define M_APPLY_FUNC2B(func, arg1, arg2) \
|
---|
43 | M_IF(M_EMPTY_P(arg2))(,func(arg1, arg2))
|
---|
44 | #define M_MAP2B_0(func, data, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z,...) \
|
---|
45 | M_APPLY_FUNC2B(func, data, a) M_APPLY_FUNC2B(func, data, b) M_APPLY_FUNC2B(func, data, c) \
|
---|
46 | M_APPLY_FUNC2B(func, data, d) M_APPLY_FUNC2B(func, data, e) M_APPLY_FUNC2B(func, data, f) \
|
---|
47 | M_APPLY_FUNC2B(func, data, g) M_APPLY_FUNC2B(func, data, h) M_APPLY_FUNC2B(func, data, i) \
|
---|
48 | M_APPLY_FUNC2B(func, data, j) M_APPLY_FUNC2B(func, data, k) M_APPLY_FUNC2B(func, data, l) \
|
---|
49 | M_APPLY_FUNC2B(func, data, m) M_APPLY_FUNC2B(func, data, n) M_APPLY_FUNC2B(func, data, o) \
|
---|
50 | M_APPLY_FUNC2B(func, data, p) M_APPLY_FUNC2B(func, data, q) M_APPLY_FUNC2B(func, data, r) \
|
---|
51 | M_APPLY_FUNC2B(func, data, s) M_APPLY_FUNC2B(func, data, t) M_APPLY_FUNC2B(func, data, u) \
|
---|
52 | M_APPLY_FUNC2B(func, data, v) M_APPLY_FUNC2B(func, data, w) M_APPLY_FUNC2B(func, data, x) \
|
---|
53 | M_APPLY_FUNC2B(func, data, y) M_APPLY_FUNC2B(func, data, z)
|
---|
54 | #define M_MAP2B(f, ...) M_MAP2B_0(f, __VA_ARGS__, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , )
|
---|
55 | #define M_INIT_INIT(a) ,a,
|
---|
56 |
|
---|
57 | #define M_GET_METHOD(method, method_default, ...) \
|
---|
58 | M_RET_ARG2 (M_MAP2B(M_C, M_C3(M_, method, _), __VA_ARGS__), method_default,)
|
---|
59 |
|
---|
60 | #define M_TEST_METHOD_P(method, oplist) \
|
---|
61 | M_BOOL(M_GET_METHOD (method, 0, M_FLAT oplist))
|
---|
62 |
|
---|
63 | #define TRUE 1
|
---|
64 | #define TEST1(n) \
|
---|
65 | M_IF(n)(ok,nok)
|
---|
66 | #define TEST2(op) \
|
---|
67 | M_TEST_METHOD_P(INIT, op)
|
---|
68 | #define TEST3(op) \
|
---|
69 | M_IF(M_TEST_METHOD_P(INIT, op))(ok, nok)
|
---|
70 | #define TEST4(op) \
|
---|
71 | TEST1(TEST2(op))
|
---|
72 | #define KO(a) ((void)1)
|
---|
73 |
|
---|
74 | /* This checks that the various expansions that ultimately lead to
|
---|
75 | something like 'KO(arg,arg)', where 'KO' comes from a macro
|
---|
76 | expansion reducing from a large macro chain do not are regarded
|
---|
77 | as funclike macro invocation of KO. E.g. X93 and X94 expand to 'KO',
|
---|
78 | but X95 must not consume the (a,b) arguments outside the M_IF()
|
---|
79 | invocation to reduce the 'KO' macro to an invocation. Instead
|
---|
80 | X95 should reduce via M_IF(KO)(a,b) to 'a'.
|
---|
81 |
|
---|
82 | The other lines here are variations on this scheme, with X1 to
|
---|
83 | X6 coming from the bug report at
|
---|
84 | http://lists.nongnu.org/archive/html/tinycc-devel/2017-07/msg00017.html */
|
---|
85 | X92 M_IF(KO)
|
---|
86 | X93 M_GET_METHOD(INIT, 0, INIT(KO))
|
---|
87 | X94 M_GET_METHOD(INIT, 0, M_FLAT (INIT(KO)))
|
---|
88 | X95 M_IF(M_GET_METHOD(INIT, 0, INIT(KO)))(a,b)
|
---|
89 | X96 M_IF(M_GET_METHOD(INIT, 0, M_FLAT (INIT(KO))))
|
---|
90 | X97 M_IF(M_GET_METHOD(INIT, 0, M_FLAT (INIT(KO))))(ok,nok)
|
---|
91 | X98 (M_TEST_METHOD_P(INIT, (INIT(KO))))(ok, nok)
|
---|
92 | X99 M_IF(M_TEST_METHOD_P(INIT, (INIT(KO))))(ok, nok)
|
---|
93 | // test begins
|
---|
94 | X1 TEST1(TRUE) // ==> expect ok, get ok
|
---|
95 | // First test with a token which is not a macro
|
---|
96 | X2 TEST2((INIT(ok))) // ==> expect 1, get 1
|
---|
97 | X3 TEST3((INIT(ok))) // ==> expect ok, get ok
|
---|
98 | // Then test with a token which is a macro, but should not be expanded.
|
---|
99 | X4 TEST2((INIT(KO))) // ==> expect 1, get 1
|
---|
100 | X5 TEST4(INIT(KO))
|
---|
101 | X6 TEST3((INIT(KO))) // ==> expect ok, get "error: macro 'KO' used with too many args"
|
---|