lemon/assert.h
changeset 115 7b44eea654d0
parent 108 889d0c289d19
child 118 407c08a0eae9
equal deleted inserted replaced
0:48086d96cc8c 1:9411a9f95424
   113   inline void assert_fail_abort(const char *file, int line, 
   113   inline void assert_fail_abort(const char *file, int line, 
   114 				const char *function,
   114 				const char *function,
   115 				const std::exception& exception,
   115 				const std::exception& exception,
   116 				const char *assertion)
   116 				const char *assertion)
   117   {
   117   {
   118     std::cerr << file << ":" << line << ": ";
   118     assert_fail_log(file, line, function, exception, assertion);
   119     if (function)
       
   120       std::cerr << function << ": ";
       
   121     std::cerr << exception.what();
       
   122     if (assertion)
       
   123       std::cerr << " (assertion '" << assertion << "' failed)";
       
   124     std::cerr << std::endl;
       
   125     std::abort();
   119     std::abort();
   126   }
   120   }
   127 
   121 
   128   inline void assert_fail_abort(const char *file, int line,
   122   inline void assert_fail_abort(const char *file, int line,
   129 				const char *function, const char* message,
   123 				const char *function, const char* message,
   130 				const char *assertion)
   124 				const char *assertion)
   131   {
   125   {
   132     std::cerr << file << ":" << line << ": ";
   126     assert_fail_log(file, line, function, message, assertion);
   133     if (function)
       
   134       std::cerr << function << ": ";
       
   135     std::cerr << message;
       
   136     if (assertion)
       
   137       std::cerr << " (assertion '" << assertion << "' failed)";
       
   138     std::cerr << std::endl;
       
   139     std::abort();
   127     std::abort();
   140   }
   128   }
   141 
   129 
   142   inline void assert_fail_abort(const char *file, int line, 
   130   inline void assert_fail_abort(const char *file, int line, 
   143 				const char *function, 
   131 				const char *function, 
   144 				const std::string& message,
   132 				const std::string& message,
   145 				const char *assertion)
   133 				const char *assertion)
   146   {
   134   {
   147     assert_fail_abort(file, line, function, message.c_str(), assertion);
   135     assert_fail_log(file, line, function, message.c_str(), assertion);
       
   136     std::abort();
   148   }
   137   }
   149 
   138 
   150   inline void assert_fail_error(const char *file, int line, 
   139   inline void assert_fail_error(const char *file, int line, 
   151 				  const char *function,
   140 				  const char *function,
   152 				  const std::exception& exception,
   141 				  const std::exception& exception,
   166   inline void assert_fail_error(const char *file, int line,
   155   inline void assert_fail_error(const char *file, int line,
   167 				  const char *function, 
   156 				  const char *function, 
   168 				  const std::string& message,
   157 				  const std::string& message,
   169 				  const char *assertion)
   158 				  const char *assertion)
   170   {
   159   {
   171     assert_fail_error(file, line, function, message.c_str(), assertion);
   160     throw AssertionFailedError(file, line, function, message.c_str(), assertion);
   172   }
   161   }
   173 
   162 
   174   template <typename Exception>
   163   template <typename Exception>
   175   inline void assert_fail_exception(const char *, int, const char *,
   164   inline void assert_fail_exception(const char *, int, const char *,
   176 				    const Exception& exception,
   165 				    const Exception& exception,
   190   inline void assert_fail_exception(const char *file, int line, 
   179   inline void assert_fail_exception(const char *file, int line, 
   191 				    const char *function, 
   180 				    const char *function, 
   192 				    const std::string& message,
   181 				    const std::string& message,
   193 				    const char *assertion)
   182 				    const char *assertion)
   194   {
   183   {
   195     assert_fail_exception(file, line, function, message.c_str(), assertion);
   184     throw AssertionFailedError(file, line, function, message.c_str(), assertion);
   196   }
   185   }
   197 
   186 
   198 /// @}
   187 /// @}
   199 
   188 
   200 }
   189 }
   206 #if (defined(LEMON_ASSERT_LOG) ? 1 : 0) +		\
   195 #if (defined(LEMON_ASSERT_LOG) ? 1 : 0) +		\
   207   (defined(LEMON_ASSERT_ABORT) ? 1 : 0) +		\
   196   (defined(LEMON_ASSERT_ABORT) ? 1 : 0) +		\
   208   (defined(LEMON_ASSERT_ERROR) ? 1 : 0) +		\
   197   (defined(LEMON_ASSERT_ERROR) ? 1 : 0) +		\
   209   (defined(LEMON_ASSERT_EXCEPTION) ? 1 : 0) +		\
   198   (defined(LEMON_ASSERT_EXCEPTION) ? 1 : 0) +		\
   210   (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) > 1
   199   (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) > 1
   211 #error "Lemon assertion system is not set properly"
   200 #error "LEMON assertion system is not set properly"
   212 #endif
   201 #endif
   213 
   202 
   214 #if ((defined(LEMON_ASSERT_LOG) ? 1 : 0) +		\
   203 #if ((defined(LEMON_ASSERT_LOG) ? 1 : 0) +		\
   215      (defined(LEMON_ASSERT_ABORT) ? 1 : 0) +		\
   204      (defined(LEMON_ASSERT_ABORT) ? 1 : 0) +		\
   216      (defined(LEMON_ASSERT_ERROR) ? 1 : 0) +		\
   205      (defined(LEMON_ASSERT_ERROR) ? 1 : 0) +		\
   217      (defined(LEMON_ASSERT_EXCEPTION) ? 1 : 0) +	\
   206      (defined(LEMON_ASSERT_EXCEPTION) ? 1 : 0) +	\
   218      (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) == 1 ||	\
   207      (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) == 1 ||	\
   219      defined(LEMON_ENABLE_ASSERT)) &&			\
   208      defined(LEMON_ENABLE_ASSERTS)) &&			\
   220   defined(LEMON_DISABLE_ASSERTS)
   209   defined(LEMON_DISABLE_ASSERTS)
   221 #error "Lemon assertion system is not set properly"
   210 #error "LEMON assertion system is not set properly"
   222 #endif
   211 #endif
   223 
   212 
   224 
   213 
   225 #if defined LEMON_ASSERT_LOG
   214 #if defined LEMON_ASSERT_LOG
   226 #  undef LEMON_ASSERT_HANDLER
   215 #  undef LEMON_ASSERT_HANDLER
   254 
   243 
   255 #ifdef DOXYGEN
   244 #ifdef DOXYGEN
   256 
   245 
   257 /// \ingroup exceptions
   246 /// \ingroup exceptions
   258 ///
   247 ///
   259 /// \brief Macro for assertions with customizable message
   248 /// \brief Macro for assertion with customizable message
   260 ///
   249 ///
   261 /// Macro for assertions with customizable message.  
   250 /// Macro for assertion with customizable message.  
   262 /// \param exp An expression convertible to bool. If the expression is
   251 /// \param exp An expression that must be convertible to \c bool.
   263 /// false, then an assertion is raised. The concrete behaviour depends
   252 /// If it is \c false, then an assertion is raised. The concrete
   264 /// on the settings of the assertion system.
   253 /// behaviour depends on the settings of the assertion system.
   265 /// \param msg A \e const \e char*, a \e const std::string& or a \e
   254 /// \param msg A <tt>const char*</tt>, a <tt>const std::string&</tt> or
   266 /// const \e std::exception& parameter. The variable can be used to
   255 /// a <tt>const std::exception&</tt> parameter, which can be used to
   267 /// provide information about the circumstances of failed assertion.
   256 /// provide information about the circumstances of the failed assertion.
   268 ///
   257 ///
   269 /// The assertions are disabled in the default behaviour. You can
   258 /// The assertions are disabled in the default behaviour.
   270 /// enable the assertions with the following code:
   259 /// You can enable them with the following code:
   271 /// \code
   260 /// \code
   272 /// #define LEMON_ENABLE_ASSERTS
   261 /// #define LEMON_ENABLE_ASSERTS
   273 /// \endcode
   262 /// \endcode
   274 /// or with compilation parameters:
   263 /// or with compilation parameters:
   275 /// \code
   264 /// \code
   276 /// g++ -DLEMON_ENABLE_ASSERTS
   265 /// g++ -DLEMON_ENABLE_ASSERTS
   277 /// make CXXFLAGS='-DLEMON_ENABLE_ASSERTS'
   266 /// make CXXFLAGS='-DLEMON_ENABLE_ASSERTS'
   278 /// \endcode
   267 /// \endcode
   279 /// 
   268 /// 
   280 /// The %lemon assertion system has a wide range of customization
   269 /// The LEMON assertion system has a wide range of customization
   281 /// properties. As default behaviour the failed assertion prints a
   270 /// properties. As a default behaviour the failed assertion prints a
   282 /// short log message to the standard ouput and aborts the execution.
   271 /// short log message to the standard error and aborts the execution.
   283 ///
   272 ///
   284 /// The following modes can be used in the assertion system: 
   273 /// The following modes can be used in the assertion system: 
   285 ///
   274 ///
   286 /// - \e LEMON_ASSERT_LOG The failed assert print a short convenient
   275 /// - \c LEMON_ASSERT_LOG The failed assertion prints a short log
   287 ///   error message to the standard error and continues the
   276 ///   message to the standard error and continues the execution.
   288 ///   execution.
   277 /// - \c LEMON_ASSERT_ABORT This mode is similar to the
   289 /// - \e LEMON_ASSERT_ABORT This mode is similar to the \e
   278 ///   \c LEMON_ASSERT_LOG, but it aborts the program. It is the default
   290 ///   LEMON_ASSERT_LOG, but it aborts the program. It is the default
   279 ///   behaviour mode when the assertions are enabled with
   291 ///   operation mode when the asserts are enabled with \e
   280 ///   \c LEMON_ENABLE_ASSERTS.
   292 ///   LEMON_ENABLE_ASSERTS.
   281 /// - \c LEMON_ASSERT_ERROR The assertion throws an
   293 /// - \e LEMON_ASSERT_ERROR The assert throws an \ref
   282 ///   \ref lemon::AssertionFailedError "AssertionFailedError".
   294 ///   lemon::AssertionFailedError "AssertionFailedError". If the \c
   283 ///   If the \c msg parameter is an exception, then the result of the
   295 ///   msg parameter is an exception, then the result of the \ref
   284 ///   \ref lemon::Exception::what() "what()" member function is passed
   296 ///   lemon::Exception::what() "what()" member function is passed as
   285 ///   as error message.
   297 ///   error message.
   286 /// - \c LEMON_ASSERT_EXCEPTION If the specified \c msg is an
   298 /// - \e LEMON_ASSERT_EXCEPTION If the specified \c msg is an
   287 ///   exception, then it raised directly (solving that the exception
   299 ///   exception then it raised directly (solving that the exception
       
   300 ///   can not be thrown polymorphically), otherwise an \ref
   288 ///   can not be thrown polymorphically), otherwise an \ref
   301 ///   lemon::AssertionFailedError "AssertionFailedError" is thrown with
   289 ///   lemon::AssertionFailedError "AssertionFailedError" is thrown with
   302 ///   the given parameter.
   290 ///   the given parameters.
   303 /// - \e LEMON_ASSERT_CUSTOM The user can define an own assertion
   291 /// - \c LEMON_ASSERT_CUSTOM The user can define own assertion handler
   304 ///   handler functions. Three overloaded functions should be defined
   292 ///   functions. Three overloaded functions should be defined with the
   305 ///   with the following parameter lists:
   293 ///   following parameter lists:
   306 ///   \code
   294 ///   \code
   307 ///     void custom_assert_handler(const char* file, int line, 
   295 ///     void custom_assert_handler(const char* file, int line, const char* function,
   308 ///                                const char* function, const char* message, const char* expression);
   296 ///                                const char* message, const char* assertion);
   309 ///     void custom_assert_handler(const char* file, int line, 
   297 ///     void custom_assert_handler(const char* file, int line, const char* function,
   310 ///                                const char* function, const std::string& message, const char* expression);
   298 ///                                const std::string& message, const char* assertion);
   311 ///     void custom_assert_handler(const char* file, int line, 
   299 ///     void custom_assert_handler(const char* file, int line, const char* function,
   312 ///                                const char* function, const std::exception& message, const char* expression);
   300 ///                                const std::exception& message, const char* assertion);
   313 ///   \endcode
   301 ///   \endcode
   314 ///   The name of the functions should be defined as the \c
   302 ///   The name of the functions should be defined as the \c
   315 ///   LEMON_CUSTOM_ASSERT_HANDLER macro name. 
   303 ///   LEMON_CUSTOM_ASSERT_HANDLER macro name. 
   316 ///   \code
   304 ///   \code
   317 ///     #define LEMON_CUSTOM_ASSERT_HANDLER custom_assert_handler
   305 ///     #define LEMON_CUSTOM_ASSERT_HANDLER custom_assert_handler
   318 ///   \endcode
   306 ///   \endcode
   319 ///   Whenever an assertion is occured, one of the custom assertion
   307 ///   Whenever an assertion is occured, one of the custom assertion
   320 ///   handler is called with appropiate parameters.
   308 ///   handlers is called with appropiate parameters.
   321 ///
   309 ///
   322 /// The assertion mode can be changed within one compilation unit, if
   310 /// The assertion mode can also be changed within one compilation unit.
   323 /// the macros are redefined with other settings and the
   311 /// If the macros are redefined with other settings and the
   324 /// lemon/assert.h file is reincluded then the behaviour is changed
   312 /// \ref lemon/assert.h "assert.h" file is reincluded, then the
   325 /// appropiately to the new settings.
   313 /// behaviour is changed appropiately to the new settings.
   326 #  define LEMON_ASSERT(exp, msg)					\
   314 #  define LEMON_ASSERT(exp, msg)					\
   327   (static_cast<void> (!!(exp) ? 0 : (					\
   315   (static_cast<void> (!!(exp) ? 0 : (					\
   328     LEMON_ASSERT_HANDLER(__FILE__, __LINE__,				\
   316     LEMON_ASSERT_HANDLER(__FILE__, __LINE__,				\
   329 			 LEMON_FUNCTION_NAME,				\
   317 			 LEMON_FUNCTION_NAME,				\
   330 			 msg, #exp), 0)))
   318 			 msg, #exp), 0)))
   344 			     "FIXME: " msg, static_cast<const char*>(0)))
   332 			     "FIXME: " msg, static_cast<const char*>(0)))
   345 
   333 
   346 #else
   334 #else
   347 
   335 
   348 #  ifndef LEMON_ASSERT_HANDLER
   336 #  ifndef LEMON_ASSERT_HANDLER
   349 #    define LEMON_ASSERT(exp, msg)  (static_cast<void> (0))
   337 #    define LEMON_ASSERT(exp, msg)  (static_cast<void>(0))
   350 #    define LEMON_FIXME(msg) (static_cast<void>(0))
   338 #    define LEMON_FIXME(msg) (static_cast<void>(0))
   351 #  else
   339 #  else
   352 #    define LEMON_ASSERT(exp, msg)                 \
   340 #    define LEMON_ASSERT(exp, msg)                 \
   353        (static_cast<void> (!!(exp) ? 0 : (         \
   341        (static_cast<void> (!!(exp) ? 0 : (         \
   354          LEMON_ASSERT_HANDLER(__FILE__, __LINE__,  \
   342          LEMON_ASSERT_HANDLER(__FILE__, __LINE__,  \