mirror of
https://github.com/QuantumLeaps/qpcpp.git
synced 2025-01-14 05:42:57 +08:00
210 lines
8.2 KiB
C
210 lines
8.2 KiB
C
/*****************************************************************************
|
|
* Product: QP/C/C++/nano
|
|
* Last Updated for Version: 5.2.0
|
|
* Date of the Last Update: Nov 22, 2013
|
|
*
|
|
* Q u a n t u m L e a P s
|
|
* ---------------------------
|
|
* innovating embedded systems
|
|
*
|
|
* Copyright (C) 2002-2013 Quantum Leaps, LLC. All rights reserved.
|
|
*
|
|
* 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
|
|
* (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:
|
|
* Quantum Leaps Web sites: http://www.quantum-leaps.com
|
|
* http://www.state-machine.com
|
|
* e-mail: info@quantum-leaps.com
|
|
*****************************************************************************/
|
|
#ifndef qassert_h
|
|
#define qassert_h
|
|
|
|
/**
|
|
* \file
|
|
* \brief Customizable QP assertions.
|
|
*
|
|
* Defines customizable and memory-efficient assertions applicable to
|
|
* embedded systems. This header file can be used in C, C++, and mixed C/C++
|
|
* programs.
|
|
*
|
|
* \note The preprocessor switch #Q_NASSERT disables checking assertions.
|
|
*/
|
|
#ifdef Q_NASSERT /* Q_NASSERT defined--assertion checking disabled */
|
|
|
|
#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)
|
|
|
|
#else /* Q_NASSERT not defined--assertion checking enabled */
|
|
|
|
/** Place this macro at the top of each C/C++ module to define the file
|
|
* name string using __FILE__ (NOTE: __FILE__ might contain lengthy path
|
|
* name). This name will be used in reporting assertions in this module.
|
|
*/
|
|
#define Q_DEFINE_THIS_FILE \
|
|
static char_t const Q_ROM Q_this_module_[] = __FILE__;
|
|
|
|
/** Place this macro at the top of each C/C++ module to define the module
|
|
* name as the argument \a name_. This name will be used in reporting
|
|
* assertions in this module.
|
|
*/
|
|
#define Q_DEFINE_THIS_MODULE(name_) \
|
|
static char_t const Q_ROM Q_this_module_[] = name_;
|
|
|
|
/** General purpose assertion that makes sure the \a test_ argument is
|
|
* TRUE. Calls the Q_onAssert() callback if the \a test_ evaluates
|
|
* to FALSE.
|
|
* \note the \a test_ is NOT evaluated if assertions are disabled with
|
|
* the #Q_NASSERT switch.
|
|
* \sa #Q_ASSERT_ID
|
|
*/
|
|
#define Q_ASSERT(test_) ((test_) \
|
|
? (void)0 : Q_onAssert(&Q_this_module_[0], (int_t)__LINE__))
|
|
|
|
/** General purpose assertion that makes sure the \a test_ argument is
|
|
* TRUE. Calls the Q_onAssert() callback if the \a test_ evaluates
|
|
* to FALSE. The argument \a id_ is the ID number (unique within
|
|
* the module) of the assertion. This assertion style is better suited
|
|
* for unit testing, because it avoids the volatility of line numbers
|
|
* for identifying assertions.
|
|
* \note the \a test_ is NOT evaluated if assertions are disabled with
|
|
* the #Q_NASSERT switch.
|
|
* \sa #Q_ASSERT
|
|
*/
|
|
#define Q_ASSERT_ID(id_, test_) ((test_) \
|
|
? (void)0 : Q_onAssert(&Q_this_module_[0], (int_t)(id_))
|
|
|
|
/** General purpose assertion that ALWAYS evaluates the \a test_
|
|
* argument and calls the Q_onAssert() callback if the \a test_
|
|
* evaluates to FALSE.
|
|
* \note the \a test_ argument IS always evaluated even when assertions
|
|
* are disabled with the #Q_NASSERT macro. When the #Q_NASSERT macro is
|
|
* defined, the Q_onAssert() callback is NOT called, even if the
|
|
* \a test_ evaluates to FALSE.
|
|
* \sa #Q_ALLEGE_ID
|
|
*/
|
|
#define Q_ALLEGE(test_) Q_ASSERT(test_)
|
|
|
|
/** General purpose assertion that ALWAYS evaluates the \a test_
|
|
* argument and calls the Q_onAssert() callback if the \a test_
|
|
* evaluates to FALSE. This assertion style is better suited
|
|
* for unit testing, because it avoids the volatility of line numbers
|
|
* for identifying assertions.
|
|
* \note the \a test_ argument IS always evaluated even when assertions
|
|
* are disabled with the #Q_NASSERT macro. When the #Q_NASSERT macro is
|
|
* defined, the Q_onAssert() callback is NOT called, even if the
|
|
* \a test_ evaluates to FALSE.
|
|
* \sa #Q_ALLEGE
|
|
*/
|
|
#define Q_ALLEGE_ID(id_, test_) Q_ASSERT_ID(id_, test_)
|
|
|
|
/** Assertion that always calls the Q_onAssert() callback if
|
|
* ever executed.
|
|
* \note can be disabled with the #Q_NASSERT switch.
|
|
* \sa #Q_ERROR_ID
|
|
*/
|
|
#define Q_ERROR() \
|
|
Q_onAssert(&Q_this_module_[0], (int_t)__LINE__)
|
|
|
|
/** Assertion that always calls the Q_onAssert() callback if
|
|
* ever executed. This assertion style is better suited for unit
|
|
* testing, because it avoids the volatility of line numbers for
|
|
* identifying assertions.
|
|
* \note can be disabled with the #Q_NASSERT switch.
|
|
* \sa #Q_ERROR
|
|
*/
|
|
#define Q_ERROR_ID(id_) \
|
|
Q_onAssert(&Q_this_module_[0], (int_t)(id_))
|
|
|
|
#endif /* Q_NASSERT */
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/** callback invoked in case the condition passed to #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 evaluates to FALSE.
|
|
*
|
|
* \param module name where the assertion failed
|
|
* \param line number at which the assertion failed
|
|
*/
|
|
void Q_onAssert(char_t const Q_ROM * const module, int_t line);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
/** Assertion that checks for a precondition. This macro is equivalent to
|
|
* #Q_ASSERT, except the name provides a better documentation of the
|
|
* intention of this assertion.
|
|
* \sa #Q_REQUIRE_ID
|
|
*/
|
|
#define Q_REQUIRE(test_) Q_ASSERT(test_)
|
|
|
|
/** Assertion that checks for a precondition. This macro is equivalent to
|
|
* #Q_ASSERT_ID, except the name provides a better documentation of the
|
|
* intention of this assertion.
|
|
* \sa #Q_REQUIRE
|
|
*/
|
|
#define Q_REQUIRE_ID(id_, test_) Q_ASSERT_ID(id_, test_)
|
|
|
|
/** Assertion that checks for a postcondition. This macro is equivalent to
|
|
* #Q_ASSERT, except the name provides a better documentation of the
|
|
* intention of this assertion.
|
|
* \sa #Q_ENSURE_ID
|
|
*/
|
|
#define Q_ENSURE(test_) Q_ASSERT(test_)
|
|
|
|
/** Assertion that checks for a postcondition. This macro is equivalent to
|
|
* #Q_ASSERT_ID, except the name provides a better documentation of the
|
|
* intention of this assertion.
|
|
* \sa #Q_ENSURE
|
|
*/
|
|
#define Q_ENSURE_ID(id_, test_) Q_ASSERT_ID(id_, test_)
|
|
|
|
/** Assertion that checks for an invariant. This macro is equivalent to
|
|
* #Q_ASSERT, except the name provides a better documentation of the
|
|
* intention of this assertion.
|
|
* \sa #Q_INVARIANT_ID
|
|
*/
|
|
#define Q_INVARIANT(test_) Q_ASSERT(test_)
|
|
|
|
/** Assertion that checks for an invariant. This macro is equivalent to
|
|
* #Q_ASSERT_ID, except the name provides a better documentation of the
|
|
* intention of this assertion.
|
|
* \sa #Q_INVARIANT
|
|
*/
|
|
#define Q_INVARIANT_ID(id_, test_) Q_ASSERT_ID(id_, test_)
|
|
|
|
/** Compile-time assertion exploits the fact that in C/C++ a dimension of
|
|
* an array cannot be negative. The following declaration causes a compilation
|
|
* error if the compile-time expression (\a test_) is not TRUE. The assertion
|
|
* has no runtime side effects.
|
|
*/
|
|
#define Q_ASSERT_COMPILE(test_) \
|
|
extern int_t Q_assert_compile[(test_) ? 1 : -1]
|
|
|
|
#endif /* qassert_h */
|