diff options
author | John Wiegley <johnw@newartisans.com> | 2007-04-27 10:08:05 +0000 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2008-04-13 03:38:31 -0400 |
commit | 4716975cb18795e4a953fc705cf0b7c74d6a1c95 (patch) | |
tree | 4e22788779337c306aa9b83282e7a67c52b6004c | |
parent | 9039e728b2015b54dc87da52f450c27683303392 (diff) | |
download | fork-ledger-4716975cb18795e4a953fc705cf0b7c74d6a1c95.tar.gz fork-ledger-4716975cb18795e4a953fc705cf0b7c74d6a1c95.tar.bz2 fork-ledger-4716975cb18795e4a953fc705cf0b7c74d6a1c95.zip |
More work done toward rearranging the utility code.
-rw-r--r-- | Makefile.am | 15 | ||||
-rw-r--r-- | context.h | 28 | ||||
-rw-r--r-- | debug.cc | 95 | ||||
-rw-r--r-- | debug.h | 166 | ||||
-rw-r--r-- | error.h | 77 | ||||
-rw-r--r-- | timing.h | 61 | ||||
-rw-r--r-- | trace.h | 130 | ||||
-rw-r--r-- | util.h | 23 | ||||
-rw-r--r-- | utils.cc (renamed from trace.cc) | 163 | ||||
-rw-r--r-- | utils.h | 363 |
10 files changed, 552 insertions, 569 deletions
diff --git a/Makefile.am b/Makefile.am index d1efe736..13ec77c2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -31,8 +31,9 @@ libledger_la_CPPFLAGS = -I$(top_builddir)/gdtoa libledger_la_LDFLAGS = -release 3.0 libledger_la_SOURCES = \ - amount.cc \ + utils.cc \ times.cc \ + amount.cc \ quotes.cc \ balance.cc \ value.cc \ @@ -40,8 +41,6 @@ libledger_la_SOURCES = \ xpath.cc \ mask.cc \ format.cc \ - util.cc \ - trace.cc \ \ session.cc \ journal.cc \ @@ -55,7 +54,6 @@ libledger_la_SOURCES = \ transform.cc \ \ register.cc \ - \ csv.cc \ derive.cc \ emacs.cc \ @@ -74,8 +72,7 @@ libledger_la_CPPFLAGS += -DHAVE_LIBOFX=1 libledger_la_SOURCES += ofx.cc endif if DEBUG -libledger_la_CPPFLAGS += -DDEBUG_LEVEL=4 -libledger_la_SOURCES += debug.cc +libledger_la_CPPFLAGS += -DFULL_DEBUG endif if HAVE_BOOST_PYTHON libledger_la_CPPFLAGS += -DUSE_BOOST_PYTHON=1 @@ -107,8 +104,8 @@ pkginclude_HEADERS = \ times.h \ balance.h \ binary.h \ + context.h \ csv.h \ - debug.h \ derive.h \ emacs.h \ error.h \ @@ -131,10 +128,8 @@ pkginclude_HEADERS = \ session.h \ system.hh \ textual.h \ - timing.h \ - trace.h \ transform.h \ - util.h \ + utils.h \ value.h \ xml.h \ xmlparse.h \ diff --git a/context.h b/context.h new file mode 100644 index 00000000..3851d073 --- /dev/null +++ b/context.h @@ -0,0 +1,28 @@ +#ifndef _CONTEXT_H +#define _CONTEXT_H + +namespace ledger { + +class context +{ +public: + string context; // ex: 'While parsing file "%R" at line %L' + + string resource; // ex: ledger.dat + long linenum_beg; // ex: 1010 + long linenum_end; // ex: 1010 + long colnum_beg; // ex: 8 + long colnum_end; // ex: 8 + long position_beg; + long position_end; + + string text; // ex: (The multi-line text of an entry) + long linenum_beg_off; // ex: 2 / -1 means start at beginning + long linenum_end_off; // ex: 2 / -1 means start at beginning + long colnum_beg_off; // ex: 8 / -1 means start + long colnum_end_off; // ex: 8 / -1 means start +}; + +} // namespace ledger + +#endif // _CONTEXT_H diff --git a/debug.cc b/debug.cc deleted file mode 100644 index 680e426c..00000000 --- a/debug.cc +++ /dev/null @@ -1,95 +0,0 @@ -#include "utils.h" - -#include <boost/regex.hpp> - -#ifdef DEBUG_ENABLED - -int new_calls = 0; -unsigned long new_size = 0; - -void * operator new(std::size_t size) throw (std::bad_alloc) { - void * ptr = std::malloc(size); - new_calls++; - new_size += size; - return ptr; -} -void * operator new[](std::size_t size) throw (std::bad_alloc) { - void * ptr = std::malloc(size); - new_calls++; - new_size += size; - return ptr; -} -void * operator new(std::size_t size, const std::nothrow_t&) throw() { - void * ptr = std::malloc(size); - new_calls++; - new_size += size; - return ptr; -} -void * operator new[](std::size_t size, const std::nothrow_t&) throw() { - void * ptr = std::malloc(size); - new_calls++; - new_size += size; - return ptr; -} -void operator delete(void * ptr) throw() { - std::free(ptr); -} -void operator delete[](void * ptr) throw() { - std::free(ptr); -} -void operator delete(void * ptr, const std::nothrow_t&) throw() { - std::free(ptr); -} -void operator delete[](void * ptr, const std::nothrow_t&) throw() { - std::free(ptr); -} - -std::ostream * _debug_stream = &std::cerr; -bool _free_debug_stream = false; -boost::regex _debug_regex; -bool _set_debug_regex = false; -bool _debug_regex_on = false; - -bool _debug_active(const char * const cls) { - if (! _set_debug_regex) { - const char * user_class = std::getenv("DEBUG_CLASS"); - if (user_class) { - _debug_regex = user_class; - _debug_regex_on = true; - } - _set_debug_regex = true; - } - if (_debug_regex_on) - return boost::regex_match(cls, _debug_regex); - return false; -} - -static struct init_streams { - init_streams() { - // If debugging is enabled and DEBUG_FILE is set, all debugging - // output goes to that file. - if (const char * p = std::getenv("DEBUG_FILE")) { - _debug_stream = new std::ofstream(p); - _free_debug_stream = true; - } - } - ~init_streams() { - if (_free_debug_stream && _debug_stream) { - delete _debug_stream; - _debug_stream = NULL; - } - } -} _debug_init; - -#endif // DEBUG_ENABLED - -#if DEBUG_LEVEL >= BETA - -void debug_assert(const ledger::string& reason, - const ledger::string& file, - unsigned long line) -{ - throw new ledger::fatal_assert(reason, new ledger::file_context(file, line)); -} - -#endif diff --git a/debug.h b/debug.h deleted file mode 100644 index f0987b3f..00000000 --- a/debug.h +++ /dev/null @@ -1,166 +0,0 @@ -#ifndef _DEBUG_H -#define _DEBUG_H - -#define DEVELOPER 4 -#define ALPHA 3 -#define BETA 2 -#define RELEASE 1 -#define NO_SEATBELT 0 - -#ifndef DEBUG_LEVEL -#define DEBUG_LEVEL NO_SEATBELT -#endif - -#if DEBUG_LEVEL >= RELEASE - -#ifdef assert -#undef assert -#endif - -#if DEBUG_LEVEL >= BETA - -void debug_assert(const ledger::string& reason, - const ledger::string& file, - unsigned long line); - -#define assert(x) \ - if (! (x)) \ - debug_assert(#x, __FILE__, __LINE__) - -#else - -#define assert(x) \ - if (! (x)) \ - throw new fatal_assert(#x, new file_context(__FILE__, __LINE__)) -#endif - -#else - -#ifdef assert -#undef assert -#endif -#define assert(x) - -#endif - -////////////////////////////////////////////////////////////////////// -// -// General debugging facilities -// -// - In developer level, all checking and debugging facilities are -// active. -// -// - Alpha level does not include performance degrading -// VALIDATE calls. -// -// - Beta level is like Alpha, but does not include debugging -// facilities. -// -// - Release level does not include CONFIRM checks, but does include -// assert calls. -// -// - Running with no seatbelt disables all checking except for normal -// syntax and semantic error checking. - -#if DEBUG_LEVEL >= ALPHA - -#define DEBUG_ENABLED - -extern std::ostream * _debug_stream; -extern bool _free_debug_stream; - -bool _debug_active(const char * const cls); - -#define DEBUG_CLASS(cls) static const char * const _debug_cls = (cls) - -#define DEBUG(cls) (_debug_active(cls)) -#define DEBUG_() DEBUG(_debug_cls) - -#define DEBUG_IF(cls) if (_debug_active(cls)) -#define DEBUG_IF_() if (_debug_active(_debug_cls)) - -#define DEBUG_PRINT(cls, x) \ - if (_debug_stream && _debug_active(cls)) { \ - *_debug_stream << x << std::endl; \ - } -#define DEBUG_PRINT_(x) DEBUG_PRINT(_debug_cls, x) - -#define DEBUG_PRINT_TIME(cls, x) { \ - DEBUG_PRINT(cls, #x << " is " << x); \ -} - -#define DEBUG_PRINT_TIME_(x) DEBUG_PRINT_TIME(_debug_cls, x) - -#define CONFIRM(x) assert(x) - -#if DEBUG_LEVEL == DEVELOPER -#define VALIDATE(x) assert(x) -#else -#define VALIDATE(x) -#endif - -extern int new_calls; -extern unsigned long new_size; - -#if 0 -void * operator new(std::size_t) throw (std::bad_alloc); -void * operator new[](std::size_t) throw (std::bad_alloc); -void operator delete(void*) throw(); -void operator delete[](void*) throw(); -void * operator new(std::size_t, const std::nothrow_t&) throw(); -void * operator new[](std::size_t, const std::nothrow_t&) throw(); -void operator delete(void*, const std::nothrow_t&) throw(); -void operator delete[](void*, const std::nothrow_t&) throw(); -#endif - -#else // DEBUG_LEVEL - -#define DEBUG_CLASS(cls) -#define DEBUG(cls) 0 -#define DEBUG_() 0 -#define DEBUG_IF(cls) -#define DEBUG_IF_() -#define DEBUG_PRINT(cls, x) -#define DEBUG_PRINT_(x) -#define DEBUG_PRINT_TIME(cls, x) -#define DEBUG_PRINT_TIME_(x) - -#define VALIDATE(x) - -#if DEBUG_LEVEL == NO_SEATBELT - -#ifdef assert -#undef assert -#endif -#define assert(x) -#define CONFIRM(x) - -#ifndef TRACE_CTOR -#define TRACE_CTOR(cls, args) -#define TRACE_DTOR(cls) -#define TRACE(cat, msg) -#define TRACE_PUSH(cat, msg) -#define TRACE_POP(cat, msg) -#endif - -#elif DEBUG_LEVEL == RELEASE - -#define CONFIRM(x) - -#ifndef TRACE_CTOR -#define TRACE_CTOR(cls, args) -#define TRACE_DTOR(cls) -#define TRACE(cat, msg) -#define TRACE_PUSH(cat, msg) -#define TRACE_POP(cat, msg) -#endif - -#elif DEBUG_LEVEL >= BETA - -#define CONFIRM(x) assert(x) - -#endif - -#endif // DEBUG_LEVEL - -#endif // _DEBUG_H @@ -1,8 +1,43 @@ #ifndef _ERROR_H #define _ERROR_H +#import "context.h" + namespace ledger { +class exception : public std::exception +{ +protected: + string reason; + +public: + std::list<context> context_stack; + + exception(const string& _reason, + const context& immediate_ctxt) throw() + : reason(_reason) { + push(immediate_ctxt); + } + + void push(const context& intermediate_ctxt) throw() { + context_stack.push_front(intermediate_ctxt); + } + + void write(std::ostream& out) const throw() { + for (std::list<context>::const_iterator + i = context.begin(); + i != context.end(); + i++) + (*i).write(out); + } + + const char * what() const throw() { + return reason.c_str(); + } +}; + +#if 0 + class error_context { public: @@ -57,46 +92,6 @@ class line_context : public error_context { } }; -////////////////////////////////////////////////////////////////////// - -class str_exception : public std::exception { - protected: - string reason; - public: - std::list<error_context *> context; - - str_exception(const string& _reason, - error_context * ctxt = NULL) throw() - : reason(_reason) { - if (ctxt) - context.push_back(ctxt); - } - - virtual ~str_exception() throw() { - for (std::list<error_context *>::iterator i = context.begin(); - i != context.end(); - i++) - delete *i; - } - - virtual void reveal_context(std::ostream& out, - const string& kind) const throw() { - for (std::list<error_context *>::const_reverse_iterator i = - context.rbegin(); - i != context.rend(); - i++) { - std::list<error_context *>::const_reverse_iterator x = i; - if (++x == context.rend()) - out << kind << ": "; - (*i)->describe(out); - } - } - - virtual const char* what() const throw() { - return reason.c_str(); - } -}; - class error : public str_exception { public: error(const string& _reason, error_context * _ctxt = NULL) throw() @@ -118,6 +113,8 @@ class fatal_assert : public fatal { virtual ~fatal_assert() throw() {} }; +#endif // 0 + inline void unexpected(char c, char wanted) { if ((unsigned char) c == 0xff) { diff --git a/timing.h b/timing.h deleted file mode 100644 index 51a3e7c4..00000000 --- a/timing.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef _TIMING_H -#define _TIMING_H - -namespace ledger { - -class timing_t -{ - public: - std::clock_t begin; - std::clock_t cumulative; - string file; - unsigned long line; - string symbol; - string category; - - timing_t(const string& _symbol, const string& _category) - : begin(0), cumulative(0), symbol(_symbol), category(_category) {} - - timing_t(const string& _symbol) - : begin(0), cumulative(0), symbol(_symbol) {} - - ~timing_t() { - string cls = "timing.results."; - cls += symbol; -#if 0 - // jww (2007-04-19): This crashes things nowadays - DEBUG_PRINT(cls.c_str(), file << ":" << line << ": " - << category << " = " - << (double(cumulative) / double(CLOCKS_PER_SEC)) << "s"); -#endif - } - - void start(const string& _file, unsigned long _line) { - file = _file; - line = _line; - begin = std::clock(); - } - void start() { - begin = std::clock(); - } - - void stop() { - cumulative += std::clock() - begin; - } -}; - -#if 0 && DEBUG_LEVEL >= 4 -#define TIMER_DEF(sym, cat) static timing_t sym(#sym, cat); -#define TIMER_DEF_(sym) static timing_t sym(#sym, #sym); -#define TIMER_START(sym) sym.start(__FILE__, __LINE__); -#define TIMER_STOP(sym) sym.stop(); -#else -#define TIMER_DEF(sym, cat) -#define TIMER_DEF_(sym) -#define TIMER_START(sym) -#define TIMER_STOP(sym) -#endif - -} // namespace ledger - -#endif // _TIMING_H diff --git a/trace.h b/trace.h deleted file mode 100644 index 3763ca77..00000000 --- a/trace.h +++ /dev/null @@ -1,130 +0,0 @@ -#ifndef _TRACE_H -#define _TRACE_H - -namespace ledger { - -class timing_t; - -extern bool trace_alloc_mode; -extern bool trace_class_mode; - -#if 0 && DEBUG_LEVEL >= 4 && ! defined(USE_BOOST_PYTHON) -class string; -#else -typedef std::string string; -#endif - -void trace(const string& cat, const string& str); -void trace_push(const string& cat, const string& str, timing_t& timer); -void trace_pop(const string& cat, const string& str, timing_t& timer); - -#ifndef TRACE -#define TRACE(cat, msg) if (trace_class_mode) trace(#cat, msg) -#define TRACE_(cat, msg) if (trace_class_mode) trace(#cat, msg) - -#define TRACE_PUSH(cat, msg) \ - timing_t timer_ ## cat(#cat); \ - if (trace_class_mode) trace_push(#cat, msg, timer_ ## cat) - -#define TRACE_POP(cat, msg) \ - if (trace_class_mode) trace_pop(#cat, msg, timer_ ## cat) -#endif - -typedef std::multimap<void *, std::string> live_objects_map; -typedef std::pair<void *, std::string> live_objects_pair; -typedef std::pair<unsigned int, std::size_t> count_size_pair; -typedef std::map<std::string, count_size_pair> object_count_map; -typedef std::pair<std::string, count_size_pair> object_count_pair; - -extern live_objects_map live_objects; -extern object_count_map live_count; -extern object_count_map ctor_count; -extern object_count_map object_count; - -extern bool tracing_active; - -bool trace_ctor(void * ptr, const char * cls_name, const char * args, - std::size_t cls_size); -bool trace_dtor(void * ptr, const char * cls_name, std::size_t cls_size); - -void report_memory(std::ostream& out); - -#if 1 -#ifndef TRACE_CTOR -#define TRACE_CTOR(cls, args) \ - CONFIRM(ledger::trace_ctor(this, #cls, args, sizeof(cls))) -#define TRACE_DTOR(cls) \ - CONFIRM(ledger::trace_dtor(this, #cls, sizeof(cls))) -#endif -#else -#define TRACE_CTOR(cls, args) -#define TRACE_DTOR(cls) -#endif - -#if 0 && DEBUG_LEVEL >= 4 && ! defined(USE_BOOST_PYTHON) - -class string : public std::string -{ -public: - string(); - string(const string& str); - string(const std::string& str); - string(const int len, char x); - string(const char * str); - string(const char * str, const char * end); - string(const string& str, int x); - string(const string& str, int x, int y); - string(const char * str, int x); - string(const char * str, int x, int y); - ~string(); -}; - -inline string operator+(const string& __lhs, const string& __rhs) -{ - string __str(__lhs); - __str.append(__rhs); - return __str; -} - -string operator+(const char* __lhs, const string& __rhs); -string operator+(char __lhs, const string& __rhs); - -inline string operator+(const string& __lhs, const char* __rhs) -{ - string __str(__lhs); - __str.append(__rhs); - return __str; -} - -inline string operator+(const string& __lhs, char __rhs) -{ - typedef string __string_type; - typedef string::size_type __size_type; - __string_type __str(__lhs); - __str.append(__size_type(1), __rhs); - return __str; -} - -inline bool operator==(const string& __lhs, const string& __rhs) -{ return __lhs.compare(__rhs) == 0; } - -inline bool operator==(const char* __lhs, const string& __rhs) -{ return __rhs.compare(__lhs) == 0; } - -inline bool operator==(const string& __lhs, const char* __rhs) -{ return __lhs.compare(__rhs) == 0; } - -inline bool operator!=(const string& __lhs, const string& __rhs) -{ return __rhs.compare(__lhs) != 0; } - -inline bool operator!=(const char* __lhs, const string& __rhs) -{ return __rhs.compare(__lhs) != 0; } - -inline bool operator!=(const string& __lhs, const char* __rhs) -{ return __lhs.compare(__rhs) != 0; } - -#endif - -} // namespace ledger - -#endif // _TRACE_H @@ -1,29 +1,6 @@ #ifndef _UTIL_H #define _UTIL_H -#if defined __FreeBSD__ && __FreeBSD__ <=4 -// FreeBSD has a broken isspace macro, so dont use it -#undef isspace(c) -#endif - -#if defined(__GNUG__) && __GNUG__ < 3 -namespace std { - inline ostream & right (ostream & i) { - i.setf(i.right, i.adjustfield); - return i; - } - inline ostream & left (ostream & i) { - i.setf(i.left, i.adjustfield); - return i; - } -} -typedef unsigned long istream_pos_type; -typedef unsigned long ostream_pos_type; -#else -typedef std::istream::pos_type istream_pos_type; -typedef std::ostream::pos_type ostream_pos_type; -#endif - namespace ledger { inline char * skip_ws(char * ptr) { @@ -1,31 +1,60 @@ #include "utils.h" #include "times.h" -namespace ledger { +namespace ledger -bool trace_alloc_mode; -bool trace_class_mode; +#if defined(ASSERTS_ON) -void trace(const string& cat, const string& str) +void debug_assert(const ledger::string& reason, + const ledger::string& func, + const ledger::string& file, + unsigned long line) { - std::cerr << boost::posix_time::to_simple_string(now) << " " - << cat << ": " << str << std::endl; + throw fatal(reason, context()); } -void trace_push(const string& cat, const string& str, - timing_t& timer) -{ - timer.start(); - trace(cat, str); -} +#endif -void trace_pop(const string& cat, const string& str, - timing_t& timer) -{ - timer.stop(); - std::ostringstream out; - out << str << ": " << (double(timer.cumulative) / double(CLOCKS_PER_SEC)) << "s"; - trace(cat, out.str()); +#if defined(VERIFY_ON) + +int new_calls = 0; +unsigned long new_size = 0; + +void * operator new(std::size_t size) throw (std::bad_alloc) { + void * ptr = std::malloc(size); + new_calls++; + new_size += size; + return ptr; +} +void * operator new[](std::size_t size) throw (std::bad_alloc) { + void * ptr = std::malloc(size); + new_calls++; + new_size += size; + return ptr; +} +void * operator new(std::size_t size, const std::nothrow_t&) throw() { + void * ptr = std::malloc(size); + new_calls++; + new_size += size; + return ptr; +} +void * operator new[](std::size_t size, const std::nothrow_t&) throw() { + void * ptr = std::malloc(size); + new_calls++; + new_size += size; + return ptr; +} +void operator delete(void * ptr) throw() { + std::free(ptr); +} +void operator delete[](void * ptr) throw() { + std::free(ptr); +} +void operator delete(void * ptr, const std::nothrow_t&) throw() { + std::free(ptr); +} +void operator delete[](void * ptr, const std::nothrow_t&) throw() { + std::free(ptr); } live_objects_map live_objects; @@ -33,8 +62,6 @@ object_count_map ctor_count; object_count_map object_count; object_count_map live_count; -bool tracing_active = false; - inline void add_to_count_map(object_count_map& the_map, const char * name, std::size_t size) { @@ -63,9 +90,6 @@ inline void report_count_map(std::ostream& out, object_count_map& the_map) bool trace_ctor(void * ptr, const char * cls_name, const char * args, std::size_t cls_size) { - if (! tracing_active) - return true; - if (trace_class_mode && cls_name[0] == '_') return true; if (trace_alloc_mode && cls_name[0] != '_') @@ -92,9 +116,6 @@ bool trace_ctor(void * ptr, const char * cls_name, const char * args, bool trace_dtor(void * ptr, const char * cls_name, std::size_t cls_size) { - if (! tracing_active) - return true; - if (trace_class_mode && cls_name[0] == '_') return true; if (trace_alloc_mode && cls_name[0] != '_') @@ -162,42 +183,106 @@ void report_memory(std::ostream& out) } } -#if 0 && DEBUG_LEVEL >= 4 && ! defined(USE_BOOST_PYTHON) +#if ! defined(USE_BOOST_PYTHON) string::string() : std::string() { - TRACE_CTOR(string, ""); + trace_ctor(string, ""); } string::string(const string& str) : std::string(str) { - TRACE_CTOR(string, "const string&"); + trace_ctor(string, "const string&"); } string::string(const std::string& str) : std::string(str) { - TRACE_CTOR(string, "const std::string&"); + trace_ctor(string, "const std::string&"); } string::string(const int len, char x) : std::string(len, x) { - TRACE_CTOR(string, "const int, char"); + trace_ctor(string, "const int, char"); } string::string(const char * str) : std::string(str) { - TRACE_CTOR(string, "const char *"); + trace_ctor(string, "const char *"); } string::string(const char * str, const char * end) : std::string(str, end) { - TRACE_CTOR(string, "const char *, const char *"); + trace_ctor(string, "const char *, const char *"); } string::string(const string& str, int x) : std::string(str, x) { - TRACE_CTOR(string, "const string&, int"); + trace_ctor(string, "const string&, int"); } string::string(const string& str, int x, int y) : std::string(str, x, y) { - TRACE_CTOR(string, "const string&, int, int"); + trace_ctor(string, "const string&, int, int"); } string::string(const char * str, int x) : std::string(str, x) { - TRACE_CTOR(string, "const char *, int"); + trace_ctor(string, "const char *, int"); } string::string(const char * str, int x, int y) : std::string(str, x, y) { - TRACE_CTOR(string, "const char *, int, int"); + trace_ctor(string, "const char *, int, int"); } string::~string() { - TRACE_DTOR(string); + trace_dtor(string); } #endif +#endif // VERIFY_ON + +#if defined(TIMERS_ON) + +void start_timer(const char * name) +{ + begin = std::clock(); +} + +void stop_timer(const char * name) +{ + cumulative += std::clock() - begin; +} + +void finish_timer(const char * name) +{ + DEBUG_PRINT(cls.c_str(), file << ":" << line << ": " + << category << " = " + << (double(cumulative) / double(CLOCKS_PER_SEC)) << "s"); +} + +#endif // TIMERS_ON + +#if defined(LOGGING_ON) && defined(DEBUG_ON) + +std::ostream * _debug_stream = &std::cerr; +bool _free_debug_stream = false; +boost::regex _debug_regex; +bool _set_debug_regex = false; +bool _debug_regex_on = false; + +bool _debug_active(const char * const cls) { + if (! _set_debug_regex) { + const char * user_class = std::getenv("DEBUG_CLASS"); + if (user_class) { + _debug_regex = user_class; + _debug_regex_on = true; + } + _set_debug_regex = true; + } + if (_debug_regex_on) + return boost::regex_match(cls, _debug_regex); + return false; +} + +static struct init_streams { + init_streams() { + // If debugging is enabled and DEBUG_FILE is set, all debugging + // output goes to that file. + if (const char * p = std::getenv("DEBUG_FILE")) { + _debug_stream = new std::ofstream(p); + _free_debug_stream = true; + } + } + ~init_streams() { + if (_free_debug_stream && _debug_stream) { + delete _debug_stream; + _debug_stream = NULL; + } + } +} _debug_init; + +#endif // LOGGING_ON && DEBUG_ON + } // namespace ledger @@ -3,6 +3,26 @@ #include <system.hh> +#if defined __FreeBSD__ && __FreeBSD__ <=4 +// FreeBSD has a broken isspace macro, so don't use it +#undef isspace(c) +#endif + +#if defined(__GNUG__) && __GNUG__ < 3 +namespace std { + inline ostream & right (ostream & i) { + i.setf(i.right, i.adjustfield); + return i; + } + inline ostream & left (ostream & i) { + i.setf(i.left, i.adjustfield); + return i; + } +} +#endif + +namespace ledger { + // jww (2007-04-23): Need to clean up the following include files. I // want to following services: // @@ -15,10 +35,343 @@ // verification (optionally on, like debugging but silent) // memory tracing and debugging (and watching for threshholds) -#include "trace.h" -#include "debug.h" -#include "timing.h" -#include "error.h" -#include "util.h" +#import "error.h" + +/********************************************************************** + * + * Default values + */ + +#if defined(FULL_DEBUG) +#define VERIFY_ON 1 +#define TRACING_ON 1 +#define DEBUG_ON 1 +#define TIMERS_ON 1 +#elif defined(NO_DEBUG) +#define NO_ASSERTS 1 +#define NO_LOGGING 1 +#else +#define TIMERS_ON 1 +#endif + +/********************************************************************** + * + * Assertions + */ + +#ifdef assert +#undef assert +#endif + +#if ! defined(NO_ASSERTS) +#define ASSERTS_ON 1 +#endif +#if defined(ASSERTS_ON) + +#include <boost/current_function.hpp> + +void debug_assert(const ledger::string& reason, + const ledger::string& func, + const ledger::string& file, + unsigned long line); + +#define assert(x) \ + ((x) ? ((void)0) : debug_assert(#x, BOOST_CURRENT_FUNCTION, \ + __FILE__, __LINE__) + +#endif // ASSERTS_ON + +/********************************************************************** + * + * Verification (basically, very slow asserts) + */ + +#if defined(VERIFY_ON) + +extern bool verify_enabled; + +#define verify(x) (verify_enabled ? assert(x) : ((void)0)) + +extern int new_calls; +extern unsigned long new_size; + +void * operator new(std::size_t) throw(std::bad_alloc); +void * operator new[](std::size_t) throw(std::bad_alloc); +void operator delete(void*) throw(); +void operator delete[](void*) throw(); +void * operator new(std::size_t, const std::nothrow_t&) throw(); +void * operator new[](std::size_t, const std::nothrow_t&) throw(); +void operator delete(void*, const std::nothrow_t&) throw(); +void operator delete[](void*, const std::nothrow_t&) throw(); + +typedef std::multimap<void *, std::string> live_objects_map; +typedef std::pair<void *, std::string> live_objects_pair; +typedef std::pair<unsigned int, std::size_t> count_size_pair; +typedef std::map<std::string, count_size_pair> object_count_map; +typedef std::pair<std::string, count_size_pair> object_count_pair; + +extern live_objects_map live_objects; +extern object_count_map live_count; +extern object_count_map ctor_count; +extern object_count_map object_count; + +bool trace_ctor(void * ptr, const char * cls_name, const char * args, + std::size_t cls_size); +bool trace_dtor(void * ptr, const char * cls_name, std::size_t cls_size); + +#define trace_ctor(cls, args) \ + verify(trace_ctor(this, #cls, args, sizeof(cls))) +#define trace_dtor(cls) \ + verify(trace_dtor(this, #cls, sizeof(cls))) + +void report_memory(std::ostream& out); + +#if ! defined(USE_BOOST_PYTHON) + +class string : public std::string +{ +public: + string(); + string(const string& str); + string(const std::string& str); + string(const int len, char x); + string(const char * str); + string(const char * str, const char * end); + string(const string& str, int x); + string(const string& str, int x, int y); + string(const char * str, int x); + string(const char * str, int x, int y); + ~string(); +}; + +inline string operator+(const string& __lhs, const string& __rhs) +{ + string __str(__lhs); + __str.append(__rhs); + return __str; +} + +string operator+(const char* __lhs, const string& __rhs); +string operator+(char __lhs, const string& __rhs); + +inline string operator+(const string& __lhs, const char* __rhs) +{ + string __str(__lhs); + __str.append(__rhs); + return __str; +} + +inline string operator+(const string& __lhs, char __rhs) +{ + typedef string __string_type; + typedef string::size_type __size_type; + __string_type __str(__lhs); + __str.append(__size_type(1), __rhs); + return __str; +} + +inline bool operator==(const string& __lhs, const string& __rhs) +{ return __lhs.compare(__rhs) == 0; } + +inline bool operator==(const char* __lhs, const string& __rhs) +{ return __rhs.compare(__lhs) == 0; } + +inline bool operator==(const string& __lhs, const char* __rhs) +{ return __lhs.compare(__rhs) == 0; } + +inline bool operator!=(const string& __lhs, const string& __rhs) +{ return __rhs.compare(__lhs) != 0; } + +inline bool operator!=(const char* __lhs, const string& __rhs) +{ return __rhs.compare(__lhs) != 0; } + +inline bool operator!=(const string& __lhs, const char* __rhs) +{ return __lhs.compare(__rhs) != 0; } + +#endif + +#else // ! VERIFY_ON + +#define verify(x) +#define trace_ctor(cls, args) +#define trace_dtor(cls) + +#endif // VERIFY_ON + +/********************************************************************** + * + * Logging + */ + +#if ! defined(NO_LOGGING) +#define LOGGING_ON 1 +#endif +#if defined(LOGGING_ON) + +// Logging + +enum log_level_t { + LOG_OFF = 0, + LOG_CRIT, + LOG_FATAL, + LOG_ASSERT, + LOG_ERROR, + LOG_VERIFY, + LOG_WARN, + LOG_INFO, + LOG_EXCEPT, + LOG_DEBUG, + LOG_TRACE, + LOG_ALL +}; + +extern log_level_t _log_level; +extern unsigned int _trace_level; +extern std::string _log_category; +extern std::ostream * _log_stream; +extern std::ostringstream _log_buffer; + +#define category(cat) \ + static const char * const _this_category = (cat) + +bool logger(log_level_t level); + +#if defined(TRACING_ON) +#define trace(lvl, msg) \ + (_log_level >= LOG_TRACE && lvl >= _trace_level ? \ + ((_log_buffer << msg), logger(LOG_TRACE)) : false) +#else +#define trace(lvl, msg) +#endif + +#if defined(DEBUG_ON) +#define debug_(cat, msg) \ + (_log_level >= LOG_DEBUG && \ + (_log_category == cat || \ + _log_category.find(cat ".") == 0) ? \ + ((_log_buffer << msg), logger(LOG_DEBUG)) : false) +#define debug(msg) debug_(_this_category, msg) +#else +#define debug_(cat, msg) +#define debug(msg) +#endif + +#define info_(cat, msg) \ + (_log_level >= LOG_INFO && \ + (_log_category == cat || \ + _log_category.find(cat ".") == 0) ? \ + ((_log_buffer << msg), logger(LOG_INFO)) : false) +#define info(msg) info_(_this_category, msg) + +#define log_macro(level, msg) \ + (_log_level >= level ? \ + ((_log_buffer << msg), logger(level)) : false) + +#define warn(msg) log_macro(LOG_WARN, msg) +#define error(msg) log_macro(LOG_ERROR, msg) +#define fatal(msg) log_macro(LOG_FATAL, msg) +#define critical(msg) log_macro(LOG_CRIT, msg) + +#else // ! LOGGING_ON + +#define category(cat) +#define trace(lvl, msg) +#define debug(msg) +#define debug_(cat, msg) +#define info(msg) +#define info_(cat, msg) +#define warn(msg) +#define error(msg) +#define fatal(msg) +#define critical(msg) + +/********************************************************************** + * + * Timers (allows log entries to specify cumulative time spent) + */ + +#if defined(LOGGING_ON) && defined(TIMERS_ON) + +struct timer_t { + std::clock_t count; + std::string message; +}; + +typedef std::map<std::string, timer_t> timing_map; +typedef timing_map::value_type timing_pair; + +void start_timer(const char * name); +void stop_timer(const char * name); +void finish_timer(const char * name); + +#if defined(TRACING_ON) +#define trace_start(name, lvl, msg) \ + (trace(lvl, msg) && start_timer(name)) +#define trace_stop(name) stop_timer(name) +#define trace_finish(name) finish_timer(name) +#else +#define trace_start(name, lvl, msg) +#define trace_stop(name) +#define trace_finish(name) +#endif + +#if defined(DEBUG_ON) +#define debug_start(name, msg) \ + (debug(msg) && start_timer(name)) +#define debug_start_(name, cat, msg) \ + (debug_(cat, msg) && start_timer(name)) +#define debug_stop(name) stop_timer(name) +#define debug_finish(name) finish_timer(name) +#else +#define debug_start(name, msg) +#define debug_start_(name, cat, msg) +#define debug_stop(name) +#define debug_finish(name) +#endif + +#define info_start(name, msg) \ + (info(msg) && start_timer(name)) +#define info_start_(name, cat, msg) +#define info_stop(name) stop_timer(name) +#define info_finish(name) finish_timer(name) + +#else // ! (LOGGING_ON && TIMERS_ON) + +#define trace_start(lvl, msg, name) +#define trace_stop(name) +#define trace_finish(name) + +#define debug_start(name, msg) +#define debug_start_(name, cat, msg) +#define debug_stop(name) +#define debug_finish(name) + +#define info_start(name, msg) +#define info_start_(name, cat, msg) +#define info_stop(name) +#define info_finish(name) + +#endif // TIMERS_ON + +/********************************************************************** + * + * Debug macros + */ + +#if defined(DEBUG_ON) + +#define if_debug_(cat) \ + if (_log_level >= LOG_DEBUG && \ + (_log_category == cat || \ + _log_category.find(cat ".") == 0)) +#define if_debug() if_debug_(_this_category) + +#else // ! DEBUG_ON + +#define if_debug(cat) if (false) + +#endif // DEBUG_ON + +// } namespace ledger #endif // _UTILS_H |