qpcpp/include/qassert.h

339 lines
12 KiB
C
Raw Normal View History

2014-04-13 21:35:34 -04:00
/**
2015-05-14 16:05:04 -04:00
* @file
* @brief Customizable and memory-efficient assertions for embedded systems
* @cond
2014-04-13 21:35:34 -04:00
******************************************************************************
2018-05-10 14:39:45 -04:00
* Last updated for version 6.3.0
* Last updated on 2018-05-09
2012-08-14 18:00:48 -04:00
*
* Q u a n t u m L e a P s
* ---------------------------
* innovating embedded systems
*
2018-03-19 14:51:26 -04:00
* Copyright (C) 2002-2018 Quantum Leaps, LLC. All rights reserved.
2012-08-14 18:00:48 -04:00
*
* This program is open source software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
2012-08-14 18:00:48 -04:00
* (at your option) any later version.
*
* Alternatively, this program may be distributed and modified under the
* terms of Quantum Leaps commercial licenses, which expressly supersede
* the GNU General Public License and are specifically designed for
* licensees interested in retaining the proprietary status of their code.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Contact information:
2018-03-19 14:51:26 -04:00
* https://www.state-machine.com
2015-12-31 14:56:37 -05:00
* mailto:info@state-machine.com
2014-04-13 21:35:34 -04:00
******************************************************************************
2015-05-14 16:05:04 -04:00
* @endcond
2014-04-13 21:35:34 -04:00
*/
2012-08-14 18:00:48 -04:00
#ifndef qassert_h
#define qassert_h
/**
2015-05-14 16:05:04 -04:00
* @note
2014-04-13 21:35:34 -04:00
* This header file can be used in C, C++, and mixed C/C++ programs.
2012-08-14 18:00:48 -04:00
*
2015-05-14 16:05:04 -04:00
* @note The preprocessor switch #Q_NASSERT disables checking assertions.
2014-04-13 21:35:34 -04:00
* However, it is generally __not__ advisable to disable assertions,
* __especially__ in the production code. Instead, the assertion handler
* Q_onAssert() should be very carefully designed and tested.
2012-08-14 18:00:48 -04:00
*/
2014-04-13 21:35:34 -04:00
#ifdef Q_NASSERT /* Q_NASSERT defined--assertion checking disabled */
2012-08-14 18:00:48 -04:00
2018-04-20 16:16:53 -04:00
/* provide dummy (empty) definitions that don't generate any code... */
2012-08-14 18:00:48 -04:00
#define Q_DEFINE_THIS_FILE
#define Q_DEFINE_THIS_MODULE(name_)
#define Q_ASSERT(test_) ((void)0)
#define Q_ASSERT_ID(id_, test_) ((void)0)
#define Q_ALLEGE(test_) ((void)(test_))
#define Q_ALLEGE_ID(id_, test_) ((void)(test_))
#define Q_ERROR() ((void)0)
#define Q_ERROR_ID(id_) ((void)0)
2017-07-20 13:06:27 -04:00
#define Q_REQUIRE(test_) ((void)0)
#define Q_REQUIRE_ID(id_, test_) ((void)0)
#define Q_ENSURE(test_) ((void)0)
#define Q_ENSURE_ID(id_, test_) ((void)0)
#define Q_INVARIANT(test_) ((void)0)
#define Q_INVARIANT_ID(id_, test_) ((void)0)
2012-08-14 18:00:48 -04:00
2014-04-13 21:35:34 -04:00
#else /* Q_NASSERT not defined--assertion checking enabled */
2012-08-14 18:00:48 -04:00
2018-04-20 16:16:53 -04:00
#ifndef qep_h /* QEP not included (i.e., is quassert.h used outside QP? */
/* provide typedefs so that qassert.h could be used "standalone"... */
/*! typedef for character strings. */
/**
* @description
* This typedef specifies character type for exclusive use in character
* strings. Use of this type, rather than plain 'char', is in compliance
* with the MISRA-C 2004 Rules 6.1(req), 6.3(adv).
*/
typedef char char_t;
/*! typedef for assertions-ids and line numbers in assertions. */
/**
* @description
* This typedef specifies integer type for exclusive use in assertions.
* Use of this type, rather than plain 'int', is in compliance
* with the MISRA-C 2004 Rules 6.1(req), 6.3(adv).
*/
typedef int int_t;
#endif
2014-04-13 21:35:34 -04:00
/*! Define the file name (with `__FILE__`) for assertions in this file. */
/**
2015-05-14 16:05:04 -04:00
* @description
2014-04-13 21:35:34 -04:00
* Macro to be placed at the top of each C/C++ module to define the
* single instance of the file name string to be used in reporting
* assertions in this module.
*
2015-05-14 16:05:04 -04:00
* @note The file name string literal is defined by means of the standard
2014-04-13 21:35:34 -04:00
* preprocessor macro `__FILE__`. However, please note that, depending
* on the compiler, the `__FILE__` macro might contain the whole path name
* to the file, which might be inconvenient to log assertions.
2015-05-14 16:05:04 -04:00
* @note This macro should __not__ be terminated by a semicolon.
* @sa Q_DEFINE_THIS_MODULE()
2012-08-14 18:00:48 -04:00
*/
#define Q_DEFINE_THIS_FILE \
2015-12-31 14:56:37 -05:00
static char_t const Q_this_module_[] = __FILE__;
2012-08-14 18:00:48 -04:00
2014-04-13 21:35:34 -04:00
/*! Define the user-specified module name for assertions in this file. */
/**
2015-05-14 16:05:04 -04:00
* @description
2014-04-13 21:35:34 -04:00
* Macro to be placed at the top of each C/C++ module to define the
* single instance of the module name string to be used in reporting
2015-05-14 16:05:04 -04:00
* assertions in this module. This macro takes the user-supplied parameter
* @p name_ instead of `__FILE__` to precisely control the name of the
2014-04-13 21:35:34 -04:00
* module.
*
2015-05-14 16:05:04 -04:00
* @param[in] name_ string constant representing the module name
2014-04-13 21:35:34 -04:00
*
2015-05-14 16:05:04 -04:00
* @note This macro should __not__ be terminated by a semicolon.
2012-08-14 18:00:48 -04:00
*/
#define Q_DEFINE_THIS_MODULE(name_) \
2015-12-31 14:56:37 -05:00
static char_t const Q_this_module_[] = name_;
2012-08-14 18:00:48 -04:00
2014-04-13 21:35:34 -04:00
/*! General purpose assertion. */
/**
2015-05-14 16:05:04 -04:00
* @description
* Makes sure the @p test_ parameter is TRUE. Calls the Q_onAssert()
* callback if the @p test_ expression evaluates to FALSE. This
2014-04-13 21:35:34 -04:00
* macro identifies the assertion location within the file by means
* of the standard `__LINE__` macro.
*
2015-05-14 16:05:04 -04:00
* @param[in] test_ Boolean expression
2014-04-13 21:35:34 -04:00
*
2015-05-14 16:05:04 -04:00
* @note the @p test_ is __not__ evaluated if assertions are disabled
2014-04-13 21:35:34 -04:00
* with the #Q_NASSERT switch.
2012-08-14 18:00:48 -04:00
*/
2013-10-10 20:01:51 -04:00
#define Q_ASSERT(test_) ((test_) \
? (void)0 : Q_onAssert(&Q_this_module_[0], (int_t)__LINE__))
2012-08-14 18:00:48 -04:00
2014-04-13 21:35:34 -04:00
/*! General purpose assertion with user-specified assertion-id. */
/**
2015-05-14 16:05:04 -04:00
* @description
* Makes sure the @p test_ parameter is TRUE. Calls the Q_onAssert()
* callback if the @p test_ evaluates to FALSE. This assertion takes the
* user-supplied parameter @p id_ to identify the location of this
2014-04-13 21:35:34 -04:00
* assertion within the file. This avoids the volatility of using line
* numbers, which change whenever a line of code is added or removed
* upstream from the assertion.
*
2015-05-14 16:05:04 -04:00
* @param[in] id_ ID number (unique within the module) of the assertion
* @param[in] test_ Boolean expression
2014-04-13 21:35:34 -04:00
*
2015-05-14 16:05:04 -04:00
* @note the @p test_ expression is __not__ evaluated if assertions are
2014-04-13 21:35:34 -04:00
* disabled with the #Q_NASSERT switch.
2012-08-14 18:00:48 -04:00
*/
2013-10-10 20:01:51 -04:00
#define Q_ASSERT_ID(id_, test_) ((test_) \
2014-04-13 21:35:34 -04:00
? (void)0 : Q_onAssert(&Q_this_module_[0], (int_t)(id_)))
2015-05-14 16:05:04 -04:00
/*! General purpose assertion that __always__ evaluates the @p test_
2014-04-13 21:35:34 -04:00
* expression. */
/**
2015-05-14 16:05:04 -04:00
* @description
* Like the Q_ASSERT() macro, except it __always__ evaluates the @p test_
2014-04-13 21:35:34 -04:00
* expression even when assertions are disabled with the #Q_NASSERT macro.
* However, when the #Q_NASSERT macro is defined, the Q_onAssert()
2015-05-14 16:05:04 -04:00
* callback is __not__ called, even if @p test_ evaluates to FALSE.
2014-04-13 21:35:34 -04:00
*
2015-05-14 16:05:04 -04:00
* @param[in] test_ Boolean expression (__always__ evaluated)
2014-04-13 21:35:34 -04:00
*
2015-05-14 16:05:04 -04:00
* @sa #Q_ALLEGE_ID
2012-08-14 18:00:48 -04:00
*/
#define Q_ALLEGE(test_) Q_ASSERT(test_)
2014-04-13 21:35:34 -04:00
/*! General purpose assertion with user-specified assertion-id that
2015-05-14 16:05:04 -04:00
* __always__ evaluates the @p test_ expression. */
2014-04-13 21:35:34 -04:00
/**
2015-05-14 16:05:04 -04:00
* @description
2014-04-13 21:35:34 -04:00
* Like the Q_ASSERT_ID() macro, except it __always__ evaluates the
2015-05-14 16:05:04 -04:00
* @p test_ expression even when assertions are disabled with the
2014-04-13 21:35:34 -04:00
* #Q_NASSERT macro. However, when the #Q_NASSERT macro is defined, the
2015-05-14 16:05:04 -04:00
* Q_onAssert() callback is __not__ called, even if @p test_ evaluates
2014-04-13 21:35:34 -04:00
* to FALSE.
*
2015-05-14 16:05:04 -04:00
* @param[in] id_ ID number (unique within the module) of the assertion
* @param[in] test_ Boolean expression
2012-08-14 18:00:48 -04:00
*/
2015-05-14 16:05:04 -04:00
#define Q_ALLEGE_ID(id_, test_) Q_ASSERT_ID((id_), (test_))
2012-08-14 18:00:48 -04:00
2014-04-13 21:35:34 -04:00
/*! Assertion for a wrong path through the code. */
/**
2015-05-14 16:05:04 -04:00
* @description
2014-04-13 21:35:34 -04:00
* Calls the Q_onAssert() callback if ever executed.
*
2015-05-14 16:05:04 -04:00
* @note Does noting if assertions are disabled with the #Q_NASSERT switch.
2012-08-14 18:00:48 -04:00
*/
#define Q_ERROR() \
2013-10-10 20:01:51 -04:00
Q_onAssert(&Q_this_module_[0], (int_t)__LINE__)
2012-08-14 18:00:48 -04:00
2014-04-13 21:35:34 -04:00
/*! Assertion with user-specified assertion-id for a wrong path. */
/**
2015-05-14 16:05:04 -04:00
* @description
2014-04-13 21:35:34 -04:00
* Calls the Q_onAssert() callback if ever executed. This assertion
2015-05-14 16:05:04 -04:00
* takes the user-supplied parameter @p id_ to identify the location of
2014-04-13 21:35:34 -04:00
* this assertion within the file. This avoids the volatility of using
* line numbers, which change whenever a line of code is added or removed
* upstream from the assertion.
*
2015-05-14 16:05:04 -04:00
* @param[in] id_ ID number (unique within the module) of the assertion
2014-04-13 21:35:34 -04:00
*
2015-05-14 16:05:04 -04:00
* @note Does noting if assertions are disabled with the #Q_NASSERT switch.
2012-08-14 18:00:48 -04:00
*/
#define Q_ERROR_ID(id_) \
2013-10-10 20:01:51 -04:00
Q_onAssert(&Q_this_module_[0], (int_t)(id_))
2012-08-14 18:00:48 -04:00
2014-04-13 21:35:34 -04:00
#endif /* Q_NASSERT */
2012-08-14 18:00:48 -04:00
2012-12-10 16:01:54 -05:00
#ifdef __cplusplus
extern "C" {
#endif
2014-04-13 21:35:34 -04:00
/*! Callback function invoked in case of any assertion failure. */
/**
2015-05-14 16:05:04 -04:00
* @description
2014-04-13 21:35:34 -04:00
* This is an application-specific callback function needs to be defined in
* the application to perform the clean system shutdown and perhaps a reset.
*
2015-05-14 16:05:04 -04:00
* @param[in] module name of the file/module in which the assertion failed
2015-12-31 14:56:37 -05:00
* (constant, zero-terminated C string)
2015-09-29 11:34:38 -04:00
* @param[in] loc location of the assertion within the module. This could
* be a line number or a user-specified ID-number.
2014-04-13 21:35:34 -04:00
*
2015-05-14 16:05:04 -04:00
* @note This callback function should _not_ return, as continuation after
2014-04-13 21:35:34 -04:00
* an assertion failure does not make sense.
*
2015-05-14 16:05:04 -04:00
* @note The Q_onAssert() function is the last line of defense after the
2014-04-13 21:35:34 -04:00
* system failure and its implementation shouild be very __carefully__
* designed and __tested__ under various fault conditions, including but
* not limited to: stack overflow, stack corruption, or calling Q_onAssert()
* from an interrupt.
2012-12-10 16:01:54 -05:00
*
2015-05-14 16:05:04 -04:00
* @note It is typically a __bad idea__ to implement Q_onAssert() as an
2014-04-13 21:35:34 -04:00
* endless loop that ties up the CPU. During debuggin, Q_onAssert() is an
* ideal place to put a breakpoint.
*
* Called by the following macros: #Q_ASSERT, #Q_REQUIRE, #Q_ENSURE,
* #Q_ERROR, #Q_ALLEGE as well as #Q_ASSERT_ID, #Q_REQUIRE_ID, #Q_ENSURE_ID,
* #Q_ERROR_ID, and #Q_ALLEGE_ID.
2012-12-10 16:01:54 -05:00
*/
2015-12-31 14:56:37 -05:00
void Q_onAssert(char_t const * const module, int_t location);
2012-12-10 16:01:54 -05:00
#ifdef __cplusplus
}
#endif
2014-04-13 21:35:34 -04:00
/*! Assertion for checking preconditions. */
/**
2015-05-14 16:05:04 -04:00
* @description
2014-04-13 21:35:34 -04:00
* This macro is equivalent to #Q_ASSERT, except the name provides a better
* documentation of the intention of this assertion.
*
2015-05-14 16:05:04 -04:00
* @param[in] test_ Boolean expression
2012-08-14 18:00:48 -04:00
*/
#define Q_REQUIRE(test_) Q_ASSERT(test_)
2014-04-13 21:35:34 -04:00
/*! Assertion for checking preconditions with user-specified assertion-id. */
/**
2015-05-14 16:05:04 -04:00
* @description
2014-04-13 21:35:34 -04:00
* Equivalent to #Q_ASSERT_ID, except the macro name provides a better
* documentation of the intention of this assertion.
*
2015-05-14 16:05:04 -04:00
* @param[in] id_ ID number (unique within the module) of the assertion
* @param[in] test_ Boolean expression
2012-08-14 18:00:48 -04:00
*/
2015-05-14 16:05:04 -04:00
#define Q_REQUIRE_ID(id_, test_) Q_ASSERT_ID((id_), (test_))
2012-08-14 18:00:48 -04:00
2014-04-13 21:35:34 -04:00
/*! Assertion for checking postconditions. */
/** Equivalent to #Q_ASSERT, except the macro name provides a better
* documentation of the intention of this assertion.
*
2015-05-14 16:05:04 -04:00
* @param[in] test_ Boolean expression
2012-08-14 18:00:48 -04:00
*/
2014-04-13 21:35:34 -04:00
#define Q_ENSURE(test_) Q_ASSERT(test_)
2012-08-14 18:00:48 -04:00
2014-04-13 21:35:34 -04:00
/*! Assertion for checking postconditions with user-specified assertion-id. */
/**
2015-05-14 16:05:04 -04:00
* @description
2014-04-13 21:35:34 -04:00
* Equivalent to #Q_ASSERT_ID, except the name provides a better documentation
* of the intention of this assertion.
*
2015-05-14 16:05:04 -04:00
* @param[in] id_ ID number (unique within the module) of the assertion
* @param[in] test_ Boolean expression
2012-08-14 18:00:48 -04:00
*/
2015-05-14 16:05:04 -04:00
#define Q_ENSURE_ID(id_, test_) Q_ASSERT_ID((id_), (test_))
2012-08-14 18:00:48 -04:00
2014-04-13 21:35:34 -04:00
/*! Assertion for checking invariants. */
/**
2015-05-14 16:05:04 -04:00
* @description
2014-04-13 21:35:34 -04:00
* Equivalent to #Q_ASSERT, except the macro name provides a better
* documentation of the intention of this assertion.
*
2015-05-14 16:05:04 -04:00
* @param[in] test_ Boolean expression
2012-08-14 18:00:48 -04:00
*/
2014-04-13 21:35:34 -04:00
#define Q_INVARIANT(test_) Q_ASSERT(test_)
2012-08-14 18:00:48 -04:00
2014-04-13 21:35:34 -04:00
/*! Assertion for checking invariants with user-specified assertion-id. */
/**
2015-05-14 16:05:04 -04:00
* @description
2014-04-13 21:35:34 -04:00
* Equivalent to #Q_ASSERT_ID, except the macro name provides a better
* documentation of the intention of this assertion.
*
2015-05-14 16:05:04 -04:00
* @param[in] id_ ID number (unique within the module) of the assertion
* @param[in] test_ Boolean expression
2012-08-14 18:00:48 -04:00
*/
2015-05-14 16:05:04 -04:00
#define Q_INVARIANT_ID(id_, test_) Q_ASSERT_ID((id_), (test_))
2012-08-14 18:00:48 -04:00
2014-04-13 21:35:34 -04:00
/*! Compile-time assertion. */
/**
2015-05-14 16:05:04 -04:00
* @description
2014-04-13 21:35:34 -04:00
* This type of assertion deliberately causes a compile-time error when
2015-05-14 16:05:04 -04:00
* the @p test_ evaluates to FALSE. The macro exploits the fact that in C/C++
2014-04-13 21:35:34 -04:00
* a dimension of an array cannot be negative. The compile-time assertion has
* no runtime side effects.
*
2015-05-14 16:05:04 -04:00
* @param[in] test_ Compile-time Boolean expression
2012-08-14 18:00:48 -04:00
*/
#define Q_ASSERT_COMPILE(test_) \
extern int_t Q_assert_compile[(test_) ? 1 : -1]
2018-05-10 14:39:45 -04:00
/*! Helper macro to calculate static dimension of a 1-dim @p array_ */
#define Q_DIM(array_) (sizeof(array_) / sizeof((array_)[0]))
2014-04-13 21:35:34 -04:00
#endif /* qassert_h */
2018-03-19 14:51:26 -04:00