qpc/include/qassert.h
Quantum Leaps 0e95d49224 5.1.0
2013-09-23 14:34:35 -04:00

210 lines
8.2 KiB
C

/*****************************************************************************
* Product: QP/C/C++/nano
* Last Updated for Version: 5.0.0
* Date of the Last Update: Sep 05, 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 2 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_ROM_VAR 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_ROM_VAR 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 Q_ROM_VAR 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 */