github.com/256dpi/max-go@v0.7.0/lib/max/ext_preprocessor.h (about) 1 /* 2 Copyright (c) 2011, Stefan Reinalter 3 4 This software is provided 'as-is', without any express or implied 5 warranty. In no event will the authors be held liable for any damages 6 arising from the use of this software. 7 8 Permission is granted to anyone to use this software for any purpose, 9 including commercial applications, and to alter it and redistribute it 10 freely, subject to the following restrictions: 11 12 1. The origin of this software must not be misrepresented; you must not 13 claim that you wrote the original software. If you use this software 14 in a product, an acknowledgment in the product documentation would be 15 appreciated but is not required. 16 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 20 3. This notice may not be removed or altered from any source 21 distribution. 22 */ 23 24 // ext_preprocessor.h: 25 // - derived from preprocessor magic here: http://altdevblogaday.com/wp-content/uploads/2011/10/Assert.txt 26 // - macros changed from ME_PP_* to C74_* to avoid any name conflicts 27 28 #ifndef _EXT_PREPROCESSOR_H_ 29 #define _EXT_PREPROCESSOR_H_ 30 31 #define C74_EXPAND(x) x 32 33 /// concatenates tokens, even when the tokens are macros themselves 34 #define C74_JOIN_HELPER_HELPER(_0, _1) _0##_1 35 #define C74_JOIN_HELPER(_0, _1) C74_JOIN_HELPER_HELPER(_0, _1) 36 #define C74_JOIN_IMPL(_0, _1) C74_JOIN_HELPER(_0, _1) 37 38 #define C74_JOIN_2(_0, _1) C74_JOIN_IMPL(_0, _1) 39 #define C74_JOIN_3(_0, _1, _2) C74_JOIN_2(C74_JOIN_2(_0, _1), _2) 40 #define C74_JOIN_4(_0, _1, _2, _3) C74_JOIN_2(C74_JOIN_3(_0, _1, _2), _3) 41 #define C74_JOIN_5(_0, _1, _2, _3, _4) C74_JOIN_2(C74_JOIN_4(_0, _1, _2, _3), _4) 42 #define C74_JOIN_6(_0, _1, _2, _3, _4, _5) C74_JOIN_2(C74_JOIN_5(_0, _1, _2, _3, _4), _5) 43 #define C74_JOIN_7(_0, _1, _2, _3, _4, _5, _6) C74_JOIN_2(C74_JOIN_6(_0, _1, _2, _3, _4, _5), _6) 44 #define C74_JOIN_8(_0, _1, _2, _3, _4, _5, _6, _7) C74_JOIN_2(C74_JOIN_7(_0, _1, _2, _3, _4, _5, _6), _7) 45 #define C74_JOIN_9(_0, _1, _2, _3, _4, _5, _6, _7, _8) C74_JOIN_2(C74_JOIN_8(_0, _1, _2, _3, _4, _5, _6, _7), _8) 46 #define C74_JOIN_10(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9) C74_JOIN_2(C74_JOIN_9(_0, _1, _2, _3, _4, _5, _6, _7, _8), _9) 47 #define C74_JOIN_11(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) C74_JOIN_2(C74_JOIN_10(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9), _10) 48 #define C74_JOIN_12(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11) C74_JOIN_2(C74_JOIN_11(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10), _11) 49 #define C74_JOIN_13(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12) C74_JOIN_2(C74_JOIN_12(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11), _12) 50 #define C74_JOIN_14(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13) C74_JOIN_2(C74_JOIN_13(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12), _13) 51 #define C74_JOIN_15(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14) C74_JOIN_2(C74_JOIN_14(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13), _14) 52 #define C74_JOIN_16(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15) C74_JOIN_2(C74_JOIN_15(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14), _15) 53 54 55 /// chooses a value based on a condition 56 #define C74_IF_0(t, f) f 57 #define C74_IF_1(t, f) t 58 #define C74_IF(cond, t, f) C74_JOIN_2(C74_IF_, C74_TO_BOOL(cond))(t, f) 59 60 61 /// converts a condition into a boolean 0 (=false) or 1 (=true) 62 #define C74_TO_BOOL_0 0 63 #define C74_TO_BOOL_1 1 64 #define C74_TO_BOOL_2 1 65 #define C74_TO_BOOL_3 1 66 #define C74_TO_BOOL_4 1 67 #define C74_TO_BOOL_5 1 68 #define C74_TO_BOOL_6 1 69 #define C74_TO_BOOL_7 1 70 #define C74_TO_BOOL_8 1 71 #define C74_TO_BOOL_9 1 72 #define C74_TO_BOOL_10 1 73 #define C74_TO_BOOL_11 1 74 #define C74_TO_BOOL_12 1 75 #define C74_TO_BOOL_13 1 76 #define C74_TO_BOOL_14 1 77 #define C74_TO_BOOL_15 1 78 #define C74_TO_BOOL_16 1 79 80 #define C74_TO_BOOL(x) C74_JOIN_2(C74_TO_BOOL_, x) 81 82 83 /// Returns 1 if the arguments to the variadic macro are separated by a comma, 0 otherwise. 84 #define C74_HAS_COMMA(...) C74_HAS_COMMA_EVAL(C74_HAS_COMMA_ARGS(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0)) 85 #define C74_HAS_COMMA_EVAL(...) __VA_ARGS__ 86 #define C74_HAS_COMMA_ARGS(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, ...) _16 87 88 89 /// Returns 1 if the argument list to the variadic macro is empty, 0 otherwise. 90 #define C74_IS_EMPTY(...) \ 91 C74_HAS_COMMA \ 92 ( \ 93 C74_JOIN_5 \ 94 ( \ 95 C74_IS_EMPTY_CASE_, \ 96 C74_HAS_COMMA(__VA_ARGS__), \ 97 C74_HAS_COMMA(C74_IS_EMPTY_BRACKET_TEST __VA_ARGS__), \ 98 C74_HAS_COMMA(__VA_ARGS__ (~)), \ 99 C74_HAS_COMMA(C74_IS_EMPTY_BRACKET_TEST __VA_ARGS__ (~)) \ 100 ) \ 101 ) 102 103 #define C74_IS_EMPTY_CASE_0001 , 104 #define C74_IS_EMPTY_BRACKET_TEST(...) , 105 106 107 // C74_VA_NUM_ARGS() is a very nifty macro to retrieve the number of arguments handed to a variable-argument macro. 108 // unfortunately, VS 2010 still has this preprocessor bug which treats a __VA_ARGS__ argument as being one single parameter: 109 // https://connect.microsoft.com/VisualStudio/feedback/details/521844/variadic-macro-treating-va-args-as-a-single-parameter-for-other-macros#details 110 #if _MSC_VER >= 1400 111 # define C74_VA_NUM_ARGS_HELPER(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, N, ...) N 112 # define C74_VA_NUM_ARGS_REVERSE_SEQUENCE 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 113 # define C74_VA_NUM_ARGS_LEFT ( 114 # define C74_VA_NUM_ARGS_RIGHT ) 115 # define C74_VA_NUM_ARGS(...) C74_VA_NUM_ARGS_HELPER C74_VA_NUM_ARGS_LEFT __VA_ARGS__, C74_VA_NUM_ARGS_REVERSE_SEQUENCE C74_VA_NUM_ARGS_RIGHT 116 #else 117 # define C74_VA_NUM_ARGS(...) C74_VA_NUM_ARGS_HELPER(__VA_ARGS__, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1) 118 # define C74_VA_NUM_ARGS_HELPER(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, N, ...) N 119 #endif 120 121 // C74_NUM_ARGS correctly handles the case of 0 arguments 122 #define C74_NUM_ARGS(...) C74_IF(C74_IS_EMPTY(__VA_ARGS__), 0, C74_VA_NUM_ARGS(__VA_ARGS__)) 123 124 125 // C74_PASS_ARGS passes __VA_ARGS__ as multiple parameters to another macro, working around the following bug: 126 // https://connect.microsoft.com/VisualStudio/feedback/details/521844/variadic-macro-treating-va-args-as-a-single-parameter-for-other-macros#details 127 #if _MSC_VER >= 1400 128 # define C74_PASS_ARGS_LEFT ( 129 # define C74_PASS_ARGS_RIGHT ) 130 # define C74_PASS_ARGS(...) C74_PASS_ARGS_LEFT __VA_ARGS__ C74_PASS_ARGS_RIGHT 131 #else 132 # define C74_PASS_ARGS(...) (__VA_ARGS__) 133 #endif 134 135 136 /// Expand any number of arguments into a list of operations called with those arguments 137 #define C74_EXPAND_ARGS_0(op, empty) 138 #define C74_EXPAND_ARGS_1(op, a1) op(a1, 0) 139 #define C74_EXPAND_ARGS_2(op, a1, a2) op(a1, 0) op(a2, 1) 140 #define C74_EXPAND_ARGS_3(op, a1, a2, a3) op(a1, 0) op(a2, 1) op(a3, 2) 141 #define C74_EXPAND_ARGS_4(op, a1, a2, a3, a4) op(a1, 0) op(a2, 1) op(a3, 2) op(a4, 3) 142 #define C74_EXPAND_ARGS_5(op, a1, a2, a3, a4, a5) op(a1, 0) op(a2, 1) op(a3, 2) op(a4, 3) op(a5, 4) 143 #define C74_EXPAND_ARGS_6(op, a1, a2, a3, a4, a5, a6) op(a1, 0) op(a2, 1) op(a3, 2) op(a4, 3) op(a5, 4) op(a6, 5) 144 #define C74_EXPAND_ARGS_7(op, a1, a2, a3, a4, a5, a6, a7) op(a1, 0) op(a2, 1) op(a3, 2) op(a4, 3) op(a5, 4) op(a6, 5) op(a7, 6) 145 #define C74_EXPAND_ARGS_8(op, a1, a2, a3, a4, a5, a6, a7, a8) op(a1, 0) op(a2, 1) op(a3, 2) op(a4, 3) op(a5, 4) op(a6, 5) op(a7, 6) op(a8, 7) 146 #define C74_EXPAND_ARGS_9(op, a1, a2, a3, a4, a5, a6, a7, a8, a9) op(a1, 0) op(a2, 1) op(a3, 2) op(a4, 3) op(a5, 4) op(a6, 5) op(a7, 6) op(a8, 7) op(a9, 8) 147 #define C74_EXPAND_ARGS_10(op, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) op(a1, 0) op(a2, 1) op(a3, 2) op(a4, 3) op(a5, 4) op(a6, 5) op(a7, 6) op(a8, 7) op(a9, 8) op(a10, 9) 148 #define C74_EXPAND_ARGS_11(op, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) op(a1, 0) op(a2, 1) op(a3, 2) op(a4, 3) op(a5, 4) op(a6, 5) op(a7, 6) op(a8, 7) op(a9, 8) op(a10, 9) op(a11, 10) 149 #define C74_EXPAND_ARGS_12(op, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) op(a1, 0) op(a2, 1) op(a3, 2) op(a4, 3) op(a5, 4) op(a6, 5) op(a7, 6) op(a8, 7) op(a9, 8) op(a10, 9) op(a11, 10) op(a12, 11) 150 #define C74_EXPAND_ARGS_13(op, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) op(a1, 0) op(a2, 1) op(a3, 2) op(a4, 3) op(a5, 4) op(a6, 5) op(a7, 6) op(a8, 7) op(a9, 8) op(a10, 9) op(a11, 10) op(a12, 11) op(a13, 12) 151 #define C74_EXPAND_ARGS_14(op, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) op(a1, 0) op(a2, 1) op(a3, 2) op(a4, 3) op(a5, 4) op(a6, 5) op(a7, 6) op(a8, 7) op(a9, 8) op(a10, 9) op(a11, 10) op(a12, 11) op(a13, 12) op(a14, 13) 152 #define C74_EXPAND_ARGS_15(op, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) op(a1, 0) op(a2, 1) op(a3, 2) op(a4, 3) op(a5, 4) op(a6, 5) op(a7, 6) op(a8, 7) op(a9, 8) op(a10, 9) op(a11, 10) op(a12, 11) op(a13, 12) op(a14, 13) op(a15, 14) 153 #define C74_EXPAND_ARGS_16(op, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16) op(a1, 0) op(a2, 1) op(a3, 2) op(a4, 3) op(a5, 4) op(a6, 5) op(a7, 6) op(a8, 7) op(a9, 8) op(a10, 9) op(a11, 10) op(a12, 11) op(a13, 12) op(a14, 13) op(a15, 14) op(a16, 15) 154 155 #define C74_EXPAND_ARGS(op, ...) C74_JOIN_2(C74_EXPAND_ARGS_, C74_NUM_ARGS(__VA_ARGS__)) C74_PASS_ARGS(op, __VA_ARGS__) 156 157 158 /// Turns any legal C++ expression into nothing 159 #define C74_UNUSED_IMPL(symExpr, n) , (void)sizeof(symExpr) 160 #define C74_UNUSED(...) (void)sizeof(true) C74_EXPAND_ARGS C74_PASS_ARGS(C74_UNUSED_IMPL, __VA_ARGS__) 161 162 #define C74_VARFUN_0(VARFUN_IMPL) VARFUN_IMPL((void*)(t_ptr_int)0, (void*)(t_ptr_int)0, (void*)(t_ptr_int)0, (void*)(t_ptr_int)0, (void*)(t_ptr_int)0, (void*)(t_ptr_int)0, (void*)(t_ptr_int)0, (void*)(t_ptr_int)0, (void*)(t_ptr_int)0, (void*)(t_ptr_int)0) 163 #define C74_VARFUN_1(VARFUN_IMPL, p1) VARFUN_IMPL((void*)(t_ptr_int)(p1), (void*)(t_ptr_int)0, (void*)(t_ptr_int)0, (void*)(t_ptr_int)0, (void*)(t_ptr_int)0, (void*)(t_ptr_int)0, (void*)(t_ptr_int)0, (void*)(t_ptr_int)0, (void*)(t_ptr_int)0, (void*)(t_ptr_int)0) 164 #define C74_VARFUN_2(VARFUN_IMPL, p1, p2) VARFUN_IMPL((void*)(t_ptr_int)(p1), (void*)(t_ptr_int)(p2), (void*)(t_ptr_int)0, (void*)(t_ptr_int)0, (void*)(t_ptr_int)0, (void*)(t_ptr_int)0, (void*)(t_ptr_int)0, (void*)(t_ptr_int)0, (void*)(t_ptr_int)0, (void*)(t_ptr_int)0) 165 #define C74_VARFUN_3(VARFUN_IMPL, p1, p2, p3) VARFUN_IMPL((void*)(t_ptr_int)(p1), (void*)(t_ptr_int)(p2), (void*)(t_ptr_int)(p3), (void*)(t_ptr_int)0, (void*)(t_ptr_int)0, (void*)(t_ptr_int)0, (void*)(t_ptr_int)0, (void*)(t_ptr_int)0, (void*)(t_ptr_int)0, (void*)(t_ptr_int)0) 166 #define C74_VARFUN_4(VARFUN_IMPL, p1, p2, p3, p4) VARFUN_IMPL((void*)(t_ptr_int)(p1), (void*)(t_ptr_int)(p2), (void*)(t_ptr_int)(p3), (void*)(t_ptr_int)(p4), (void*)(t_ptr_int)0, (void*)(t_ptr_int)0, (void*)(t_ptr_int)0, (void*)(t_ptr_int)0, (void*)(t_ptr_int)0, (void*)(t_ptr_int)0) 167 #define C74_VARFUN_5(VARFUN_IMPL, p1, p2, p3, p4, p5) VARFUN_IMPL((void*)(t_ptr_int)(p1), (void*)(t_ptr_int)(p2), (void*)(t_ptr_int)(p3), (void*)(t_ptr_int)(p4), (void*)(t_ptr_int)(p5), (void*)(t_ptr_int)0, (void*)(t_ptr_int)0, (void*)(t_ptr_int)0, (void*)(t_ptr_int)0, (void*)(t_ptr_int)0) 168 #define C74_VARFUN_6(VARFUN_IMPL, p1, p2, p3, p4, p5, p6) VARFUN_IMPL((void*)(t_ptr_int)(p1), (void*)(t_ptr_int)(p2), (void*)(t_ptr_int)(p3), (void*)(t_ptr_int)(p4), (void*)(t_ptr_int)(p5), (void*)(t_ptr_int)(p6), (void*)(t_ptr_int)0, (void*)(t_ptr_int)0, (void*)(t_ptr_int)0, (void*)(t_ptr_int)0) 169 #define C74_VARFUN_7(VARFUN_IMPL, p1, p2, p3, p4, p5, p6, p7) VARFUN_IMPL((void*)(t_ptr_int)(p1), (void*)(t_ptr_int)(p2), (void*)(t_ptr_int)(p3), (void*)(t_ptr_int)(p4), (void*)(t_ptr_int)(p5), (void*)(t_ptr_int)(p6), (void*)(t_ptr_int)(p7), (void*)(t_ptr_int)0, (void*)(t_ptr_int)0, (void*)(t_ptr_int)0) 170 #define C74_VARFUN_8(VARFUN_IMPL, p1, p2, p3, p4, p5, p6, p7, p8) VARFUN_IMPL((void*)(t_ptr_int)(p1), (void*)(t_ptr_int)(p2), (void*)(t_ptr_int)(p3), (void*)(t_ptr_int)(p4), (void*)(t_ptr_int)(p5), (void*)(t_ptr_int)(p6), (void*)(t_ptr_int)(p7), (void*)(t_ptr_int)(p8), (void*)(t_ptr_int)0, (void*)(t_ptr_int)0) 171 #define C74_VARFUN_9(VARFUN_IMPL, p1, p2, p3, p4, p5, p6, p7, p8, p9) VARFUN_IMPL((void*)(t_ptr_int)(p1), (void*)(t_ptr_int)(p2), (void*)(t_ptr_int)(p3), (void*)(t_ptr_int)(p4), (void*)(t_ptr_int)(p5), (void*)(t_ptr_int)(p6), (void*)(t_ptr_int)(p7), (void*)(t_ptr_int)(p8), (void*)(t_ptr_int)(p9), (void*)(t_ptr_int)0) 172 #define C74_VARFUN_10(VARFUN_IMPL, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10) VARFUN_IMPL((void*)(t_ptr_int)(p1), (void*)(t_ptr_int)(p2), (void*)(t_ptr_int)(p3), (void*)(t_ptr_int)(p4), (void*)(t_ptr_int)(p5), (void*)(t_ptr_int)(p6), (void*)(t_ptr_int)(p7), (void*)(t_ptr_int)(p8), (void*)(t_ptr_int)(p9), (void*)(t_ptr_int)(p10)) 173 #define C74_VARFUN_11(VARFUN_IMPL, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11) VARFUN_IMPL((void*)(t_ptr_int)(p1), (void*)(t_ptr_int)(p2), (void*)(t_ptr_int)(p3), (void*)(t_ptr_int)(p4), (void*)(t_ptr_int)(p5), (void*)(t_ptr_int)(p6), (void*)(t_ptr_int)(p7), (void*)(t_ptr_int)(p8), (void*)(t_ptr_int)(p9), (void*)(t_ptr_int)(p10), (void*)(t_ptr_int)(p11)) 174 175 // C74_VARFUN supports calling a function via a macro in a way that looks like a var args function 176 // - VARFUN_IMPL: is a function that takes 10 void* parameters 177 // - there must be at least one parameter passed after the VARFUN_IMPL 178 // - each parameter passed is cast first to a t_ptr_int and then to a void* 179 // this is done to sign-extend and promote shorter integer types 180 // - see object_method for an example 181 182 #if _MSC_VER >= 1400 183 #define C74_VARFUN(VARFUN_IMPL, ...) C74_JOIN_2(C74_VARFUN_, C74_NUM_ARGS(__VA_ARGS__)) C74_PASS_ARGS(VARFUN_IMPL, __VA_ARGS__) 184 #else 185 #define C74_VARFUN(VARFUN_IMPL, ...) C74_JOIN_2(C74_VARFUN_, C74_NUM_ARGS(__VA_ARGS__))( VARFUN_IMPL, __VA_ARGS__ ) 186 #endif 187 188 #endif // #ifndef _EXT_PREPROCESSOR_H_