| 
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
  |