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