Added compiler feature detection for __VA_ARGS__ and GCC ##__VA_ARGS__

Made macro names more explicit to prevent name conflicts
This commit is contained in:
Rcmaniac25 2016-01-17 00:50:49 -05:00
parent 874ed4d328
commit 55fd60f288

View File

@ -27,16 +27,33 @@
#ifndef FREEGLUT_CALLBACK_MACROS_H #ifndef FREEGLUT_CALLBACK_MACROS_H
#define FREEGLUT_CALLBACK_MACROS_H #define FREEGLUT_CALLBACK_MACROS_H
#ifndef FREEGLUT_INTERNAL_H
#error "fg_internal.h needs to be included before this header"
#endif
/* /*
* Compiler defines: * Compiler defines:
* FG_COMPILER_SUPPORTS_GCC_VA_ARGS_HACK: if the compiler supports GCC's varadic macro implementation (AKA, ##__VA_ARGS__) * FG_COMPILER_SUPPORTS_GCC_VA_ARGS_HACK: if the compiler supports GCC's variadic macro implementation (AKA, ##__VA_ARGS__)
* FG_COMPILER_SUPPORTS_VA_ARGS: if the compiler supports varadic macros * FG_COMPILER_SUPPORTS_VA_ARGS: if the compiler supports variadic macros
*/ */
/* What supports variadic macros based off Wikipedia article on it */
#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
(defined(__GNUC__) && (__GNUC__ >= 3)) || \
(defined(__clang__)) || \
(defined(_MSC_VER) && (_MSC_VER >= 1400)) || \
(defined(__BORLANDC__) && (__BORLANDC__ >= 0x570)) || \
(defined(__SUNPRO_C) && (__SUNPRO_C >= 0x530))
#define FG_COMPILER_SUPPORTS_VA_ARGS 1
#else
#define FG_COMPILER_SUPPORTS_VA_ARGS 0
#endif
/* If __VA_ARGS__ is supported, it needs to be GCC(-like) or Clang (since Clang mimics GCC) */
#if FG_COMPILER_SUPPORTS_VA_ARGS && \
(defined(__GNUC__)) || \
(defined(__clang__))
#define FG_COMPILER_SUPPORTS_GCC_VA_ARGS_HACK 1
#else
#define FG_COMPILER_SUPPORTS_GCC_VA_ARGS_HACK 0
#endif
/* /*
* Info: * Info:
* *
@ -58,20 +75,20 @@
* There is one for GCC/Clang(/and supposedly the Intel compiler) which supports the non-standard ##__VA_ARGS__ token. The code may * There is one for GCC/Clang(/and supposedly the Intel compiler) which supports the non-standard ##__VA_ARGS__ token. The code may
* look ugly, but the result is, if this was standard, no one would ever need to open this file unless they were curious (or needed * look ugly, but the result is, if this was standard, no one would ever need to open this file unless they were curious (or needed
* more then 5 arguments for a callback, but that's trivial to add). It works by adding many fake macros to a "picker" macro * more then 5 arguments for a callback, but that's trivial to add). It works by adding many fake macros to a "picker" macro
* (PP_HAS_ARGS_IMPL2) which then indictaes which macro counter to use. As we can already use varadic macros (the VA in __VA_ARGS__), * (PP_HAS_ARGS_IMPL2) which then indictaes which macro counter to use. As we can already use variadic macros (the VA in __VA_ARGS__),
* this just becomes a "reuse the arguments*. * this just becomes a "reuse the arguments*.
* *
* The next is for any non-GCC/Clang/etc. compiler *cough* MSVC/compiler you probably shouldn't be using *cough* that supports C99 * The next is for any non-GCC/Clang/etc. compiler *cough* MSVC/compiler you probably shouldn't be using *cough* that supports C99
* by default. It requires each callback to have a specific argument count passthrough macro. The only reason there are specific * by default. It requires each callback to have a specific argument count passthrough macro. The only reason there are specific
* count macros is so that (see paraghraph below) don't need have their own set of callback macros. Ideally, there would only be * count macros is so that (see paraghraph below) don't need have their own set of callback macros. Ideally, there would only be
* ZERO and ONE_OR_MORE. This works by having callback-specific macros call a specific handler macro to return user data (ZERO) or * ZERO and ONE_OR_MORE. This works by having callback-specific macros call a specific handler macro to return user data (ZERO) or
* return one or more arguments along with userData (ONE_OR_MORE) where, with varadic macros, it just reuses the arguments. * return one or more arguments along with userData (ONE_OR_MORE) where, with variadic macros, it just reuses the arguments.
* *
* The last set is for the poor individual who has to use a compiler that doesn't support C99 by default, or may not support it at * The last set is for the poor individual who has to use a compiler that doesn't support C99 by default, or may not support it at
* all. Stuff like MSVC6... It works by having a specific-count macro that "extracts" each argument to have them reused without the * all. Stuff like MSVC6... It works by having a specific-count macro that "extracts" each argument to have them reused without the
* parathesis. * parathesis.
* *
* A note on parathesis, as earlier mentioned, if the GCC varadic macro element was standard, then instead of needing: * A note on parathesis, as earlier mentioned, if the GCC variadic macro element was standard, then instead of needing:
* *
* func EXPAND_WCB(Mouse)(( (GLUT_LEFT_BUTTON, GLUT_DOWN, 10, 30), userData)); * func EXPAND_WCB(Mouse)(( (GLUT_LEFT_BUTTON, GLUT_DOWN, 10, 30), userData));
* *
@ -84,7 +101,7 @@
* implicitly passes "userData" and only works on GCC vardiac macro supporting compilers. * implicitly passes "userData" and only works on GCC vardiac macro supporting compilers.
*/ */
#ifdef FG_COMPILER_SUPPORTS_GCC_VA_ARGS_HACK #if FG_COMPILER_SUPPORTS_GCC_VA_ARGS_HACK
/* /*
* EXPAND_WCB() is used as: * EXPAND_WCB() is used as:
@ -108,19 +125,19 @@
* should not require any modification unless additional arguments are to * should not require any modification unless additional arguments are to
* be supported. * be supported.
* *
* Supports callbacks up to 5 args (follow the pattern of PP_HAS_ARGS_IMPL2 * Supports callbacks up to 5 args (follow the pattern of
* and PP_HAS_ARGS_SOURCE to add more) * EXPAND_WCB_PP_HAS_ARGS_IMPL2 and EXPAND_WCB_PP_HAS_ARGS_SOURCE to add more)
* *
* Edit with care. * Edit with care.
*/ */
#define EXPAND_WCB_UNPARAN(...) __VA_ARGS__ #define EXPAND_WCB_UNPARAN(...) __VA_ARGS__
#define PP_HAS_ARGS_IMPL2(_0, _1, _2, _3, _4, _5, N, ...) N #define EXPAND_WCB_PP_HAS_ARGS_IMPL2(_0, _1, _2, _3, _4, _5, N, ...) N
#define PP_HAS_ARGS_SOURCE() ONE_OR_MORE, ONE_OR_MORE, ONE_OR_MORE, ONE_OR_MORE, ONE_OR_MORE, ZERO #define EXPAND_WCB_PP_HAS_ARGS_SOURCE() ONE_OR_MORE, ONE_OR_MORE, ONE_OR_MORE, ONE_OR_MORE, ONE_OR_MORE, ZERO
#define PP_HAS_ARGS_IMPL(...) PP_HAS_ARGS_IMPL2( __VA_ARGS__ ) #define EXPAND_WCB_PP_HAS_ARGS_IMPL(...) EXPAND_WCB_PP_HAS_ARGS_IMPL2( __VA_ARGS__ )
#define PP_HAS_ARGS(...) PP_HAS_ARGS_IMPL( NOT_EXIST, ##__VA_ARGS__, PP_HAS_ARGS_SOURCE() ) #define EXPAND_WCB_PP_HAS_ARGS(...) EXPAND_WCB_PP_HAS_ARGS_IMPL( NOT_EXIST, ##__VA_ARGS__, EXPAND_WCB_PP_HAS_ARGS_SOURCE() )
#define EXPAND_WCB_ZERO(args, userData) ( userData ) #define EXPAND_WCB_ZERO(args, userData) ( userData )
#define EXPAND_WCB_ONE_OR_MORE(args, userData) ( EXPAND_WCB_UNPARAN args, userData ) #define EXPAND_WCB_ONE_OR_MORE(args, userData) ( EXPAND_WCB_UNPARAN args, userData )
@ -128,7 +145,7 @@
#define EXPAND_WCB_DISAMBIGUATE2(has_args, args, userData) EXPAND_WCB_ ## has_args ( args, userData ) #define EXPAND_WCB_DISAMBIGUATE2(has_args, args, userData) EXPAND_WCB_ ## has_args ( args, userData )
#define EXPAND_WCB_DISAMBIGUATE(has_args, args, userData) EXPAND_WCB_DISAMBIGUATE2( has_args, args, userData ) #define EXPAND_WCB_DISAMBIGUATE(has_args, args, userData) EXPAND_WCB_DISAMBIGUATE2( has_args, args, userData )
#define EXPAND_WCB_UNWRAP_ARGS2(args, userData) EXPAND_WCB_DISAMBIGUATE( PP_HAS_ARGS args, args, userData ) #define EXPAND_WCB_UNWRAP_ARGS2(args, userData) EXPAND_WCB_DISAMBIGUATE( EXPAND_WCB_PP_HAS_ARGS args, args, userData )
#define EXPAND_WCB_UNWRAP_ARGS(args) EXPAND_WCB_UNWRAP_ARGS2 args #define EXPAND_WCB_UNWRAP_ARGS(args) EXPAND_WCB_UNWRAP_ARGS2 args
#define EXPAND_WCB(cbname) EXPAND_WCB_UNWRAP_ARGS #define EXPAND_WCB(cbname) EXPAND_WCB_UNWRAP_ARGS
@ -159,7 +176,7 @@
* #define EXPAND_WCB_SUB_Entry(args) EXPAND_WCB_ONE args * #define EXPAND_WCB_SUB_Entry(args) EXPAND_WCB_ONE args
*/ */
#ifdef FG_COMPILER_SUPPORTS_VA_ARGS #if FG_COMPILER_SUPPORTS_VA_ARGS
#define EXPAND_WCB_UNPARAN(...) __VA_ARGS__ #define EXPAND_WCB_UNPARAN(...) __VA_ARGS__
#define EXPAND_WCB_ONE_OR_MORE(args, userData) ( EXPAND_WCB_UNPARAN args, userData ) #define EXPAND_WCB_ONE_OR_MORE(args, userData) ( EXPAND_WCB_UNPARAN args, userData )
@ -172,17 +189,17 @@
#else #else
#define EXTRACT_ONE_ARGS(arg1) arg1 #define EXPAND_WCB_EXTRACT_ONE_ARGS(arg1) arg1
#define EXTRACT_TWO_ARGS(arg1, arg2) arg1, arg2 #define EXPAND_WCB_EXTRACT_TWO_ARGS(arg1, arg2) arg1, arg2
#define EXTRACT_THREE_ARGS(arg1, arg2, arg3) arg1, arg2, arg3 #define EXPAND_WCB_EXTRACT_THREE_ARGS(arg1, arg2, arg3) arg1, arg2, arg3
#define EXTRACT_FOUR_ARGS(arg1, arg2, arg3, arg4) arg1, arg2, arg3, arg4 #define EXPAND_WCB_EXTRACT_FOUR_ARGS(arg1, arg2, arg3, arg4) arg1, arg2, arg3, arg4
#define EXTRACT_FIVE_ARGS(arg1, arg2, arg3, arg4, arg5) arg1, arg2, arg3, arg4, arg5 #define EXPAND_WCB_EXTRACT_FIVE_ARGS(arg1, arg2, arg3, arg4, arg5) arg1, arg2, arg3, arg4, arg5
#define EXPAND_WCB_ONE(args, userData) (EXTRACT_ONE_ARGS args, userData) #define EXPAND_WCB_ONE(args, userData) (EXPAND_WCB_EXTRACT_ONE_ARGS args, userData)
#define EXPAND_WCB_TWO(args, userData) (EXTRACT_TWO_ARGS args, userData) #define EXPAND_WCB_TWO(args, userData) (EXPAND_WCB_EXTRACT_TWO_ARGS args, userData)
#define EXPAND_WCB_THREE(args, userData) (EXTRACT_THREE_ARGS args, userData) #define EXPAND_WCB_THREE(args, userData) (EXPAND_WCB_EXTRACT_THREE_ARGS args, userData)
#define EXPAND_WCB_FOUR(args, userData) (EXTRACT_FOUR_ARGS args, userData) #define EXPAND_WCB_FOUR(args, userData) (EXPAND_WCB_EXTRACT_FOUR_ARGS args, userData)
#define EXPAND_WCB_FIVE(args, userData) (EXTRACT_FIVE_ARGS args, userData) #define EXPAND_WCB_FIVE(args, userData) (EXPAND_WCB_EXTRACT_FIVE_ARGS args, userData)
#endif #endif