| alpar@209 |      1 | /* -*- mode: C++; indent-tabs-mode: nil; -*-
 | 
| kpeter@66 |      2 |  *
 | 
| alpar@209 |      3 |  * This file is a part of LEMON, a generic C++ optimization library.
 | 
| kpeter@66 |      4 |  *
 | 
| alpar@463 |      5 |  * Copyright (C) 2003-2009
 | 
| kpeter@66 |      6 |  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
 | 
| kpeter@66 |      7 |  * (Egervary Research Group on Combinatorial Optimization, EGRES).
 | 
| kpeter@66 |      8 |  *
 | 
| kpeter@66 |      9 |  * Permission to use, modify and distribute this software is granted
 | 
| kpeter@66 |     10 |  * provided that this copyright notice appears in all copies. For
 | 
| kpeter@66 |     11 |  * precise terms see the accompanying LICENSE file.
 | 
| kpeter@66 |     12 |  *
 | 
| kpeter@66 |     13 |  * This software is provided "AS IS" with no warranty of any kind,
 | 
| kpeter@66 |     14 |  * express or implied, and with no claim as to its suitability for any
 | 
| kpeter@66 |     15 |  * purpose.
 | 
| kpeter@66 |     16 |  *
 | 
| kpeter@66 |     17 |  */
 | 
| kpeter@66 |     18 | 
 | 
| deba@108 |     19 | #ifndef LEMON_ASSERT_H
 | 
| deba@108 |     20 | #define LEMON_ASSERT_H
 | 
| kpeter@66 |     21 | 
 | 
| kpeter@66 |     22 | /// \ingroup exceptions
 | 
| kpeter@66 |     23 | /// \file
 | 
| deba@108 |     24 | /// \brief Extended assertion handling
 | 
| kpeter@66 |     25 | 
 | 
| deba@108 |     26 | #include <lemon/error.h>
 | 
| kpeter@66 |     27 | 
 | 
| kpeter@66 |     28 | namespace lemon {
 | 
| kpeter@66 |     29 | 
 | 
| deba@277 |     30 |   inline void assert_fail_abort(const char *file, int line,
 | 
| deba@277 |     31 |                                 const char *function, const char* message,
 | 
| deba@277 |     32 |                                 const char *assertion)
 | 
| kpeter@66 |     33 |   {
 | 
| deba@108 |     34 |     std::cerr << file << ":" << line << ": ";
 | 
| deba@108 |     35 |     if (function)
 | 
| deba@108 |     36 |       std::cerr << function << ": ";
 | 
| deba@108 |     37 |     std::cerr << message;
 | 
| kpeter@66 |     38 |     if (assertion)
 | 
| deba@108 |     39 |       std::cerr << " (assertion '" << assertion << "' failed)";
 | 
| deba@108 |     40 |     std::cerr << std::endl;
 | 
| deba@108 |     41 |     std::abort();
 | 
| deba@108 |     42 |   }
 | 
| deba@108 |     43 | 
 | 
| deba@118 |     44 |   namespace _assert_bits {
 | 
| alpar@209 |     45 | 
 | 
| alpar@209 |     46 | 
 | 
| deba@118 |     47 |     inline const char* cstringify(const std::string& str) {
 | 
| deba@118 |     48 |       return str.c_str();
 | 
| deba@118 |     49 |     }
 | 
| deba@118 |     50 | 
 | 
| deba@118 |     51 |     inline const char* cstringify(const char* str) {
 | 
| deba@118 |     52 |       return str;
 | 
| alpar@209 |     53 |     }
 | 
| deba@108 |     54 |   }
 | 
| deba@118 |     55 | }
 | 
| deba@108 |     56 | 
 | 
| deba@108 |     57 | #endif // LEMON_ASSERT_H
 | 
| kpeter@66 |     58 | 
 | 
| kpeter@66 |     59 | #undef LEMON_ASSERT
 | 
| deba@118 |     60 | #undef LEMON_DEBUG
 | 
| kpeter@66 |     61 | 
 | 
| deba@277 |     62 | #if (defined(LEMON_ASSERT_ABORT) ? 1 : 0) +               \
 | 
| deba@108 |     63 |   (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) > 1
 | 
