490 lines
33 KiB
C++
490 lines
33 KiB
C++
/*
|
|
* Copyright 2010-2016 Nest Labs Inc. All Rights Reserved.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
* Description:
|
|
* This file defines macros internal to the implementation of the
|
|
* Nest Labs assertion and exception checking facility.
|
|
*
|
|
*/
|
|
|
|
#ifndef NLASSERT_INTERNAL_H
|
|
#define NLASSERT_INTERNAL_H
|
|
|
|
#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__)
|
|
# define __nlLIKELY(condition) __builtin_expect(condition, 1)
|
|
# define __nlUNLIKELY(condition) __builtin_expect(condition, 0)
|
|
#else
|
|
# define __nlLIKELY(condition) (condition)
|
|
# define __nlUNLIKELY(condition) (condition)
|
|
#endif /* defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__) */
|
|
|
|
// Notes on the unusual design of __nlSHOULD_ASSERT and __nl_ASSERT_UNUSED:
|
|
//
|
|
//
|
|
// For non-production builds (aka "development" or "debug" builds)
|
|
// ===============================================================
|
|
//
|
|
// The nlASSERT(condition) macro evaluates the "condition" expression and, if
|
|
// it is false, calls NL_ASSERT_ABORT() to abort execution (after optionally
|
|
// performing some logging and debugging operations). Partially expanded, for
|
|
// clarity, it looks like this:
|
|
//
|
|
// if (__nlSHOULD_ASSERT(condition))
|
|
// {
|
|
// do
|
|
// {
|
|
// /* optional logging, backtrace, and/or trap handling */
|
|
// } while (0);
|
|
//
|
|
// {
|
|
// NL_ASSERT_ABORT();
|
|
// }
|
|
// }
|
|
// else do { /* nothing */ } while (0)
|
|
//
|
|
// NOTE: The "if (foo) / else do { } while (0)" construct is just a more
|
|
// robust version of the standard "do / while (0)" macro wrapper.
|
|
// It is explained below, in the comments accompanying __nlCHECK.
|
|
//
|
|
// The __nlSHOULD_ASSERT(condition) macro must evaluate to true if "condition"
|
|
// is false; conceptually, its definition is "!(condition)". But it is not
|
|
// actually defined that way, for this reason:
|
|
//
|
|
// It is not uncommon for an equality test like "if (x == y)" to be accidentally
|
|
// written as an assignment: "if (x = y)". GCC and similar compilers can detect
|
|
// this and emit a warning, but the warning is suppressed if the assignment is
|
|
// surrounded by an extra pair of parentheses to indicate that it is
|
|
// intentional: "if ((x = y))". So if __nlSHOULD_ASSERT(condition) were defined
|
|
// as "!(condition)", the parentheses around "condition" -- required by the "!"
|
|
// operator -- would be seen by the compiler as an indication that the
|
|
// assignment was intentional, so no warning would be emitted if, for example,
|
|
// "nlASSERT(x == y)" were mistakenly written as "nlASSERT(x = y)".
|
|
//
|
|
// Therefore, __nlSHOULD_ASSERT(condition) is defined so that there will be no
|
|
// extra parentheses around "condition" when the nlASSERT(condition) macro is
|
|
// expanded. With this definition, nlASSERT(condition) expands to:
|
|
//
|
|
// if (condition)
|
|
// {
|
|
// /* do nothing */
|
|
// }
|
|
// else if (1)
|
|
// {
|
|
// do
|
|
// {
|
|
// /* optional logging, backtrace, and/or trap handling */
|
|
// } while (0);
|
|
//
|
|
// {
|
|
// NL_ASSERT_ABORT();
|
|
// }
|
|
// }
|
|
// else do { /* nothing */ } while (0)
|
|
//
|
|
// GCC's branch-prediction hinting mechanism ("__builtin_expect(condition,1)")
|
|
// would also suppress the "unintended assignment" warning, so is not used in
|
|
// the macro definition. But the macro compiles to exactly the same assembly
|
|
// code as it would if the hint were included, so omitting the hint incurs no
|
|
// speed or memory cost. This is true for both ARM and x86 ISAs (tested under
|
|
// GCC 4.x.x, with optimization for speed enabled via compiler flag -O3).
|
|
//
|
|
//
|
|
// For production builds (aka "release" builds)
|
|
// ============================================
|
|
//
|
|
// The nlASSERT(condition) macro is disabled by defining it as
|
|
// __nlASSERT_UNUSED(condition).
|
|
//
|
|
// The __nlASSERT_UNUSED(condition) macro must not perform any logging or
|
|
// debugging operations, and it must not abort program execution even when
|
|
// "condition" is false. It cannot simply be defined as "(void)0", however,
|
|
// because it must allow side effects in "condition", if any, to occur exactly
|
|
// as they would in the non-production version of the macro. And it can't be
|
|
// defined as (void)(condition) because it is desirable for an unintended
|
|
// assignment in "condition" to be caught by the compiler, just as it would be
|
|
// in a non-production build.
|
|
//
|
|
// Therefore, __nl_ASSERT_UNUSED(condition) is defined so that "condition" is
|
|
// treated as a truth value, to ensure that unintended assignment will be
|
|
// caught, and so that "condition" is evaluated at runtime if and only if it
|
|
// would also be evaluated by the non-production version of nlASSERT(condition),
|
|
// to ensure that side effects will occur identically.
|
|
|
|
#define __nlSHOULD_ASSERT(condition) condition) { /* do nothing */ } else if (1
|
|
|
|
#define __nlASSERT_UNUSED(condition) do { if (condition) { /* do nothing */ } } while (0)
|
|
|
|
/** @cond */
|
|
#define __nlSTATIC_ASSERT_CONCAT(aPrefix, aSuffix) aPrefix ## aSuffix
|
|
|
|
#define _nlSTATIC_ASSERT_CONCAT(aPrefix, aSuffix) __nlSTATIC_ASSERT_CONCAT(aPrefix, aSuffix)
|
|
/** @endcond */
|
|
|
|
/**
|
|
* @def _nlSTATIC_ASSERT(aCondition)
|
|
*
|
|
* @brief
|
|
* This checks, at compile-time, for the specified condition, which
|
|
* is expected to commonly be true and terminates compilation if the
|
|
* condition is false. It is legal, in both C and C++, anywhere that
|
|
* a declaration would be.
|
|
*
|
|
* @note This is a package-internal interface. If C++11/C11 or greater is
|
|
* available, this falls back to using C++11/C11 intrinsic facilities:
|
|
* static_assert or _Static_assert.
|
|
*
|
|
* @param[in] aCondition A Boolean expression to be evaluated.
|
|
* @param[in] aMessage A pointer to a NULL-terminated C string
|
|
* containing a caller-specified message
|
|
* further describing the assertion
|
|
* failure. Note, this message is not
|
|
* actually emitted in any meaningful way for
|
|
* non-C11 or -C++11 code. It serves to
|
|
* simply comment or annotate the assertion
|
|
* and to provide interface parallelism with
|
|
* the run-time assertion interfaces.
|
|
*
|
|
*/
|
|
#if defined(__cplusplus) && (__cplusplus >= 201103L)
|
|
# define _nlSTATIC_ASSERT(aCondition, aMessage) static_assert(aCondition, aMessage)
|
|
#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
|
|
# define _nlSTATIC_ASSERT(aCondition, aMessage) _Static_assert(aCondition, aMessage)
|
|
#else
|
|
# ifdef __COUNTER__
|
|
# define _nlSTATIC_ASSERT(aCondition, aMessage) typedef char _nlSTATIC_ASSERT_CONCAT(STATIC_ASSERT_t_, __COUNTER__)[(aCondition) ? 1 : -1] __attribute__ ((unused))
|
|
# else
|
|
# define _nlSTATIC_ASSERT(aCondition, aMessage) typedef char _nlSTATIC_ASSERT_CONCAT(STATIC_ASSERT_t_, __LINE__)[(aCondition) ? 1 : -1] __attribute__ ((unused))
|
|
# endif
|
|
#endif /* defined(__cplusplus) && (__cplusplus >= 201103L) */
|
|
|
|
// __nlSTATIC_ASSERT_UNUSED(aCondition)
|
|
//
|
|
// Can be used everywhere that _nlSTATIC_ASSERT can, and behaves exactly the
|
|
// same way except that it never asserts.
|
|
#if defined(__cplusplus) && (__cplusplus >= 201103L)
|
|
# define __nlSTATIC_ASSERT_UNUSED(aCondition, aMessage) static_assert((aCondition) || 1, aMessage)
|
|
#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
|
|
# define __nlSTATIC_ASSERT_UNUSED(aCondition, aMessage) _Static_assert((aCondition) || 1, aMessage)
|
|
#else
|
|
# ifdef __COUNTER__
|
|
# define __nlSTATIC_ASSERT_UNUSED(aCondition, aMessage) typedef char _nlSTATIC_ASSERT_CONCAT(STATIC_ASSERT_t_, __COUNTER__)[((aCondition) || 1) ? 1 : -1] __attribute__ ((unused))
|
|
# else
|
|
# define __nlSTATIC_ASSERT_UNUSED(aCondition, aMessage) typedef char _nlSTATIC_ASSERT_CONCAT(STATIC_ASSERT_t_, __LINE__)[((aCondition) || 1) ? 1 : -1] __attribute__ ((unused))
|
|
# endif
|
|
#endif /* defined(__cplusplus) && (__cplusplus >= 201103L) */
|
|
|
|
#define __NL_ASSERT_MAYBE_RUN_TRIGGERS(flags, prefix, name, condition, label, file, line, message) \
|
|
do \
|
|
{ \
|
|
if ((flags) & NL_ASSERT_FLAG_LOG) { \
|
|
NL_ASSERT_LOG(prefix, name, condition, label, file, line, message); \
|
|
} \
|
|
if ((flags) & NL_ASSERT_FLAG_BACKTRACE) { \
|
|
NL_ASSERT_BACKTRACE(); \
|
|
} \
|
|
if ((flags) & NL_ASSERT_FLAG_TRAP) { \
|
|
NL_ASSERT_TRAP(); \
|
|
} \
|
|
} while (0)
|
|
|
|
#define __NL_ASSERT_MAYBE_RUN_PRE_ACTION_TRIGGERS(flags, prefix, name, condition, label, file, line, message) \
|
|
do \
|
|
{ \
|
|
if ((flags) & NL_ASSERT_FLAG_LOG) { \
|
|
NL_ASSERT_LOG(prefix, name, condition, label, file, line, message); \
|
|
} \
|
|
if ((flags) & NL_ASSERT_FLAG_BACKTRACE) { \
|
|
NL_ASSERT_BACKTRACE(); \
|
|
} \
|
|
} while (0)
|
|
|
|
#define __NL_ASSERT_MAYBE_RUN_POST_ACTION_TRIGGERS(flags, prefix, name, condition, label, file, line, message) \
|
|
do \
|
|
{ \
|
|
if ((flags) & NL_ASSERT_FLAG_TRAP) { \
|
|
NL_ASSERT_TRAP(); \
|
|
} \
|
|
} while (0)
|
|
|
|
// __nlEXPECT
|
|
|
|
#define __nlEXPECT(flags, condition, label) \
|
|
do \
|
|
{ \
|
|
if (__nlSHOULD_ASSERT(condition)) \
|
|
{ \
|
|
__NL_ASSERT_MAYBE_RUN_TRIGGERS((flags), \
|
|
NL_ASSERT_PREFIX_STRING, \
|
|
NL_ASSERT_COMPONENT_STRING, \
|
|
#condition, \
|
|
#label, \
|
|
NL_ASSERT_FILE, \
|
|
__LINE__, \
|
|
0); \
|
|
goto label; \
|
|
} \
|
|
} while (0)
|
|
|
|
#define __nlEXPECT_PRINT(flags, condition, label, message) \
|
|
do \
|
|
{ \
|
|
if (__nlSHOULD_ASSERT(condition)) \
|
|
{ \
|
|
__NL_ASSERT_MAYBE_RUN_TRIGGERS((flags), \
|
|
NL_ASSERT_PREFIX_STRING, \
|
|
NL_ASSERT_COMPONENT_STRING, \
|
|
#condition, \
|
|
#label, \
|
|
NL_ASSERT_FILE, \
|
|
__LINE__, \
|
|
message); \
|
|
goto label; \
|
|
} \
|
|
} while (0)
|
|
|
|
#define __nlEXPECT_ACTION(flags, condition, label, action) \
|
|
do \
|
|
{ \
|
|
if (__nlSHOULD_ASSERT(condition)) \
|
|
{ \
|
|
__NL_ASSERT_MAYBE_RUN_PRE_ACTION_TRIGGERS((flags), \
|
|
NL_ASSERT_PREFIX_STRING, \
|
|
NL_ASSERT_COMPONENT_STRING, \
|
|
#condition, \
|
|
#label, \
|
|
NL_ASSERT_FILE, \
|
|
__LINE__, \
|
|
0); \
|
|
{ \
|
|
action; \
|
|
} \
|
|
__NL_ASSERT_MAYBE_RUN_POST_ACTION_TRIGGERS((flags), \
|
|
NL_ASSERT_PREFIX_STRING, \
|
|
NL_ASSERT_COMPONENT_STRING, \
|
|
#condition, \
|
|
#label, \
|
|
NL_ASSERT_FILE, \
|
|
__LINE__, \
|
|
0); \
|
|
goto label; \
|
|
} \
|
|
} while (0)
|
|
|
|
#define __nlEXPECT_ACTION_PRINT(flags, condition, label, action, message) \
|
|
do \
|
|
{ \
|
|
if (__nlSHOULD_ASSERT(condition)) \
|
|
{ \
|
|
__NL_ASSERT_MAYBE_RUN_PRE_ACTION_TRIGGERS((flags), \
|
|
NL_ASSERT_PREFIX_STRING, \
|
|
NL_ASSERT_COMPONENT_STRING, \
|
|
#condition, \
|
|
#label, \
|
|
NL_ASSERT_FILE, \
|
|
__LINE__, \
|
|
message); \
|
|
{ \
|
|
action; \
|
|
} \
|
|
__NL_ASSERT_MAYBE_RUN_POST_ACTION_TRIGGERS((flags), \
|
|
NL_ASSERT_PREFIX_STRING, \
|
|
NL_ASSERT_COMPONENT_STRING, \
|
|
#condition, \
|
|
#label, \
|
|
NL_ASSERT_FILE, \
|
|
__LINE__, \
|
|
message); \
|
|
goto label; \
|
|
} \
|
|
} while (0)
|
|
|
|
#define __nlEXPECT_SUCCESS(flags, status, label) __nlEXPECT(flags, status == 0, label)
|
|
#define __nlEXPECT_SUCCESS_PRINT(flags, status, label, message) __nlEXPECT_PRINT(flags, status == 0, label, message)
|
|
#define __nlEXPECT_SUCCESS_ACTION(flags, status, label, action) __nlEXPECT_ACTION(flags, status == 0, label, action)
|
|
#define __nlEXPECT_SUCCESS_ACTION_PRINT(flags, status, label, action, message) __nlEXPECT_ACTION_PRINT(flags, status == 0, label, action, message)
|
|
|
|
#define __nlNEXPECT(flags, condition, label) __nlEXPECT(flags, !(condition), label)
|
|
#define __nlNEXPECT_PRINT(flags, condition, label, message) __nlEXPECT_PRINT(flags, !(condition), label, message)
|
|
#define __nlNEXPECT_ACTION(flags, condition, label, action) __nlEXPECT_ACTION(flags, !(condition), label, action)
|
|
#define __nlNEXPECT_ACTION_PRINT(flags, condition, label, action, message) __nlEXPECT_ACTION_PRINT(flags, !(condition), label, action, message)
|
|
|
|
// __nlCHECK
|
|
//
|
|
// NOTE: Some of these macros take a C statement as a parameter. The unusual
|
|
// "else do {} while(0)" construct allows those macros to work properly when
|
|
// that parameter is set to "continue" or "break" (which isn't unexpected in
|
|
// an assert macro).
|
|
//
|
|
// If the macros were written in the standard way by wrapping them in a
|
|
// "do/while(0)", they could fail silently: A "continue" or "break" statement,
|
|
// intended to break out of one or all iterations of the loop containing the
|
|
// macro invocation -- would instead just break out of the macro's internal
|
|
// do-while.
|
|
|
|
#define __nlCHECK(flags, condition) \
|
|
if (__nlSHOULD_ASSERT(condition)) \
|
|
{ \
|
|
__NL_ASSERT_MAYBE_RUN_TRIGGERS((flags), \
|
|
NL_ASSERT_PREFIX_STRING, \
|
|
NL_ASSERT_COMPONENT_STRING, \
|
|
#condition, \
|
|
0, \
|
|
NL_ASSERT_FILE, \
|
|
__LINE__, \
|
|
0); \
|
|
} \
|
|
else do {} while (0)
|
|
|
|
#define __nlCHECK_ACTION(flags, condition, action) \
|
|
if (__nlSHOULD_ASSERT(condition)) \
|
|
{ \
|
|
__NL_ASSERT_MAYBE_RUN_PRE_ACTION_TRIGGERS((flags), \
|
|
NL_ASSERT_PREFIX_STRING, \
|
|
NL_ASSERT_COMPONENT_STRING, \
|
|
#condition, \
|
|
0, \
|
|
NL_ASSERT_FILE, \
|
|
__LINE__, \
|
|
0); \
|
|
{ \
|
|
action; \
|
|
} \
|
|
__NL_ASSERT_MAYBE_RUN_POST_ACTION_TRIGGERS((flags), \
|
|
NL_ASSERT_PREFIX_STRING, \
|
|
NL_ASSERT_COMPONENT_STRING, \
|
|
#condition, \
|
|
0, \
|
|
NL_ASSERT_FILE, \
|
|
__LINE__, \
|
|
0); \
|
|
} \
|
|
else do {} while (0) /* This is explained in the comment above __nlCHECK */
|
|
|
|
#define __nlCHECK_PRINT(flags, condition, message) \
|
|
if (__nlSHOULD_ASSERT(condition)) \
|
|
{ \
|
|
__NL_ASSERT_MAYBE_RUN_TRIGGERS((flags), \
|
|
NL_ASSERT_PREFIX_STRING, \
|
|
NL_ASSERT_COMPONENT_STRING, \
|
|
#condition, \
|
|
0, \
|
|
NL_ASSERT_FILE, \
|
|
__LINE__, \
|
|
message); \
|
|
} \
|
|
else do {} while (0) /* This is explained in the comment above __nlCHECK */
|
|
|
|
#define __nlCHECK_SUCCESS(flags, status) __nlCHECK(flags, status == 0)
|
|
#define __nlCHECK_SUCCESS_ACTION(flags, status, action) __nlCHECK_ACTION(flags, status == 0, action)
|
|
#define __nlCHECK_SUCCESS_PRINT(flags, status, message) __nlCHECK_PRINT(flags, status == 0, message)
|
|
|
|
#define __nlNCHECK(flags, condition) __nlCHECK(flags, !(condition))
|
|
#define __nlNCHECK_ACTION(flags, condition, action) __nlCHECK_ACTION(flags, !(condition), action)
|
|
#define __nlNCHECK_PRINT(flags, condition, message) __nlCHECK_PRINT(flags, !(condition), message)
|
|
|
|
// __nlVERIFY
|
|
|
|
#define __nlVERIFY(flags, condition) __nlCHECK(flags, condition)
|
|
#define __nlVERIFY_ACTION(flags, condition, action) __nlCHECK_ACTION(flags, condition, action)
|
|
#define __nlVERIFY_PRINT(flags, condition, message) __nlCHECK_PRINT(flags, condition, message)
|
|
|
|
#define __nlVERIFY_SUCCESS(flags, status) __nlCHECK_SUCCESS(flags, status)
|
|
#define __nlVERIFY_SUCCESS_ACTION(flags, status, action) __nlCHECK_SUCCESS_ACTION(flags, status, action)
|
|
#define __nlVERIFY_SUCCESS_PRINT(flags, status, message) __nlCHECK_SUCCESS_PRINT(flags, status, message)
|
|
|
|
#define __nlNVERIFY(flags, condition) __nlNCHECK(flags, condition)
|
|
#define __nlNVERIFY_ACTION(flags, condition, action) __nlNCHECK_ACTION(flags, condition, action)
|
|
#define __nlNVERIFY_PRINT(flags, condition, message) __nlNCHECK_PRINT(flags, condition, message)
|
|
|
|
// __nlPRECONDITION
|
|
|
|
#define __nlPRECONDITION(flags, condition, termination) \
|
|
if (__nlSHOULD_ASSERT(condition)) \
|
|
{ \
|
|
__NL_ASSERT_MAYBE_RUN_TRIGGERS((flags), \
|
|
NL_ASSERT_PREFIX_STRING, \
|
|
NL_ASSERT_COMPONENT_STRING, \
|
|
#condition, \
|
|
0, \
|
|
NL_ASSERT_FILE, \
|
|
__LINE__, \
|
|
0); \
|
|
{ \
|
|
termination; \
|
|
} \
|
|
} \
|
|
else do {} while (0) /* This is explained in the comment above __nlCHECK */
|
|
|
|
#define __nlPRECONDITION_ACTION(flags, condition, termination, action) \
|
|
if (__nlSHOULD_ASSERT(condition)) \
|
|
{ \
|
|
__NL_ASSERT_MAYBE_RUN_PRE_ACTION_TRIGGERS((flags), \
|
|
NL_ASSERT_PREFIX_STRING, \
|
|
NL_ASSERT_COMPONENT_STRING, \
|
|
#condition, \
|
|
0, \
|
|
NL_ASSERT_FILE, \
|
|
__LINE__, \
|
|
0); \
|
|
{ \
|
|
action; \
|
|
} \
|
|
__NL_ASSERT_MAYBE_RUN_POST_ACTION_TRIGGERS((flags), \
|
|
NL_ASSERT_PREFIX_STRING, \
|
|
NL_ASSERT_COMPONENT_STRING, \
|
|
#condition, \
|
|
0, \
|
|
NL_ASSERT_FILE, \
|
|
__LINE__, \
|
|
0); \
|
|
{ \
|
|
termination; \
|
|
} \
|
|
} \
|
|
else do {} while (0) /* This is explained in the comment above __nlCHECK */
|
|
|
|
#define __nlPRECONDITION_PRINT(flags, condition, termination, message) \
|
|
if (__nlSHOULD_ASSERT(condition)) \
|
|
{ \
|
|
__NL_ASSERT_MAYBE_RUN_TRIGGERS((flags), \
|
|
NL_ASSERT_PREFIX_STRING, \
|
|
NL_ASSERT_COMPONENT_STRING, \
|
|
#condition, \
|
|
0, \
|
|
NL_ASSERT_FILE, \
|
|
__LINE__, \
|
|
message); \
|
|
{ \
|
|
termination; \
|
|
} \
|
|
} \
|
|
else do {} while (0) /* This is explained in the comment above __nlCHECK */
|
|
|
|
#define __nlPRECONDITION_SUCCESS(flags, status, termination) __nlPRECONDITION(flags, status == 0, termination)
|
|
#define __nlPRECONDITION_SUCCESS_ACTION(flags, status, termination, action) __nlPRECONDITION_ACTION(flags, status == 0, termination, action)
|
|
#define __nlPRECONDITION_SUCCESS_PRINT(flags, status, termination, message) __nlPRECONDITION_PRINT(flags, status == 0, termination, message)
|
|
|
|
#define __nlNPRECONDITION(flags, condition, termination) __nlPRECONDITION(flags, !(condition), termination)
|
|
#define __nlNPRECONDITION_ACTION(flags, condition, termination, action) __nlPRECONDITION_ACTION(flags, !(condition), termination, action)
|
|
#define __nlNPRECONDITION_PRINT(flags, condition, termination, message) __nlPRECONDITION_PRINT(flags, !(condition), termination, message)
|
|
|
|
// __nlABORT
|
|
|
|
#define __nlABORT(flags, condition) __nlPRECONDITION(flags, condition, NL_ASSERT_ABORT())
|
|
|
|
#define __nlABORT_ACTION(flags, condition, action) __nlPRECONDITION_ACTION(flags, condition, NL_ASSERT_ABORT(), action)
|
|
|
|
#endif /* NLASSERT_INTERNAL_H */
|