1 #ifndef STLPLUS_DEBUG
2 #define STLPLUS_DEBUG
3 ////////////////////////////////////////////////////////////////////////////////
4 
5 //   Author:    Andy Rushton
6 //   Copyright: (c) Southampton University 1999-2004
7 //              (c) Andy Rushton           2004 onwards
8 //   License:   BSD License, see ../docs/license.html
9 
10 //   Set of simple debug utilities, all of which are switched off by the
11 //   NDEBUG compiler directive
12 
13 ////////////////////////////////////////////////////////////////////////////////
14 
15 #include "portability_fixes.hpp"
16 #include <stdexcept>
17 #include <string>
18 
19 ////////////////////////////////////////////////////////////////////////////////
20 // Problem with missing __FUNCTION__ macro
21 ////////////////////////////////////////////////////////////////////////////////
22 
23 // this macro is used in debugging but was missing in Visual Studio prior to version 7
24 #if defined(_MSC_VER) && (_MSC_VER < 1300)
25 #define __FUNCTION__ 0
26 #endif
27 
28 // old versions of Borland compiler defined a macro __FUNC__ but more recent ones define __FUNCTION__
29 // I'm not sure at what version this change was made - assumed C++ Builder 6.32
30 #if defined(__BORLANDC__) && (__BORLANDC__ < 1585)
31 #define __FUNCTION__ __FUNC__
32 #endif
33 
34 ////////////////////////////////////////////////////////////////////////////////
35 // Exception thrown if an assertion fails
36 
37 namespace stlplus
38 {
39 
40   class assert_failed : public std::logic_error
41   {
42   public:
43     assert_failed(const char* file, int line, const char* function, const char* message) ;
44     ~assert_failed(void) throw();
45   };
46 
47 } // end namespace stlplus
48 
49   ////////////////////////////////////////////////////////////////////////////////
50   // The macros used in debugging
51 
52 #ifndef NDEBUG
53 
54 #define DEBUG_TRACE stlplus::debug_trace stlplus_debug_trace(__FILE__,__LINE__,__FUNCTION__)
55 #define IF_DEBUG(stmts) {if (stlplus_debug_trace.debug()){stlplus_debug_trace.prefix(__LINE__);stmts;}}
56 #define DEBUG_REPORT(str) IF_DEBUG(stlplus_debug_trace.report(__LINE__,str))
57 #define DEBUG_ERROR(str) stlplus_debug_trace.error(__LINE__,str)
58 #define DEBUG_STACKDUMP(str) stlplus_debug_trace.stackdump(__LINE__,str)
59 #define DEBUG_ON stlplus_debug_trace.debug_on(__LINE__,true)
60 #define DEBUG_ON_LOCAL stlplus_debug_trace.debug_on(__LINE__,false)
61 #define DEBUG_ON_GLOBAL stlplus::debug_global(__FILE__,__LINE__,__FUNCTION__,true)
62 #define DEBUG_OFF_GLOBAL stlplus::debug_global(__FILE__,__LINE__,__FUNCTION__,false)
63 #define DEBUG_OFF stlplus_debug_trace.debug_off(__LINE__)
64 #define DEBUG_ASSERT(test) if (!(test))stlplus::debug_assert_fail(__FILE__,__LINE__,__FUNCTION__,#test)
65 
66 #else
67 
68 #define DEBUG_TRACE
69 #define IF_DEBUG(stmts)
70 #define DEBUG_REPORT(str)
71 #define DEBUG_ERROR(str)
72 #define DEBUG_STACKDUMP(str)
73 #define DEBUG_ON
74 #define DEBUG_ON_LOCAL
75 #define DEBUG_ON_GLOBAL
76 #define DEBUG_OFF_GLOBAL
77 #define DEBUG_OFF
78 #define DEBUG_ASSERT(test)
79 
80 #endif
81 
82 ////////////////////////////////////////////////////////////////////////////////
83 // infrastructure - don't use directly
84 
85 namespace stlplus
86 {
87 
88   void debug_global(const char* file, int line, const char* function, bool state = true);
89   // exceptions: assert_failed
90   void debug_assert_fail(const char* file, int line, const char* function, const char* test) ;
91 
92   class debug_trace
93   {
94   public:
95     debug_trace(const char* f, int l, const char* fn);
96     ~debug_trace(void);
97     const char* file(void) const;
98     int line(void) const;
99     bool debug(void) const;
100     void debug_on(int l, bool recurse);
101     void debug_off(int l);
102     void prefix(int l) const;
103     void report(int l, const std::string& message) const;
104     void report(const std::string& message) const;
105     void error(int l, const std::string& message) const;
106     void error(const std::string& message) const;
107     void stackdump(int l, const std::string& message) const;
108     void stackdump(const std::string& message) const;
109     void stackdump(void) const;
110 
111   private:
112     const char* m_file;
113     int m_line;
114     const char* m_function;
115     unsigned m_depth;
116     const debug_trace* m_last;
117     bool m_dbg;
118     bool m_old;
119     void do_report(int l, const std::string& message) const;
120     void do_report(const std::string& message) const;
121 
122     // make this class uncopyable
123     debug_trace(const debug_trace&);
124     debug_trace& operator = (const debug_trace&);
125   };
126 
127 } // end namespace stlplus
128 
129   ////////////////////////////////////////////////////////////////////////////////
130 #endif
131