| kpeter@112 |     64 | #error "LEMON assertion system is not set properly"
 | 
| kpeter@66 |     65 | #endif
 | 
| kpeter@66 |     66 | 
 | 
| deba@277 |     67 | #if ((defined(LEMON_ASSERT_ABORT) ? 1 : 0) +            \
 | 
| kpeter@212 |     68 |      (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) == 1 ||     \
 | 
| kpeter@212 |     69 |      defined(LEMON_ENABLE_ASSERTS)) &&                  \
 | 
| kpeter@212 |     70 |   (defined(LEMON_DISABLE_ASSERTS) ||                    \
 | 
| deba@118 |     71 |    defined(NDEBUG))
 | 
| kpeter@112 |     72 | #error "LEMON assertion system is not set properly"
 | 
| kpeter@66 |     73 | #endif
 | 
| kpeter@66 |     74 | 
 | 
| deba@108 |     75 | 
 | 
| deba@277 |     76 | #if defined LEMON_ASSERT_ABORT
 | 
| deba@108 |     77 | #  undef LEMON_ASSERT_HANDLER
 | 
| deba@108 |     78 | #  define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort
 | 
| deba@108 |     79 | #elif defined LEMON_ASSERT_CUSTOM
 | 
| deba@108 |     80 | #  undef LEMON_ASSERT_HANDLER
 | 
| deba@108 |     81 | #  ifndef LEMON_CUSTOM_ASSERT_HANDLER
 | 
| deba@108 |     82 | #    error "LEMON_CUSTOM_ASSERT_HANDLER is not set"
 | 
| kpeter@66 |     83 | #  endif
 | 
| deba@108 |     84 | #  define LEMON_ASSERT_HANDLER LEMON_CUSTOM_ASSERT_HANDLER
 | 
| deba@118 |     85 | #elif defined LEMON_DISABLE_ASSERTS
 | 
| deba@108 |     86 | #  undef LEMON_ASSERT_HANDLER
 | 
| deba@118 |     87 | #elif defined NDEBUG
 | 
| deba@118 |     88 | #  undef LEMON_ASSERT_HANDLER
 | 
| deba@118 |     89 | #else
 | 
| deba@108 |     90 | #  define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort
 | 
| deba@108 |     91 | #endif
 | 
| deba@108 |     92 | 
 | 
| deba@108 |     93 | #ifndef LEMON_FUNCTION_NAME
 | 
| ladanyi@142 |     94 | #  if defined __GNUC__
 | 
| ladanyi@142 |     95 | #    define LEMON_FUNCTION_NAME (__PRETTY_FUNCTION__)
 | 
| ladanyi@142 |     96 | #  elif defined _MSC_VER
 | 
| ladanyi@142 |     97 | #    define LEMON_FUNCTION_NAME (__FUNCSIG__)
 | 
| ladanyi@266 |     98 | #  elif __STDC_VERSION__ >= 199901L
 | 
| ladanyi@266 |     99 | #    define LEMON_FUNCTION_NAME (__func__)
 | 
| ladanyi@142 |    100 | #  else
 | 
| ladanyi@266 |    101 | #    define LEMON_FUNCTION_NAME ("<unknown>")
 | 
| ladanyi@142 |    102 | #  endif
 | 
| kpeter@66 |    103 | #endif
 | 
| kpeter@66 |    104 | 
 | 
| kpeter@66 |    105 | #ifdef DOXYGEN
 | 
| kpeter@66 |    106 | 
 | 
| deba@108 |    107 | /// \ingroup exceptions
 | 
| deba@108 |    108 | ///
 | 
| kpeter@112 |    109 | /// \brief Macro for assertion with customizable message
 | 
| kpeter@66 |    110 | ///
 | 
| deba@290 |    111 | /// Macro for assertion with customizable message.
 | 
| deba@277 |    112 | /// \param exp An expression that must be convertible to \c bool.  If it is \c
 | 
| deba@277 |    113 | /// false, then an assertion is raised. The concrete behaviour depends on the
 | 
| deba@277 |    114 | /// settings of the assertion system.
 | 
