]> Dogcows Code - chaz/yoink/blob - src/stlplus/portability/debug.cpp
import stlplus 3.7
[chaz/yoink] / src / stlplus / portability / debug.cpp
1 ////////////////////////////////////////////////////////////////////////////////
2
3 // Author: Andy Rushton
4 // Copyright: (c) Southampton University 1999-2004
5 // (c) Andy Rushton 2004 onwards
6 // License: BSD License, see ../docs/license.html
7
8 ////////////////////////////////////////////////////////////////////////////////
9
10 #include "debug.hpp"
11 #include "dprintf.hpp"
12 #include <string.h>
13 #include <stdlib.h>
14 #include <stdio.h>
15
16 ////////////////////////////////////////////////////////////////////////////////
17
18 namespace stlplus
19 {
20
21 ////////////////////////////////////////////////////////////////////////////////
22
23 static std::string format(const char* file, int line, const char* function, const char* message)
24 {
25 return dformat("%s:%d:%s: assertion failed: %s",
26 (file ? file : ""),
27 line,
28 (function ? function : "") ,
29 (message ? message : ""));
30 }
31
32 ////////////////////////////////////////////////////////////////////////////////
33
34 assert_failed::assert_failed(const char* file, int line, const char* function, const char* message)
35 throw() :
36 std::logic_error(format(file, line, function, message))
37 {
38 }
39
40 assert_failed::~assert_failed(void) throw()
41 {
42 }
43
44 ////////////////////////////////////////////////////////////////////////////////
45
46 static unsigned _debug_depth = 0;
47 static bool _debug_global = false;
48 static bool _debug_set = false;
49 static bool _debug_recurse = false;
50 static bool _debug_read = false;
51 static char* _debug_match = 0;
52 static const debug_trace* debug_last = 0;
53
54 void debug_global(const char* file, int line, const char* function, bool state)
55 {
56 _debug_global = state;
57 fprintf(stderr, "%s:%i:[%i]%s ", file, line, _debug_depth, function ? function : "");
58 fprintf(stderr, "debug global : %s\n", _debug_global ? "on" : "off");
59 }
60
61 void debug_assert_fail(const char* file, int line, const char* function, const char* test)
62 throw(assert_failed)
63 {
64 fprintf(stderr, "%s:%i:[%i]%s: assertion failed: %s\n",
65 file, line, _debug_depth, function ? function : "", test);
66 if (debug_last) debug_last->stackdump();
67 throw assert_failed(file, line, function, test);
68 }
69
70 ////////////////////////////////////////////////////////////////////////////////
71
72 debug_trace::debug_trace(const char* f, int l, const char* fn) :
73 m_file(f), m_line(l), m_function(fn ? fn : ""),
74 m_depth(0), m_last(debug_last), m_dbg(false), m_old(false)
75 {
76 if (!_debug_read)
77 {
78 _debug_match = getenv("DEBUG");
79 _debug_recurse = getenv("DEBUG_LOCAL") == 0;
80 _debug_read = true;
81 }
82 m_dbg = _debug_set || (_debug_match && (!_debug_match[0] || (strcmp(_debug_match, m_file) == 0)));
83 m_old = _debug_set;
84 if (m_dbg && _debug_recurse)
85 _debug_set = true;
86 m_depth = ++_debug_depth;
87 debug_last = this;
88 if (debug()) report(std::string("entering ") + (m_function ? m_function : ""));
89 }
90
91 debug_trace::~debug_trace(void)
92 {
93 if (debug()) report("leaving");
94 --_debug_depth;
95 _debug_set = m_old;
96 debug_last = m_last;
97 }
98
99 const char* debug_trace::file(void) const
100 {
101 return m_file;
102 }
103
104 int debug_trace::line(void) const
105 {
106 return m_line;
107 }
108
109 bool debug_trace::debug(void) const
110 {
111 return m_dbg || _debug_global;
112 }
113
114 void debug_trace::debug_on(int l, bool recurse)
115 {
116 m_dbg = true;
117 m_old = _debug_set;
118 if (recurse)
119 _debug_set = true;
120 report(l, std::string("debug on") + (recurse ? " recursive" : ""));
121 }
122
123 void debug_trace::debug_off(int l)
124 {
125 if (debug()) report(l, std::string("debug off"));
126 m_dbg = false;
127 _debug_set = m_old;
128 }
129
130 void debug_trace::prefix(int l) const
131 {
132 fprintf(stderr, "%s:%i:[%i]%s ", m_file, l, m_depth, m_function ? m_function : "");
133 }
134
135 void debug_trace::do_report(int l, const std::string& message) const
136 {
137 prefix(l);
138 fprintf(stderr, "%s\n", message.c_str());
139 fflush(stderr);
140 }
141
142 void debug_trace::do_report(const std::string& message) const
143 {
144 do_report(m_line, message);
145 }
146
147 void debug_trace::report(int l, const std::string& message) const
148 {
149 do_report(l, message);
150 }
151
152 void debug_trace::report(const std::string& message) const
153 {
154 report(m_line, message);
155 }
156
157 void debug_trace::error(int l, const std::string& message) const
158 {
159 do_report(l, "ERROR: " + message);
160 }
161
162 void debug_trace::error(const std::string& message) const
163 {
164 error(m_line, message);
165 }
166
167 void debug_trace::stackdump(int l, const std::string& message) const
168 {
169 do_report(l, message);
170 stackdump();
171 }
172
173 void debug_trace::stackdump(const std::string& message) const
174 {
175 stackdump(m_line, message);
176 }
177
178 void debug_trace::stackdump(void) const
179 {
180 for (const debug_trace* item = this; item; item = item->m_last)
181 item->do_report("...called from here");
182 }
183
184
185 ////////////////////////////////////////////////////////////////////////////////
186
187 } // end namespace stlplus
This page took 0.039416 seconds and 4 git commands to generate.