292 lines
16 KiB
C++
292 lines
16 KiB
C++
// DO NOT PUT #pragma once or include guard check here
|
|
// This header is designed to be able to be included multiple times
|
|
|
|
// -------------------------------------------------------------------------------------------------
|
|
// this macros are undefined in UndefineCoreMacros.h
|
|
|
|
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
// !!! IF YOU ADD A NEW MACRO TO THIS SECTION !!!
|
|
// !!! please add it to UndefineCoreMacros.h !!!
|
|
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
|
|
// this is where we collect context-free macros of general utility. it's a holding area until the new sub-core layer
|
|
// project is started.
|
|
//
|
|
// IMPORTANT: only macros! and no non-system #includes!
|
|
|
|
// FORCE_INLINE forwarded to compiler defined macro
|
|
#define FORCE_INLINE COMPILER_FORCEINLINE
|
|
|
|
// You may use OPTIMIZER_LIKELY / OPTIMIZER_UNLIKELY to provide the compiler with branch prediction information.
|
|
//
|
|
// The return value is the value of 'EXPR_', which should be an integral expression.
|
|
//
|
|
// OPTIMIZER_LIKELY makes it so that the branch predictor chooses to take the branch.
|
|
// OPTIMIZER_UNLIKELY makes it so that the branch predictor chooses not to take the branch.
|
|
//
|
|
#define OPTIMIZER_LIKELY(EXPR_) COMPILER_BUILTIN_EXPECT(!!(EXPR_), 1)
|
|
#define OPTIMIZER_UNLIKELY(EXPR_) COMPILER_BUILTIN_EXPECT(!!(EXPR_), 0)
|
|
|
|
// UNUSED will tell the compiler not to warn about a given variable being unused. "yeah, we know - this is unused."
|
|
//
|
|
// the internet says that (void)sizeof(expr) is the right way to do this, but not for us, not with our
|
|
// compilers. the below is the result of much experimentation by @lucas, who says that we have at least one compiler
|
|
// that does not consider sizeof(expr) to be a 'usage' of the variable(s) inside of expr.
|
|
//
|
|
// also note that we do not have the 'if+const expr' warning enabled because combining #if and if expression/constants
|
|
// (which we often need to do - for example 'caps->gles.requireClearAlpha = PLATFORM_WEBGL || PLATFORM_STV') is super noisy.
|
|
//
|
|
#define UNUSED(EXPR_) \
|
|
do { if (false) (void)(EXPR_); } while(0)
|
|
|
|
// COMPILER_WARNING will generate a compiler warning. this will work for all our compilers, though note the usage
|
|
// requires a pragma. (based on http://goodliffe.blogspot.dk/2009/07/c-how-to-say-warning-to-visual-studio-c.html)
|
|
//
|
|
// usage:
|
|
//
|
|
// #pragma COMPILER_WARNING("this file is obsolete! use foo/bar.h instead.")
|
|
//
|
|
#define COMPILER_WARNING(MESSAGE_) message(__FILE__ "(" UNITY_STRINGIFY(__LINE__) ") : warning: " MESSAGE_)
|
|
|
|
#define UNSIGNED_FLAGS_1(FLAG1_) static_cast<unsigned int>(FLAG1_)
|
|
#define UNSIGNED_FLAGS_2(FLAG1_, FLAG2_) UNSIGNED_FLAGS_1(FLAG1_) | UNSIGNED_FLAGS_1(FLAG2_)
|
|
#define UNSIGNED_FLAGS_3(FLAG1_, FLAG2_, FLAG3_) UNSIGNED_FLAGS_1(FLAG1_) | UNSIGNED_FLAGS_2(FLAG2_, FLAG3_)
|
|
#define UNSIGNED_FLAGS_4(FLAG1_, FLAG2_, FLAG3_, FLAG4_) UNSIGNED_FLAGS_1(FLAG1_) | UNSIGNED_FLAGS_3(FLAG2_, FLAG3_, FLAG4_)
|
|
#define UNSIGNED_FLAGS_5(FLAG1_, FLAG2_, FLAG3_, FLAG4_, FLAG5_) UNSIGNED_FLAGS_1(FLAG1_) | UNSIGNED_FLAGS_4(FLAG2_, FLAG3_, FLAG4_, FLAG5_)
|
|
#define UNSIGNED_FLAGS_6(FLAG1_, FLAG2_, FLAG3_, FLAG4_, FLAG5_, FLAG6_) UNSIGNED_FLAGS_1(FLAG1_) | UNSIGNED_FLAGS_5(FLAG2_, FLAG3_, FLAG4_, FLAG5_, FLAG6_)
|
|
#define UNSIGNED_FLAGS(...) PP_VARG_SELECT_OVERLOAD(UNSIGNED_FLAGS_, (__VA_ARGS__))
|
|
|
|
// -------------------------------------------------------------------------------------------------
|
|
// this macros are not undefined in UndefineCoreMacros.h, hence we put a guard to not define them twice
|
|
#ifndef DETAIL__PP_AND_DETAILS_CORE_MACROS_DEFINED
|
|
#define DETAIL__PP_AND_DETAILS_CORE_MACROS_DEFINED
|
|
|
|
// when putting control-flow, multiple statements, or unknown code (e.g. passed via an outer macro) inside of a macro,
|
|
// wrap it in PP_WRAP_CODE to be safe. https://q.unity3d.com/answers/1382/view.html
|
|
//
|
|
// (also see http://stackoverflow.com/questions/154136/do-while-and-if-else-statements-in-c-c-macros)
|
|
//
|
|
// things not to use PP_WRAP_CODE for:
|
|
//
|
|
// * 'break' or 'continue' statements that are expected to operate on the scope containing the macro
|
|
// * introduction of variables that are expected not to go out of scope at macro end
|
|
//
|
|
#define PP_WRAP_CODE(CODE_) \
|
|
do { CODE_; } while (0)
|
|
|
|
// PP_EMPTY_STATEMENT is used to insert an empty statement in a macro to require a semicolon terminator where used.
|
|
// most useful when creating "function style" macros where there is no natural place inside the macro to leave off a
|
|
// semicolon so as to require it in usage (for example when the internals end with a closing brace).
|
|
//
|
|
#define PP_EMPTY_STATEMENT \
|
|
do { } while (0)
|
|
|
|
// PP_VARG_COUNT expands to the the number of arguments passed to the macro. It supports 1 to 20 arguments (0 is not
|
|
// supported)
|
|
//
|
|
#define PP_VARG_COUNT(...) \
|
|
DETAIL__PP_EXPAND_2(DETAIL__PP_VARG_COUNT, (__VA_ARGS__, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1))
|
|
|
|
// PP_VARG_SELECT_OVERLOAD calls the correct overloaded version of the macro "name" name1, name2 etc.
|
|
//
|
|
// WARNING: **Varargs break Intellisense**. Intellisense gives us the argument list, which most of the time should be
|
|
// sufficient documentation for using a macro. Macro overloading hides the args and possibly makes it less safe as
|
|
// well. So be certain this tradeoff is worth it!
|
|
//
|
|
// Use like this:
|
|
//
|
|
// #define FORWARD_DECLARE_CLASS_1(CLASSNAME_) class CLASSNAME_;
|
|
// #define FORWARD_DECLARE_CLASS_2(NAMESPACE_, CLASSNAME_) namespace NAMESPACE_ { class CLASSNAME_; }
|
|
// #define FORWARD_DECLARE_CLASS_3(NAMESPACE_1_, NAMESPACE_2_, CLASSNAME_) namespace NAMESPACE_1_ { namespace NAMESPACE_1_ { class CLASSNAME_; } }
|
|
// // Up to 10 overloads can be added
|
|
// #define FORWARD_DECLARE_CLASS(...) PP_VARG_SELECT_OVERLOAD(FORWARD_DECLARE_CLASS_, (__VA_ARGS__))
|
|
//
|
|
// ...which can then be used with optional number of arguments like this:
|
|
//
|
|
// FORWARD_DECLARE_CLASS(GlobalClass)
|
|
// FORWARD_DECLARE_CLASS(FooNamespace, FooClass)
|
|
// FORWARD_DECLARE_CLASS(FooNamespace, BarNamespace, FooBarClass)
|
|
//
|
|
#define PP_VARG_SELECT_OVERLOAD(NAME_, ARGS_) \
|
|
DETAIL__PP_EXPAND_2(DETAIL__PP_VARG_CONCAT(NAME_, PP_VARG_COUNT ARGS_), ARGS_)
|
|
|
|
// PP_CONCAT concatenates all passed preprocessor tokens after macro-expanding them
|
|
#define PP_CONCAT(...) PP_VARG_SELECT_OVERLOAD(DETAIL__PP_CONCAT_, (__VA_ARGS__))
|
|
|
|
// PP_NOOP does nothing, but is useful for forcing the preprocessor to re-evaluate expressions after expansion.
|
|
#define PP_NOOP()
|
|
|
|
// PP_DEFER defers evaluation of EXPR_ to the next expansion pass.
|
|
#define PP_DEFER(EXPR_) EXPR_ PP_NOOP ()
|
|
|
|
// PP_DEFER2 defers evaluation of EXPR_ to the expansion pass *after* the next one
|
|
#define PP_DEFER2(EXPR_) EXPR_ PP_NOOP PP_NOOP ()()
|
|
|
|
// PP_DEFER3 defers evaluation of EXP_ to the expansion pass *after* the expansion pass after the next one
|
|
#define PP_DEFER3(EXPR_) EXPR_ PP_NOOP PP_NOOP PP_NOOP ()()()
|
|
|
|
// PP_RECURSE allows recursive expansion of macros; PP_RECURSE(A) will expand to A_RECURSE which you should define to A.
|
|
#define PP_RECURSE(MACRO_) PP_DEFER(MACRO_##_RECURSE)()
|
|
|
|
// Use PP_EVAL to force up to 1024 evaluation passes on an expression, ensuring that everything is fully expanded.
|
|
#define PP_EVAL(...) DETAIL__PP_EVAL1024(__VA_ARGS__)
|
|
|
|
// Use PP_STRINGIZE to wrap the precise characters in the given argument in double quotes (auto-escaping where necessary).
|
|
// This is most often used to convert an expression to a string, but be aware that the contents aren't limited to what a
|
|
// C expression permits! For example PP_STRINGIZE(pork & beans ("awesome")!) results in the literal "pork & beans (\"awesome\")!"
|
|
#define PP_STRINGIZE(ARG_) DETAIL__PP_STRINGIZE_EXPAND(ARG_)
|
|
|
|
// PP_FIRST expands to the first argument in a list of arguments
|
|
#define PP_FIRST(A_, ...) A_
|
|
|
|
// PP_SECOND expands to the second argument in a list of (at least two) arguments
|
|
#define PP_SECOND(A_, B_, ...) B_
|
|
|
|
// PP_BOOLIFY expands to 0 if the argument is 0, and 1 otherwise
|
|
// It should be used inside a PP_EVAL expression.
|
|
#define PP_BOOLIFY(EXPR_) DETAIL__PP_BOOLIFY_NOT(DETAIL__PP_BOOLIFY_NOT(EXPR_))
|
|
|
|
// PP_VARG_IS_NONEMPTY evaluates to 0 if no arguments are provided, and 1 otherwise
|
|
// It should be used inside a PP_EVAL expression.
|
|
#if COMPILER_MSVC
|
|
#define PP_VARG_IS_NONEMPTY(...) PP_BOOLIFY(PP_FIRST(__VA_ARGS__ DETAIL__PP_VARG_END_MARKER)())
|
|
#else
|
|
#define PP_VARG_IS_NONEMPTY(...) PP_BOOLIFY(PP_DEFER(PP_FIRST)(DETAIL__PP_VARG_END_MARKER DETAIL__PP_VARG_UNPAREN_FIRST(__VA_ARGS__))())
|
|
#endif
|
|
|
|
// PP_IF_ELSE(EXPR_)(A_)(B_) evaluates to A_ if EXPR_ is nonzero, or to B_ if EXPR_ is 0.
|
|
// It should be used inside a PP_EVAL expression.
|
|
#define PP_IF_ELSE(EXPR_) DETAIL__PP_IF_ELSE(PP_BOOLIFY(EXPR_))
|
|
|
|
// PP_MAP applies MACRO_ to each of the following arguments.
|
|
// It should be used inside a PP_EVAL expression.
|
|
#define PP_MAP(MACRO_, ...) PP_EVAL(PP_IF_ELSE(PP_VARG_IS_NONEMPTY(__VA_ARGS__))(PP_DEFER3(DETAIL__PP_MAP_NONOPTIONAL)(MACRO_, __VA_ARGS__))())
|
|
|
|
// PP_UNPAREN removes one set of optional parenthesis around the argument.
|
|
// Useful for implementing macros that take types as argument since the commas in templated types
|
|
// normally are seen as macro argument separators.
|
|
// #define ARRAY(NAME_, TYPE_, COUNT_) PP_UNPAREN(TYPE_) NAME_[COUNT_]
|
|
// The type passed to the ARRAY macro ARRAY macro can now be used like:
|
|
// ARRAY(array_of_maps, (map<int,int>), 8);
|
|
// while still accepting:
|
|
// ARRAY(array_of_ints, int, 8);
|
|
#define PP_UNPAREN(EXPR_) DETAIL__PP_UNPAREN_EVAL_AND_CONCAT_FIRST_2_ARGS(DETAIL__PP_UNPAREN_EMPTY_, DETAIL__PP_UNPAREN_HELPER EXPR_)
|
|
|
|
#if __cplusplus
|
|
|
|
// PP_IS_STRING evaluates to true if the argument is of const char* type, false otherwise
|
|
#define PP_IS_STRING(EXPR_) (sizeof(core::detail::ReturnCharIfString(EXPR_)) == sizeof(char))
|
|
|
|
// PP_CONST_VALUE takes a value that _may_ be an int, or may be a string, and produces a constant expression suitable for use as an enum
|
|
// initializer. If you pass it a string, the result will still be a constant expression, but it will have undefined value.
|
|
#define PP_CONST_VALUE(EXPR_) ((int)DETAIL__PP_CONST_VALUE_HIGHBITS(EXPR_) + (int)DETAIL__PP_CONST_VALUE_LOWBITS(EXPR_))
|
|
|
|
#endif
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// implementation details for above macros follow. we have this in a separate section to cut down on clutter above.
|
|
|
|
// visual c++ requires two levels of indirection to ensure proper macro expansion of PP_CONCAT with certain arguments involving __VA_ARGS__
|
|
// and other scenarios like the one below.
|
|
// #define PP_CAT(a,b) a##b
|
|
// #define PP_CAT2(a,b) PP_CAT(a,b)
|
|
// #define PP_CAT3(a,b) PP_CAT2(a,b)
|
|
//
|
|
// #define E(a) QQ a
|
|
// #define QQ() Q
|
|
//
|
|
// #define T2() PP_CAT2(_,E(()))
|
|
// #define T3() PP_CAT3(_,E(()))
|
|
//
|
|
// T2() and T3() will expand differently with VC but not with other preprocessors.
|
|
#define DETAIL__PP_CONCAT_Y(A_, B_) A_##B_
|
|
#define DETAIL__PP_CONCAT_X(A_, B_) DETAIL__PP_CONCAT_Y(A_, B_)
|
|
|
|
#define DETAIL__PP_EXPAND_2(A_, B_) A_ B_
|
|
|
|
|
|
#define DETAIL__PP_VARG_CONCAT_Y(A_, B_) A_##B_
|
|
#define DETAIL__PP_VARG_CONCAT_X(A_, B_) DETAIL__PP_VARG_CONCAT_Y(A_, B_)
|
|
#define DETAIL__PP_VARG_CONCAT(A_, B_) DETAIL__PP_VARG_CONCAT_X(A_, B_)
|
|
#define DETAIL__PP_VARG_COUNT(ARG0_, ARG1_, ARG2_, ARG3_, ARG4_, ARG5_, ARG6_, ARG7_, ARG8_, ARG9_, ARG10_, ARG11_, ARG12_, ARG13_, ARG14_, ARG15_, ARG16_, ARG17_, ARG18_, ARG19_, RESULT_, ...) RESULT_
|
|
|
|
#define DETAIL__PP_CONCAT_1(A_) DETAIL__PP_CONCAT_X(A_,)
|
|
#define DETAIL__PP_CONCAT_2(A_, B_) DETAIL__PP_CONCAT_X(A_, B_)
|
|
#define DETAIL__PP_CONCAT_3(A_, B_, C_) DETAIL__PP_CONCAT_2(DETAIL__PP_CONCAT_2(A_, B_), C_)
|
|
#define DETAIL__PP_CONCAT_4(A_, B_, C_, D_) DETAIL__PP_CONCAT_2(DETAIL__PP_CONCAT_2(A_, B_), DETAIL__PP_CONCAT_2(C_, D_))
|
|
#define DETAIL__PP_CONCAT_5(A_, B_, C_, D_, E_) DETAIL__PP_CONCAT_2(DETAIL__PP_CONCAT_2(A_, B_), DETAIL__PP_CONCAT_3(C_, D_, E_))
|
|
#define DETAIL__PP_CONCAT_6(A_, B_, C_, D_, E_, F_) DETAIL__PP_CONCAT_2(DETAIL__PP_CONCAT_2(A_, B_), DETAIL__PP_CONCAT_4(C_, D_, E_, F_))
|
|
#define DETAIL__PP_CONCAT_7(A_, B_, C_, D_, E_, F_, G_) DETAIL__PP_CONCAT_2(DETAIL__PP_CONCAT_3(A_, B_, C_), DETAIL__PP_CONCAT_4(D_, E_, F_, G_))
|
|
#define DETAIL__PP_CONCAT_8(A_, B_, C_, D_, E_, F_, G_, H_) DETAIL__PP_CONCAT_2(DETAIL__PP_CONCAT_4(A_, B_, C_, D_), DETAIL__PP_CONCAT_4(E_, F_, G_, H_))
|
|
|
|
#define DETAIL__PP_EVAL1024(...) DETAIL__PP_EVAL512(DETAIL__PP_EVAL512(__VA_ARGS__))
|
|
#define DETAIL__PP_EVAL512(...) DETAIL__PP_EVAL256(DETAIL__PP_EVAL256(__VA_ARGS__))
|
|
#define DETAIL__PP_EVAL256(...) DETAIL__PP_EVAL128(DETAIL__PP_EVAL128(__VA_ARGS__))
|
|
#define DETAIL__PP_EVAL128(...) DETAIL__PP_EVAL64(DETAIL__PP_EVAL64(__VA_ARGS__))
|
|
#define DETAIL__PP_EVAL64(...) DETAIL__PP_EVAL32(DETAIL__PP_EVAL32(__VA_ARGS__))
|
|
#define DETAIL__PP_EVAL32(...) DETAIL__PP_EVAL16(DETAIL__PP_EVAL16(__VA_ARGS__))
|
|
#define DETAIL__PP_EVAL16(...) DETAIL__PP_EVAL8(DETAIL__PP_EVAL8(__VA_ARGS__))
|
|
#define DETAIL__PP_EVAL8(...) DETAIL__PP_EVAL4(DETAIL__PP_EVAL4(__VA_ARGS__))
|
|
#define DETAIL__PP_EVAL4(...) DETAIL__PP_EVAL2(DETAIL__PP_EVAL2(__VA_ARGS__))
|
|
#define DETAIL__PP_EVAL2(...) DETAIL__PP_EVAL1(DETAIL__PP_EVAL1(__VA_ARGS__))
|
|
#define DETAIL__PP_EVAL1(...) __VA_ARGS__
|
|
|
|
#define DETAIL__PP_CONST_VALUE_ARR(EXPR_) core::detail::ConstValueHelper<sizeof(core::detail::ReturnCharIfString(EXPR_))>::arr
|
|
|
|
// Extract the high bits of x. We cannot just do (x & 0xffff0000) because 0x7fffffff is the maximum permitted array size on 32bit, so we have to shift
|
|
// and the array is not allowed to be size 0, so we add 0x10000 to ensure nonzero
|
|
#define DETAIL__PP_CONST_VALUE_HIGHBITS(EXPR_) ((sizeof(DETAIL__PP_CONST_VALUE_ARR(EXPR_)[ ((ptrdiff_t)(EXPR_) >> 16) + 0x10000]) - 0x10000) << 16)
|
|
|
|
// Extract the low bits of x - as with the high bits, the array cannot be zero-length, so we add 1 and then subtract it again after the sizeof
|
|
#define DETAIL__PP_CONST_VALUE_LOWBITS(EXPR_) (sizeof(DETAIL__PP_CONST_VALUE_ARR(EXPR_)[ ((ptrdiff_t)(EXPR_) & 0xFFFF) + 1]) - 1)
|
|
|
|
#define DETAIL__PP_STRINGIZE_EXPAND(EXPR_) #EXPR_
|
|
|
|
// Expand to 1 if the first argument is DETAIL__PP_PROBE(), 0 otherwise
|
|
#define DETAIL__PP_IS_PROBE(...) PP_DEFER(PP_SECOND)(__VA_ARGS__, 0)
|
|
#define DETAIL__PP_PROBE() _, 1
|
|
|
|
#define DETAIL__PP_BOOLIFY_NOT(EXPR_) PP_DEFER(DETAIL__PP_IS_PROBE)(PP_CONCAT(DETAIL__PP_BOOLIFY_NOT_PROBE_, EXPR_))
|
|
#define DETAIL__PP_BOOLIFY_NOT_PROBE_0 DETAIL__PP_PROBE()
|
|
#define DETAIL__PP_BOOLIFY_NOT_PROBE_1 0
|
|
|
|
#define DETAIL__PP_VARG_END_MARKER() 0
|
|
#define DETAIL__PP_VARG_UNPAREN_FIRST(...) DETAIL__PP_UNPAREN_EVAL_AND_CONCAT_FIRST_2_ARGS(DETAIL__PP_UNPAREN_EMPTY_, DETAIL__PP_UNPAREN_HELPER __VA_ARGS__)
|
|
|
|
#define DETAIL__PP_IF_ELSE(EXPR_) PP_CONCAT(DETAIL__PP_IF_, EXPR_)
|
|
#define DETAIL__PP_IF_1(...) __VA_ARGS__ DETAIL__PP_IF_1_ELSE
|
|
#define DETAIL__PP_IF_0(...) DETAIL__PP_IF_0_ELSE
|
|
#define DETAIL__PP_IF_1_ELSE(...)
|
|
#define DETAIL__PP_IF_0_ELSE(...) __VA_ARGS__
|
|
|
|
#define DETAIL__PP_MAP_NONOPTIONAL(MACRO_, FIRST_, ...) MACRO_(FIRST_) PP_IF_ELSE(PP_VARG_IS_NONEMPTY(__VA_ARGS__))( PP_DEFER2(DETAIL__PP_MAP_RECURSE)()(MACRO_, __VA_ARGS__) )()
|
|
#define DETAIL__PP_MAP_RECURSE() DETAIL__PP_MAP_NONOPTIONAL
|
|
|
|
#define DETAIL__PP_UNPAREN_CONCAT_FIRST_2_ARGS(x, ...) x##__VA_ARGS__
|
|
#define DETAIL__PP_UNPAREN_EVAL_AND_CONCAT_FIRST_2_ARGS(x, ...) DETAIL__PP_UNPAREN_CONCAT_FIRST_2_ARGS(x, __VA_ARGS__)
|
|
#define DETAIL__PP_UNPAREN_EMPTY_DETAIL__PP_UNPAREN_HELPER
|
|
#define DETAIL__PP_UNPAREN_HELPER(...) DETAIL__PP_UNPAREN_HELPER __VA_ARGS__
|
|
|
|
#if __cplusplus
|
|
|
|
namespace core
|
|
{
|
|
namespace detail
|
|
{
|
|
char ReturnCharIfString(const char*);
|
|
long ReturnCharIfString(unsigned int);
|
|
long ReturnCharIfString(int);
|
|
long ReturnCharIfString(float);
|
|
|
|
template<int dummy> struct ConstValueHelper { typedef char arr; };
|
|
template<> struct ConstValueHelper<sizeof(char)> { static char arr[1]; };
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif /* DETAIL__PP_AND_DETAILS_CORE_MACROS_DEFINED */
|