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_