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