1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
|
/**
@file debugAssert.h
debugAssert(expression);
debugAssertM(expression, message);
@cite
John Robbins, Microsoft Systems Journal Bugslayer Column, Feb 1999.
<A HREF="http://msdn.microsoft.com/library/periodic/period99/feb99_BUGSLAYE_BUGSLAYE.htm">
http://msdn.microsoft.com/library/periodic/period99/feb99_BUGSLAYE_BUGSLAYE.htm</A>
@cite
Douglas Cox, An assert() Replacement, Code of The Day, flipcode, Sept 19, 2000
<A HREF="http://www.flipcode.com/cgi-bin/msg.cgi?showThread=COTD-AssertReplace&forum=cotd&id=-1">
http://www.flipcode.com/cgi-bin/msg.cgi?showThread=COTD-AssertReplace&forum=cotd&id=-1</A>
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
@created 2001-08-26
@edited 2006-01-12
Copyright 2000-2006, Morgan McGuire.
All rights reserved.
*/
#ifndef G3D_DEBUGASSERT_H
#define G3D_DEBUGASSERT_H
#include <string>
#include "G3D/platform.h"
#include <cstdlib>
#ifdef _MSC_VER
#include <intrin.h>
// conditional expression is constant
# pragma warning (disable : 4127)
#endif
#ifdef G3D_LINUX
// Needed so we can define a global display
// pointer for debugAssert.
#if 0 /* G3DFIX: Disabled to avoid requirement for X11 libraries */
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#endif
#endif
/**
@def debugBreak()
Break at the current location (i.e. don't push a procedure stack frame
before breaking).
*/
/**
@def debugAssert(exp)
Breaks if the expression is false. If G3D_DEBUG_NOGUI is defined, prompts at
the console, otherwise pops up a dialog. The user may then break (debug),
ignore, or halt the program.
The assertion is also posted to the clipboard under Win32.
*/
/**
@def debugAssertM(exp, msg)
Breaks if the expression is false and displays a message. If G3D_DEBUG_NOGUI
is defined, prompts at the console, otherwise pops up a dialog. The user may
then break (debug), ignore, or halt the program.
The assertion is also posted to the clipboard under Win32.
*/
/**
@def alwaysAssertM(exp, msg)
Same as debugAssertM except that it asserts in release builds as well.
*/
namespace G3D {
typedef bool (*AssertionHook)(
const char* _expression,
const std::string& message,
const char* filename,
int lineNumber,
bool useGuiPrompt);
/**
Allows customization of the global function invoked when a debugAssert fails.
The initial value is G3D::_internal::_handleDebugAssert_. G3D will invoke
rawBreak if the hook returns true. If NULL, assertions are not handled.
*/
void setAssertionHook(AssertionHook hook);
AssertionHook assertionHook();
/**
Called by alwaysAssertM in case of failure in release mode. If returns
true then the program exits with -1 (you can replace this with your own
version that throws an exception or has other failure modes).
*/
void setFailureHook(AssertionHook hook);
AssertionHook failureHook();
namespace _internal {
extern AssertionHook _debugHook;
extern AssertionHook _failureHook;
} // internal
} // G3D
/**
@def __debugPromptShowDialog__
@internal
*/
#ifdef G3D_DEBUG
# if defined(_MSC_VER)
# define rawBreak() ::__debugbreak();
# elif defined(__i386__)
// gcc on intel
# define rawBreak() __asm__ __volatile__ ( "int $3" );
# else
// some other gcc
# define rawBreak() ::abort()
# endif
# define debugBreak() G3D::_internal::_releaseInputGrab_(); rawBreak(); G3D::_internal::_restoreInputGrab_();
# define debugAssert(exp) debugAssertM(exp, "Debug assertion failure")
#ifdef G3D_DEBUG_NOGUI
#define __debugPromptShowDialog__ false
#else
#define __debugPromptShowDialog__ true
#endif
#define debugAssertM(exp, message) do { \
if (!(exp)) { \
G3D::_internal::_releaseInputGrab_(); \
if ((G3D::_internal::_debugHook != NULL) && \
G3D::_internal::_debugHook((const char*)(#exp), message, __FILE__, __LINE__, __debugPromptShowDialog__)) { \
rawBreak(); \
} \
G3D::_internal::_restoreInputGrab_(); \
} \
} while (0)
#define alwaysAssertM debugAssertM
#else // Release
#ifdef G3D_DEBUG_NOGUI
#define __debugPromptShowDialog__ false
#else
#define __debugPromptShowDialog__ true
#endif
// In the release build, just define away assertions.
#define rawBreak() do {} while (0)
#define debugAssert(exp) do {} while (0)
#define debugAssertM(exp, message) do {} while (0)
#define debugBreak() do {} while (0)
// But keep the 'always' assertions
#define alwaysAssertM(exp, message) { \
if (!(exp)) { \
G3D::_internal::_releaseInputGrab_(); \
if ((G3D::_internal::_failureHook != NULL) && \
G3D::_internal::_failureHook(#exp, message, __FILE__, __LINE__, __debugPromptShowDialog__)) { \
::exit(-1); \
} \
G3D::_internal::_restoreInputGrab_(); \
} \
}
#endif // if debug
namespace G3D { namespace _internal {
#ifdef G3D_LINUX
#if 0 /* G3DFIX: Disabled to avoid requirement for X11 libraries */
/**
A pointer to the X11 display. Initially NULL. If set to a
non-null value (e.g. by SDLWindow), debugAssert attempts to use
this display to release the mouse/input grab when an assertion
fails.
*/
extern Display* x11Display;
/**
A pointer to the X11 window. Initially NULL. If set to a
non-null value (e.g. by SDLWindow), debugAssert attempts to use
this window to release the mouse/input grab when an assertion
fails.
*/
extern Window x11Window;
#endif
#endif
/**
Pops up an assertion dialog or prints an assertion
ignoreAlways - return result of pressing the ignore button.
useGuiPrompt - if true, shows a dialog
*/
bool _handleDebugAssert_(
const char* expression,
const std::string& message,
const char* filename,
int lineNumber,
bool useGuiPrompt);
bool _handleErrorCheck_(
const char* expression,
const std::string& message,
const char* filename,
int lineNumber,
bool useGuiPrompt);
/** Attempts to give the user back their mouse and keyboard if they
were locked to the current window.
@internal*/
void _releaseInputGrab_();
/** Attempts to restore the state before _releaseInputGrab_.
@internal*/
void _restoreInputGrab_();
}; }; // namespace
#endif
|