| deba@277 |    115 | /// \param msg A <tt>const char*</tt> parameter, which can be used to provide
 | 
| deba@277 |    116 | /// information about the circumstances of the failed assertion.
 | 
| kpeter@66 |    117 | ///
 | 
| deba@118 |    118 | /// The assertions are enabled in the default behaviour.
 | 
| deba@118 |    119 | /// You can disable them with the following code:
 | 
| kpeter@66 |    120 | /// \code
 | 
| deba@118 |    121 | /// #define LEMON_DISABLE_ASSERTS
 | 
| kpeter@66 |    122 | /// \endcode
 | 
| deba@108 |    123 | /// or with compilation parameters:
 | 
| deba@108 |    124 | /// \code
 | 
| deba@118 |    125 | /// g++ -DLEMON_DISABLE_ASSERTS
 | 
| deba@118 |    126 | /// make CXXFLAGS='-DLEMON_DISABLE_ASSERTS'
 | 
| deba@108 |    127 | /// \endcode
 | 
| deba@118 |    128 | /// The checking is also disabled when the standard macro \c NDEBUG is defined.
 | 
| alpar@209 |    129 | ///
 | 
| deba@277 |    130 | /// As a default behaviour the failed assertion prints a short log message to
 | 
| deba@277 |    131 | /// the standard error and aborts the execution.
 | 
| kpeter@66 |    132 | ///
 | 
| deba@277 |    133 | /// However, the following modes can be used in the assertion system:
 | 
| deba@277 |    134 | /// - \c LEMON_ASSERT_ABORT The failed assertion prints a short log message to
 | 
| deba@277 |    135 | ///   the standard error and aborts the program. It is the default behaviour.
 | 
| kpeter@112 |    136 | /// - \c LEMON_ASSERT_CUSTOM The user can define own assertion handler
 | 
| deba@118 |    137 | ///   function.
 | 
| deba@108 |    138 | ///   \code
 | 
| alpar@210 |    139 | ///     void custom_assert_handler(const char* file, int line,
 | 
| alpar@210 |    140 | ///                                const char* function, const char* message,
 | 
| alpar@210 |    141 | ///                                const char* assertion);
 | 
| deba@108 |    142 | ///   \endcode
 | 
| deba@118 |    143 | ///   The name of the function should be defined as the \c
 | 
| alpar@209 |    144 | ///   LEMON_CUSTOM_ASSERT_HANDLER macro name.
 | 
| deba@108 |    145 | ///   \code
 | 
| deba@108 |    146 | ///     #define LEMON_CUSTOM_ASSERT_HANDLER custom_assert_handler
 | 
| deba@108 |    147 | ///   \endcode
 | 
| deba@118 |    148 | ///   Whenever an assertion is occured, the custom assertion
 | 
| deba@118 |    149 | ///   handler is called with appropiate parameters.
 | 
| kpeter@66 |    150 | ///
 | 
| kpeter@112 |    151 | /// The assertion mode can also be changed within one compilation unit.
 | 
| kpeter@112 |    152 | /// If the macros are redefined with other settings and the
 | 
| kpeter@112 |    153 | /// \ref lemon/assert.h "assert.h" file is reincluded, then the
 | 
| kpeter@112 |    154 | /// behaviour is changed appropiately to the new settings.
 | 
| alpar@209 |    155 | #  define LEMON_ASSERT(exp, msg)                                        \
 | 
