alpar@209: /* -*- mode: C++; indent-tabs-mode: nil; -*- kpeter@66: * alpar@209: * This file is a part of LEMON, a generic C++ optimization library. kpeter@66: * kpeter@66: * Copyright (C) 2003-2008 kpeter@66: * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport kpeter@66: * (Egervary Research Group on Combinatorial Optimization, EGRES). kpeter@66: * kpeter@66: * Permission to use, modify and distribute this software is granted kpeter@66: * provided that this copyright notice appears in all copies. For kpeter@66: * precise terms see the accompanying LICENSE file. kpeter@66: * kpeter@66: * This software is provided "AS IS" with no warranty of any kind, kpeter@66: * express or implied, and with no claim as to its suitability for any kpeter@66: * purpose. kpeter@66: * kpeter@66: */ kpeter@66: deba@108: #ifndef LEMON_ASSERT_H deba@108: #define LEMON_ASSERT_H kpeter@66: kpeter@66: /// \ingroup exceptions kpeter@66: /// \file deba@108: /// \brief Extended assertion handling kpeter@66: deba@108: #include kpeter@66: kpeter@66: namespace lemon { kpeter@66: deba@108: inline void assert_fail_log(const char *file, int line, const char *function, alpar@209: const char *message, const char *assertion) kpeter@66: { deba@108: std::cerr << file << ":" << line << ": "; deba@108: if (function) deba@108: std::cerr << function << ": "; deba@108: std::cerr << message; kpeter@66: if (assertion) deba@108: std::cerr << " (assertion '" << assertion << "' failed)"; deba@108: std::cerr << std::endl; kpeter@66: } kpeter@66: deba@108: inline void assert_fail_abort(const char *file, int line, alpar@209: const char *function, const char* message, alpar@209: const char *assertion) deba@108: { kpeter@112: assert_fail_log(file, line, function, message, assertion); deba@108: std::abort(); deba@108: } deba@108: deba@118: namespace _assert_bits { alpar@209: alpar@209: deba@118: inline const char* cstringify(const std::string& str) { deba@118: return str.c_str(); deba@118: } deba@118: deba@118: inline const char* cstringify(const char* str) { deba@118: return str; alpar@209: } deba@108: } deba@118: } deba@108: deba@108: #endif // LEMON_ASSERT_H kpeter@66: kpeter@66: #undef LEMON_ASSERT kpeter@66: #undef LEMON_FIXME deba@118: #undef LEMON_DEBUG kpeter@66: kpeter@212: #if (defined(LEMON_ASSERT_LOG) ? 1 : 0) + \ kpeter@212: (defined(LEMON_ASSERT_ABORT) ? 1 : 0) + \ deba@108: (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) > 1 kpeter@112: #error "LEMON assertion system is not set properly" kpeter@66: #endif kpeter@66: kpeter@212: #if ((defined(LEMON_ASSERT_LOG) ? 1 : 0) + \ kpeter@212: (defined(LEMON_ASSERT_ABORT) ? 1 : 0) + \ kpeter@212: (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) == 1 || \ kpeter@212: defined(LEMON_ENABLE_ASSERTS)) && \ kpeter@212: (defined(LEMON_DISABLE_ASSERTS) || \ deba@118: defined(NDEBUG)) kpeter@112: #error "LEMON assertion system is not set properly" kpeter@66: #endif kpeter@66: deba@108: deba@108: #if defined LEMON_ASSERT_LOG deba@108: # undef LEMON_ASSERT_HANDLER deba@108: # define LEMON_ASSERT_HANDLER ::lemon::assert_fail_log deba@108: #elif defined LEMON_ASSERT_ABORT deba@108: # undef LEMON_ASSERT_HANDLER deba@108: # define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort deba@108: #elif defined LEMON_ASSERT_CUSTOM deba@108: # undef LEMON_ASSERT_HANDLER deba@108: # ifndef LEMON_CUSTOM_ASSERT_HANDLER deba@108: # error "LEMON_CUSTOM_ASSERT_HANDLER is not set" kpeter@66: # endif deba@108: # define LEMON_ASSERT_HANDLER LEMON_CUSTOM_ASSERT_HANDLER deba@118: #elif defined LEMON_DISABLE_ASSERTS deba@108: # undef LEMON_ASSERT_HANDLER deba@118: #elif defined NDEBUG deba@118: # undef LEMON_ASSERT_HANDLER deba@118: #else deba@108: # define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort deba@108: #endif deba@108: deba@108: #ifndef LEMON_FUNCTION_NAME ladanyi@142: # if defined __GNUC__ ladanyi@142: # define LEMON_FUNCTION_NAME (__PRETTY_FUNCTION__) ladanyi@142: # elif defined _MSC_VER ladanyi@142: # define LEMON_FUNCTION_NAME (__FUNCSIG__) ladanyi@142: # else ladanyi@142: # define LEMON_FUNCTION_NAME (__func__) ladanyi@142: # endif kpeter@66: #endif kpeter@66: kpeter@66: #ifdef DOXYGEN kpeter@66: deba@108: /// \ingroup exceptions deba@108: /// kpeter@112: /// \brief Macro for assertion with customizable message kpeter@66: /// deba@118: /// Macro for assertion with customizable message. \param exp An deba@118: /// expression that must be convertible to \c bool. If it is \c deba@118: /// false, then an assertion is raised. The concrete behaviour depends deba@118: /// on the settings of the assertion system. \param msg A const deba@118: /// char* parameter, which can be used to provide information deba@118: /// about the circumstances of the failed assertion. kpeter@66: /// deba@118: /// The assertions are enabled in the default behaviour. deba@118: /// You can disable them with the following code: kpeter@66: /// \code deba@118: /// #define LEMON_DISABLE_ASSERTS kpeter@66: /// \endcode deba@108: /// or with compilation parameters: deba@108: /// \code deba@118: /// g++ -DLEMON_DISABLE_ASSERTS deba@118: /// make CXXFLAGS='-DLEMON_DISABLE_ASSERTS' deba@108: /// \endcode deba@118: /// The checking is also disabled when the standard macro \c NDEBUG is defined. alpar@209: /// kpeter@112: /// The LEMON assertion system has a wide range of customization kpeter@112: /// properties. As a default behaviour the failed assertion prints a kpeter@112: /// short log message to the standard error and aborts the execution. kpeter@66: /// alpar@209: /// The following modes can be used in the assertion system: kpeter@66: /// kpeter@112: /// - \c LEMON_ASSERT_LOG The failed assertion prints a short log kpeter@112: /// message to the standard error and continues the execution. deba@118: /// - \c LEMON_ASSERT_ABORT This mode is similar to the \c deba@118: /// LEMON_ASSERT_LOG, but it aborts the program. It is the default deba@118: /// behaviour. kpeter@112: /// - \c LEMON_ASSERT_CUSTOM The user can define own assertion handler deba@118: /// function. deba@108: /// \code alpar@210: /// void custom_assert_handler(const char* file, int line, alpar@210: /// const char* function, const char* message, alpar@210: /// const char* assertion); deba@108: /// \endcode deba@118: /// The name of the function should be defined as the \c alpar@209: /// LEMON_CUSTOM_ASSERT_HANDLER macro name. deba@108: /// \code deba@108: /// #define LEMON_CUSTOM_ASSERT_HANDLER custom_assert_handler deba@108: /// \endcode deba@118: /// Whenever an assertion is occured, the custom assertion deba@118: /// handler is called with appropiate parameters. kpeter@66: /// kpeter@112: /// The assertion mode can also be changed within one compilation unit. kpeter@112: /// If the macros are redefined with other settings and the kpeter@112: /// \ref lemon/assert.h "assert.h" file is reincluded, then the kpeter@112: /// behaviour is changed appropiately to the new settings. alpar@209: # define LEMON_ASSERT(exp, msg) \ kpeter@212: (static_cast (!!(exp) ? 0 : ( \ kpeter@212: LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \ kpeter@212: LEMON_FUNCTION_NAME, \ alpar@209: ::lemon::_assert_bits::cstringify(msg), #exp), 0))) deba@108: deba@108: /// \ingroup exceptions kpeter@66: /// deba@108: /// \brief Macro for mark not yet implemented features. deba@108: /// deba@108: /// Macro for mark not yet implemented features and outstanding bugs. deba@108: /// It is close to be the shortcut of the following code: deba@108: /// \code deba@108: /// LEMON_ASSERT(false, msg); deba@108: /// \endcode deba@118: /// alpar@209: /// \see LEMON_ASSERT kpeter@212: # define LEMON_FIXME(msg) \ alpar@209: (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME, \ kpeter@212: ::lemon::_assert_bits::cstringify(msg), \ alpar@209: static_cast(0))) deba@118: deba@118: /// \ingroup exceptions deba@118: /// deba@118: /// \brief Macro for internal assertions deba@118: /// deba@118: /// Macro for internal assertions, it is used in the library to check deba@118: /// the consistency of results of algorithms, several pre- and deba@118: /// postconditions and invariants. The checking is disabled by deba@118: /// default, but it can be turned on with the macro \c deba@118: /// LEMON_ENABLE_DEBUG. deba@118: /// \code deba@118: /// #define LEMON_ENABLE_DEBUG deba@118: /// \endcode deba@118: /// or with compilation parameters: deba@118: /// \code deba@118: /// g++ -DLEMON_ENABLE_DEBUG deba@118: /// make CXXFLAGS='-DLEMON_ENABLE_DEBUG' deba@118: /// \endcode deba@118: /// deba@118: /// This macro works like the \c LEMON_ASSERT macro, therefore the deba@118: /// current behaviour depends on the settings of \c LEMON_ASSERT deba@118: /// macro. deba@118: /// alpar@209: /// \see LEMON_ASSERT kpeter@212: # define LEMON_DEBUG(exp, msg) \ kpeter@212: (static_cast (!!(exp) ? 0 : ( \ deba@118: LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \ kpeter@212: LEMON_FUNCTION_NAME, \ alpar@209: ::lemon::_assert_bits::cstringify(msg), #exp), 0))) kpeter@66: kpeter@66: #else kpeter@66: deba@108: # ifndef LEMON_ASSERT_HANDLER kpeter@112: # define LEMON_ASSERT(exp, msg) (static_cast(0)) deba@108: # define LEMON_FIXME(msg) (static_cast(0)) deba@118: # define LEMON_DEBUG(exp, msg) (static_cast(0)) kpeter@66: # else kpeter@212: # define LEMON_ASSERT(exp, msg) \ kpeter@212: (static_cast (!!(exp) ? 0 : ( \ deba@118: LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \ kpeter@212: LEMON_FUNCTION_NAME, \ kpeter@212: ::lemon::_assert_bits::cstringify(msg), \ alpar@209: #exp), 0))) kpeter@212: # define LEMON_FIXME(msg) \ kpeter@212: (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME, \ kpeter@212: ::lemon::_assert_bits::cstringify(msg), \ alpar@209: static_cast(0))) deba@118: deba@118: # if LEMON_ENABLE_DEBUG kpeter@218: # define LEMON_DEBUG(exp, msg) \ kpeter@212: (static_cast (!!(exp) ? 0 : ( \ kpeter@212: LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \ kpeter@212: LEMON_FUNCTION_NAME, \ kpeter@212: ::lemon::_assert_bits::cstringify(msg), \ alpar@209: #exp), 0))) deba@118: # else deba@118: # define LEMON_DEBUG(exp, msg) (static_cast(0)) deba@118: # endif kpeter@66: # endif deba@108: kpeter@66: #endif