Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // File: dbc.h
- // SPDX-License-Identifier: Unlicensed
- //
- // This is free and unencumbered software released into the public domain.
- /*!
- * \file dbc.h
- *
- * \brief This header file defines macros that implement the
- * Design By Contract (DBC) protocol.
- *
- * The macro functions \c DBC_REQUIRE, \c DBC_ENSURE, and \c DBC_INVARIANT
- * are defined.
- *
- * If the macro \c DBC_ALL has been defined before this header file is
- * included, or none of the macros \c DBC_DISABLE, \c DBC_ENABLE_REQUIRE,
- * \c DBC_ENABLE_ENSURE, or \c DBC_ENABLE_INVARIANT have been defined then all
- * of the DBC-check macro functions perform the specified checks and report
- * error if appropriate.
- *
- * If only certain macro functions are required to perform their function then
- * the required macro functions can be enabled by defining the appropriate
- * \c DBC_ENABLE_REQUIRE, \c DBC_ENABLE_ENSURE, and/or DBC_ENABLE_INVARIANT
- * macros before including the \c dbc.h header file.
- *
- * \version 1.0
- * \date 2023
- */
- #ifndef DBC_H_
- #define DBC_H_
- #ifndef DBC_DISABLE
- #include <stdio.h> // for fprintf, stderr
- #include <stdbool.h> // for _Bool, true, false
- #include <stdlib.h> // for exit, EXIT_FAILURE
- /*!
- * \internal
- *
- * \def DBC_ALL
- *
- * \brief If this macro is defined then all of the \c DBC macros will be
- * defined.
- *
- * If none of the macros \c DBC_DISABLE, \c DBC_ENABLE_REQUIRE,
- * \c DBC_ENABLE_ENSURE, or \c DBC_ENABLE_INVARIANT have been defined then
- * all the DBC-check macros are implicitly defined.
- *
- * \endinternal
- */
- #if !( defined( DBC_ALL ) || defined( DBC_ENABLE_REQUIRE ) \
- || defined( DBC_ENABLE_ENSURE ) || defined( DBC_ENABLE_INVARIANT ) )
- // If none of the macros that control whether or not DBC
- // checks are enabled are defined then define them all
- #define DBC_ALL
- #define DBC_ENABLE_REQUIRE
- #define DBC_ENABLE_ENSURE
- #define DBC_ENABLE_INVARIANT
- #endif
- /*!
- * \def DBC_REQUIRE( pred )
- *
- * \brief This macro function is used to ensure that conditions are met at
- * the beginning of a function call.
- *
- * If the \c DBC_ENABLE_REQUIRE macro is defined then the \c DBC_REQUIRE macro
- * is defined, otherwise this macro does nothing.
- *
- * \param [in] pred The predicate that is to be tested to ensure that it
- * is true.
- */
- #ifndef DBC_REQUIRE
- #ifdef DBC_ENABLE_REQUIRE
- #define DBC_REQUIRE( pred ) DBC_ASSERT( pred, "Precondition", #pred, \
- __func__, __FILE__, __LINE__ )
- #else // if DBC_REQUIRE is not defined
- #define DBC_REQUIRE( ... )
- #endif
- #else // if DBC_REQUIRE is already defined
- #error "DBC_REQUIRE already defined"
- #endif
- /*!
- * \def DBC_ENSURE( pred )
- *
- * \brief This macro function is used to ensure that conditions are met at
- * the end of a function call.
- *
- * If the \c DBC_ENABLE_ENSURE macro is defined then the \c DBC_ENSURE
- * macro is defined, otherwise this macro does nothing.
- *
- * \param [in] pred The predicate that is to be tested to ensure that it
- * is true.
- */
- #ifndef DBC_ENSURE
- #ifdef DBC_ENABLE_ENSURE
- #define DBC_ENSURE( pred ) DBC_ASSERT( pred, "Postcondition", #pred, \
- __func__, __FILE__, __LINE__ )
- #else // if DBC_ENSURE is not defined
- #define DBC_ENSURE( pred )
- #endif
- #else // if DBC_ENSURE is already defined
- #error "DBC_ENSURE already defined"
- #endif
- /*!
- * \def DBC_INVARIANT( pred )
- *
- * \brief This macro function is used to ensure that conditions are met at
- * any point in the programs execution.
- *
- * If the \c DBC_ENABLE_INVARIANT macro is defined then the \c DBC_INVARIANT
- * macro is defined, otherwise this macro does nothing.
- *
- * \param [in] pred The predicate that is to be tested to ensure that it
- * is true.
- */
- #ifndef DBC_INVARIANT
- #if defined( DBC_ENABLE_INVARIANT )
- #define DBC_INVARIANT( pred ) DBC_ASSERT( pred, "Invariant", #pred, \
- __func__, __FILE__, __LINE__ )
- #else // if DBC_INVARIANT is not defined
- #define DBC_INVARIANT( pred )
- #endif
- #else // if DBC_INVARIANT is already defined
- #error "DBC_INVARIANT already defined"
- #endif
- /*!
- * \internal
- *
- * \def DBC_ASSERT( PRED, DBC_DESC, PRED_STR, FN_NAME, FILENAME, LINE )
- *
- * \brief This function is used to ensure that a condition is met.
- *
- * This macro function is used by all of the \c DBC-check macros.
- *
- * If the \p pred is not met then an error message is written to \c stderr and
- * the program is exited with exit code \c EXIT_FAILURE.
- *
- * \param [in] pred The predicate that is to be tested to ensure that
- * it is true.
- * \param [in] dbc_desc The type of DBC assertion (i.e. require, ensure,
- * or invariant). This parameter is used in the
- * construction of the assertion failure message that
- * is written to \c stderr if \p pred is not true.
- * \param [in] pred_str A string representation of the \p pred that is
- * being tested.
- * \param [in] fn_name The name of the function where the \p pred is
- * being tested.
- * \param [in] filename The name of the file where the \p fn_name resides.
- * \param [in] line The line number of the file where the test is
- * occurring.
- *
- * \see DBC_REQUIRE
- * \see DBC_ENSURE
- * \see DBC_INVARIANT
- *
- * \endinternal
- */
- #ifndef DBC_ASSERT
- #define DBC_ASSERT( pred, dbc_desc, pred_str, fn_name, filename, line ) \
- do { \
- if ( !( pred ) ) { \
- fprintf( stderr, \
- "%s: Assertion failed: Error " \
- "%s: <%s> file <%s> line %d.\n", \
- dbc_desc, pred_str, fn_name, filename, line ); \
- exit( EXIT_FAILURE ); \
- } \
- } while (0)
- #else // if DBC_ASSERT is already defined
- #error "DBC_ASSERT already defined"
- #endif
- #else // if DBC_DISABLE is defined
- // Define the DBC_REQUIRE, DBC_ENSURE, DBC_INVARIANT, and DBC_ASSERT macros,
- // thereby disabling all DBC-checks.
- #define DBC_REQUIRE( ... )
- #define DBC_ENSURE( ... )
- #define DBC_INVARIANT( ... )
- #define DBC_ASSERT( ... )
- #endif
- #endif // DBC_H_
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement