1.1 --- a/src/work/klao/Makefile Sun Jan 09 23:21:52 2005 +0000
1.2 +++ b/src/work/klao/Makefile Sun Jan 09 23:28:18 2005 +0000
1.3 @@ -1,4 +1,5 @@
1.4 -BINARIES = tag_demo
1.5 +BINARIES = error_test
1.6 INCLUDEDIRS= -I. -I.. -I../.. -I../{marci,jacint,alpar,johanna,athos,akos} -I$(HOME)/boost
1.7 include ../makefile
1.8
1.9 +CXXFLAGS += $(C)
2.1 --- a/src/work/klao/error.h Sun Jan 09 23:21:52 2005 +0000
2.2 +++ b/src/work/klao/error.h Sun Jan 09 23:28:18 2005 +0000
2.3 @@ -19,23 +19,29 @@
2.4
2.5 //! \ingroup misc
2.6 //! \file
2.7 -//! \brief Basic error handling (signaling) routines.
2.8 +//! \brief Basic exception classes and error handling.
2.9
2.10 #include <exception>
2.11 #include <string>
2.12 #include <sstream>
2.13 +#include <iostream>
2.14 +#include <cstdlib>
2.15
2.16 #include <boost/shared_ptr.hpp>
2.17
2.18 namespace lemon {
2.19
2.20 /// Exception-safe convenient "error message" class.
2.21 +
2.22 + /// Helper class which provides a convenient ostream-like (operator <<
2.23 + /// based) interface to create a string message. Mostly useful in
2.24 + /// exception classes (therefore the name).
2.25 class ErrorMessage {
2.26 protected:
2.27 - ///\e
2.28 + ///\e
2.29 boost::shared_ptr<std::ostringstream> buf;
2.30
2.31 - ///\e
2.32 + ///\e
2.33 bool init() throw() {
2.34 try {
2.35 buf.reset(new std::ostringstream);
2.36 @@ -48,22 +54,22 @@
2.37
2.38 public:
2.39
2.40 - ///\e
2.41 + ///\e
2.42 ErrorMessage() throw() { init(); }
2.43
2.44 - ///\e
2.45 + ///\e
2.46 ErrorMessage(const char *message) throw() {
2.47 init();
2.48 *this << message;
2.49 }
2.50
2.51 - ///\e
2.52 + ///\e
2.53 ErrorMessage(const std::string &message) throw() {
2.54 init();
2.55 *this << message;
2.56 }
2.57
2.58 - ///\e
2.59 + ///\e
2.60 template <typename T>
2.61 ErrorMessage& operator<<(const T &t) throw() {
2.62 if( !buf ) return *this;
2.63 @@ -76,7 +82,7 @@
2.64 }
2.65 }
2.66
2.67 - ///\e
2.68 + ///\e
2.69 const char* message() throw() {
2.70 if( !buf ) return 0;
2.71
2.72 @@ -95,65 +101,81 @@
2.73 *
2.74 * Base class for exceptions used in LEMON.
2.75 */
2.76 - class Exception : public std::exception, public ErrorMessage {
2.77 + class Exception : public std::exception {
2.78 + protected:
2.79 + ///\e
2.80 + const char *message;
2.81 +
2.82 public:
2.83 - ///\e
2.84 - Exception() throw() {}
2.85 - ///\e
2.86 - explicit Exception(const std::string &s) throw()
2.87 - : ErrorMessage(s) {}
2.88 - ///\e
2.89 + ///\e
2.90 + Exception() throw() : message(0) {}
2.91 + ///\e
2.92 + explicit Exception(const char *msg) throw()
2.93 + : message(msg) {}
2.94 + ///\e
2.95 virtual ~Exception() throw() {}
2.96
2.97 - ///\e
2.98 + ///\e
2.99 virtual const char* what() const throw() {
2.100 - const char *mes = message();
2.101 - if( mes ) return mes;
2.102 + if( message ) return message;
2.103 return "lemon::Exception";
2.104 }
2.105 };
2.106
2.107 ///\e
2.108 class LogicError : public Exception {
2.109 - ///\e
2.110 - explicit LogicError(const std::string &s)
2.111 + public:
2.112 + ///\e
2.113 + explicit LogicError() {}
2.114 + ///\e
2.115 + explicit LogicError(const char *s)
2.116 : Exception(s) {}
2.117 };
2.118
2.119 ///\e
2.120 class RuntimeError : public Exception {
2.121 - ///\e
2.122 - explicit RuntimeError(const std::string &s)
2.123 + public:
2.124 + ///\e
2.125 + explicit RuntimeError() {}
2.126 + ///\e
2.127 + explicit RuntimeError(const char *s)
2.128 : Exception(s) {}
2.129 };
2.130
2.131 - ///\e
2.132 + ///\e
2.133 class RangeError : public RuntimeError {
2.134 - ///\e
2.135 - explicit RangeError(const std::string &s)
2.136 + public:
2.137 + ///\e
2.138 + explicit RangeError(const char *s)
2.139 : RuntimeError(s) {}
2.140 };
2.141
2.142 ///\e
2.143 class IOError : public RuntimeError {
2.144 - ///\e
2.145 - explicit IOError(const std::string &s)
2.146 + public:
2.147 + ///\e
2.148 + explicit IOError(const char *s)
2.149 : RuntimeError(s) {}
2.150 };
2.151
2.152 ///\e
2.153 class DataFormatError : public IOError {
2.154 - ///\e
2.155 - explicit DataFormatError(const std::string &message)
2.156 - : IOError(message) : line(0) {}
2.157 - ///\e
2.158 + protected:
2.159 + int line;
2.160 + boost::shared_ptr<std::string> file;
2.161 +
2.162 + public:
2.163 + ///\e
2.164 + explicit DataFormatError(const char *message)
2.165 + : IOError(message), line(0) {}
2.166 + ///\e
2.167 DataFormatError(const std::string &file_name, int line_num,
2.168 - const std::string &message)
2.169 + const char *message)
2.170 : IOError(message), line(line_num) { set_file(file_name); }
2.171
2.172 - ///\e
2.173 + ///\e
2.174 void set_line(int line_num) { line=line_num; }
2.175 - ///\e
2.176 + ///\e
2.177 void set_file(const std::string &file_name) {
2.178 try {
2.179 file.reset(new std::string);
2.180 @@ -164,16 +186,31 @@
2.181 }
2.182 }
2.183
2.184 - ///\e
2.185 - virtual const char* what() const {
2.186 + ///\e
2.187 + int get_line() const { return line; }
2.188 +
2.189 + /// \brief Returns the filename.
2.190 + ///
2.191 + /// Returns "(unknown)" if the filename was not specified.
2.192 + const char* get_file() const {
2.193 + if( file )
2.194 + return file->c_str();
2.195 + else
2.196 + return "(unknown)";
2.197 + }
2.198 +
2.199 + ///\e
2.200 + virtual const char* what() const throw() {
2.201 const char *mes = 0;
2.202 try {
2.203 std::ostringstream ostr;
2.204 ostr << IOError::what();
2.205 if( file || line ) {
2.206 ostr << " (";
2.207 - if( file ) ostr << "in file" << *file;
2.208 - if( line ) ostr << " at line" << line;
2.209 + if( file ) ostr << "in file '" << *file << "'";
2.210 + if( file && line ) ostr << " ";
2.211 + if( line ) ostr << "at line " << line;
2.212 + ostr << ")";
2.213 }
2.214 mes = ostr.str().c_str();
2.215 }
2.216 @@ -181,32 +218,132 @@
2.217 if( mes ) return mes;
2.218 return "lemon::DataFormatError";
2.219 }
2.220 +
2.221 + virtual ~DataFormatError() throw() {}
2.222 };
2.223
2.224
2.225 + class AssertionFailedError : public LogicError {
2.226 + protected:
2.227 + const char *assertion;
2.228 + const char *file;
2.229 + int line;
2.230 + const char *function;
2.231 + const char *message;
2.232 + public:
2.233 + ///\e
2.234 + AssertionFailedError(const char *_file, int _line, const char *func,
2.235 + const char *msg, const char *_assertion = 0) :
2.236 + assertion(_assertion), file(_file), line(_line), function(func),
2.237 + message(msg) {}
2.238 +
2.239 + ///\e
2.240 + const char* get_assertion() const { return assertion; }
2.241 + ///\e
2.242 + const char* get_message() const { return message; }
2.243 + ///\e
2.244 + const char* get_file() const { return file; }
2.245 + ///\e
2.246 + const char* get_function() const { return function; }
2.247 + ///\e
2.248 + int get_line() const { return line; }
2.249 +
2.250 +
2.251 + virtual const char* what() const throw() {
2.252 + const char *mes = 0;
2.253 + try {
2.254 + std::ostringstream ostr;
2.255 + ostr << file << ":" << line << ": ";
2.256 + if( function )
2.257 + ostr << function << ": ";
2.258 + ostr << message;
2.259 + if( assertion )
2.260 + ostr << " (assertion '" << assertion << "' failed)";
2.261 + mes = ostr.str().c_str();
2.262 + }
2.263 + catch(...) {}
2.264 + if( mes ) return mes;
2.265 + return "lemon::AssertionFailedError";
2.266 + }
2.267 +
2.268 + virtual ~AssertionFailedError() throw() {}
2.269 + };
2.270 +
2.271
2.272 /**************** Macros ****************/
2.273
2.274
2.275 - /**
2.276 - * \brief Macro for assertions with customizable message
2.277 - */
2.278 + inline
2.279 + void assert_fail(const char *file, int line, const char *func,
2.280 + const char *message, const char *assertion = 0,
2.281 + bool do_abort=true)
2.282 + {
2.283 + using namespace std;
2.284 + cerr << file << ":" << line << ": ";
2.285 + if( func )
2.286 + cerr << func << ": ";
2.287 + cerr << message;
2.288 + if( assertion )
2.289 + cerr << " (assertion '" << assertion << "' failed)";
2.290 + cerr << endl;
2.291 + if(do_abort)
2.292 + abort();
2.293 + }
2.294
2.295 -# define lemon_assert(exp, msg) \
2.296 - if(!(exp)) { \
2.297 - std::cerr << __FILE__ ":" << __LINE__ << ": " << (msg) << std::endl; \
2.298 - abort; \
2.299 - }
2.300 + inline
2.301 + void assert_fail_throw(const char *file, int line, const char *func,
2.302 + const char *message, const char *assertion = 0,
2.303 + bool = true)
2.304 + {
2.305 + throw AssertionFailedError(file, line, func, message, assertion);
2.306 + }
2.307
2.308
2.309 - /**
2.310 - * \brief Macro for mark not yet implemented features.
2.311 - *
2.312 - * \todo Is this the right place for this? It should be used only in
2.313 - * modules under development.
2.314 - */
2.315 -
2.316 -# define FIXME(msg) lemon_assert(0, "FIXME: " msg)
2.317 -
2.318 }
2.319 #endif // LEMON_ERROR_H
2.320 +
2.321 +#undef LEMON_ASSERT
2.322 +#undef LEMON_FIXME
2.323 +
2.324 +#ifndef LEMON_ASSERT_ABORT
2.325 +# define LEMON_ASSERT_ABORT 1
2.326 +#endif
2.327 +
2.328 +#ifndef LEMON_ASSERT_HANDLER
2.329 +# define LEMON_ASSERT_HANDLER ::lemon::assert_fail
2.330 +#endif
2.331 +
2.332 +#if defined(NDEBUG) || defined(LEMON_DISABLE_ASSERTS)
2.333 +
2.334 +# define LEMON_ASSERT(exp, msg) (static_cast<void> (0))
2.335 +
2.336 +#else
2.337 +
2.338 +/**
2.339 + * \brief Macro for assertions with customizable message
2.340 + *
2.341 + * \todo __PRETTY_FUNCTION__ should be replaced by something
2.342 + * compiler-independant, like BOOST_CURRENT_FUNCTION
2.343 + */
2.344 +
2.345 +# define LEMON_ASSERT(exp, msg) \
2.346 + (static_cast<void> (!!(exp) ? 0 : ( \
2.347 + LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \
2.348 + __PRETTY_FUNCTION__, \
2.349 + (msg), #exp, LEMON_ASSERT_ABORT), 0)))
2.350 +
2.351 +# endif // NDEBUG
2.352 +
2.353 +/**
2.354 + * \brief Macro for mark not yet implemented features.
2.355 + *
2.356 + * \todo Is this the right place for this? It should be used only in
2.357 + * modules under development.
2.358 + *
2.359 + * \todo __PRETTY_FUNCTION__ should be replaced by something
2.360 + * compiler-independant, like BOOST_CURRENT_FUNCTION
2.361 + */
2.362 +
2.363 +# define LEMON_FIXME(msg) \
2.364 + (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, __PRETTY_FUNCTION__, \
2.365 + "FIXME: " msg))
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/src/work/klao/error_test.cc Sun Jan 09 23:28:18 2005 +0000
3.3 @@ -0,0 +1,57 @@
3.4 +#include <iostream>
3.5 +#include <string>
3.6 +
3.7 +#define LEMON_ASSERT_ABORT 0
3.8 +#include <error.h>
3.9 +
3.10 +using namespace std;
3.11 +
3.12 +void parse_line() {
3.13 + throw lemon::DataFormatError("Syntax error");
3.14 +}
3.15 +
3.16 +void parse_file(string fn) {
3.17 + try {
3.18 + parse_line();
3.19 + }
3.20 + catch(lemon::DataFormatError &e) {
3.21 + e.set_file(fn);
3.22 + e.set_line(5);
3.23 + throw;
3.24 + }
3.25 +}
3.26 +
3.27 +void fail_assert();
3.28 +
3.29 +int main() {
3.30 + try {
3.31 + parse_file("input.txt");
3.32 + }
3.33 + catch(exception &e) {
3.34 + cerr << "Exception caught: " << endl;
3.35 + cerr << e.what() << endl;
3.36 + }
3.37 +
3.38 + try {
3.39 + fail_assert();
3.40 + }
3.41 + catch(exception &e) {
3.42 + cerr << "Exception caught: " << endl;
3.43 + cerr << e.what() << endl;
3.44 + }
3.45 +
3.46 + // assert(1==0);
3.47 + LEMON_ASSERT(1==0, "Ellentmondas");
3.48 + LEMON_FIXME("Nincs kesz");
3.49 +}
3.50 +
3.51 +#undef LEMON_ASSERT_HANDLER
3.52 +#define LEMON_ASSERT_HANDLER ::lemon::assert_fail_throw
3.53 +
3.54 +#include <error.h>
3.55 +
3.56 +void fail_assert() {
3.57 + LEMON_ASSERT(2*2==5, "Marson vagyunk");
3.58 +}
3.59 +
3.60 +
4.1 --- a/src/work/makefile Sun Jan 09 23:21:52 2005 +0000
4.2 +++ b/src/work/makefile Sun Jan 09 23:28:18 2005 +0000
4.3 @@ -1,5 +1,5 @@
4.4 INCLUDEDIRS ?= -I.. -I. -I./{marci,jacint,alpar,klao,akos}
4.5 -CXXFLAGS = -g -O3 -W -Wall $(INCLUDEDIRS) -ansi -pedantic
4.6 +CXXFLAGS += -g -O2 -W -Wall $(INCLUDEDIRS) -ansi -pedantic
4.7
4.8 BINARIES ?= bin_heap_demo
4.9