| kpeter@212 |    156 |   (static_cast<void> (!!(exp) ? 0 : (                                   \
 | 
| kpeter@212 |    157 |     LEMON_ASSERT_HANDLER(__FILE__, __LINE__,                            \
 | 
| kpeter@212 |    158 |                          LEMON_FUNCTION_NAME,                           \
 | 
| alpar@209 |    159 |                          ::lemon::_assert_bits::cstringify(msg), #exp), 0)))
 | 
| deba@108 |    160 | 
 | 
| deba@108 |    161 | /// \ingroup exceptions
 | 
| kpeter@66 |    162 | ///
 | 
| deba@118 |    163 | /// \brief Macro for internal assertions
 | 
| deba@118 |    164 | ///
 | 
| deba@118 |    165 | /// Macro for internal assertions, it is used in the library to check
 | 
| deba@118 |    166 | /// the consistency of results of algorithms, several pre- and
 | 
| deba@118 |    167 | /// postconditions and invariants. The checking is disabled by
 | 
| deba@118 |    168 | /// default, but it can be turned on with the macro \c
 | 
| deba@118 |    169 | /// LEMON_ENABLE_DEBUG.
 | 
| deba@118 |    170 | /// \code
 | 
| deba@118 |    171 | /// #define LEMON_ENABLE_DEBUG
 | 
| deba@118 |    172 | /// \endcode
 | 
| deba@118 |    173 | /// or with compilation parameters:
 | 
| deba@118 |    174 | /// \code
 | 
| deba@118 |    175 | /// g++ -DLEMON_ENABLE_DEBUG
 | 
| deba@118 |    176 | /// make CXXFLAGS='-DLEMON_ENABLE_DEBUG'
 | 
| deba@118 |    177 | /// \endcode
 | 
| deba@118 |    178 | ///
 | 
| deba@118 |    179 | /// This macro works like the \c LEMON_ASSERT macro, therefore the
 | 
| deba@118 |    180 | /// current behaviour depends on the settings of \c LEMON_ASSERT
 | 
| deba@118 |    181 | /// macro.
 | 
| deba@118 |    182 | ///
 | 
| alpar@209 |    183 | /// \see LEMON_ASSERT
 | 
| kpeter@212 |    184 | #  define LEMON_DEBUG(exp, msg)                                         \
 | 
| kpeter@212 |    185 |   (static_cast<void> (!!(exp) ? 0 : (                                   \
 | 
| deba@118 |    186 |     LEMON_ASSERT_HANDLER(__FILE__, __LINE__,                            \
 | 
| kpeter@212 |    187 |                          LEMON_FUNCTION_NAME,                           \
 | 
| alpar@209 |    188 |                          ::lemon::_assert_bits::cstringify(msg), #exp), 0)))
 | 
| kpeter@66 |    189 | 
 | 
| kpeter@66 |    190 | #else
 | 
| kpeter@66 |    191 | 
 | 
| deba@108 |    192 | #  ifndef LEMON_ASSERT_HANDLER
 | 
| kpeter@112 |    193 | #    define LEMON_ASSERT(exp, msg)  (static_cast<void>(0))
 | 
| deba@118 |    194 | #    define LEMON_DEBUG(exp, msg) (static_cast<void>(0))
 | 
| kpeter@66 |    195 | #  else
 | 
| kpeter@212 |    196 | #    define LEMON_ASSERT(exp, msg)                                      \
 | 
| kpeter@212 |    197 |        (static_cast<void> (!!(exp) ? 0 : (                              \
 | 
| deba@118 |    198 |         LEMON_ASSERT_HANDLER(__FILE__, __LINE__,                        \
 | 
| kpeter@212 |    199 |                              LEMON_FUNCTION_NAME,                       \
 | 
| kpeter@212 |    200 |                              ::lemon::_assert_bits::cstringify(msg),    \
 | 
| alpar@209 |    201 |                              #exp), 0)))
 | 
| deba@118 |    202 | #    if LEMON_ENABLE_DEBUG
 | 
| kpeter@218 |    203 | #      define LEMON_DEBUG(exp, msg)                                     \
 | 
| kpeter@212 |    204 |          (static_cast<void> (!!(exp) ? 0 : (                            \
 | 
| kpeter@212 |    205 |            LEMON_ASSERT_HANDLER(__FILE__, __LINE__,                     \
 | 
| kpeter@212 |    206 |                                 LEMON_FUNCTION_NAME,                    \
 | 
| kpeter@212 |    207 |                                 ::lemon::_assert_bits::cstringify(msg), \
 | 
| alpar@209 |    208 |                                 #exp), 0)))
 | 
| deba@118 |    209 | #    else
 | 
| deba@118 |    210 | #      define LEMON_DEBUG(exp, msg) (static_cast<void>(0))
 | 
| deba@118 |    211 | #    endif
 | 
| kpeter@66 |    212 | #  endif
 | 
| deba@108 |    213 | 
 | 
| kpeter@66 |    214 | #endif
 |