zenilib: zenilib/jni/external/sdl/src/SDL_assert.c Source File

zenilib 0.5.3.0

- Main Page
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
SDL_assert.c
Go to the documentation of this file.
1 /*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "SDL_config.h"
22
23 #include "SDL.h"
24 #include "SDL_atomic.h"
25 #include "SDL_messagebox.h"
26 #include "SDL_video.h"
27 #include "SDL_assert.h"
28 #include "SDL_assert_c.h"
29 #include "video/SDL_sysvideo.h"
30
31 #ifdef __WIN32__
32 #include "core/windows/SDL_windows.h"
33
34 #ifndef WS_OVERLAPPEDWINDOW
35 #define WS_OVERLAPPEDWINDOW 0
36 #endif
37 #else /* fprintf, _exit(), etc. */
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <unistd.h>
41 #endif
42
43 static SDL_assert_state
44 SDL_PromptAssertion(const SDL_assert_data *data, void *userdata);
45
46 /*
47 * We keep all triggered assertions in a singly-linked list so we can
48 * generate a report later.
49 */
50 static SDL_assert_data *triggered_assertions = NULL;
51
52 static SDL_mutex *assertion_mutex = NULL;
53 static SDL_AssertionHandler assertion_handler = SDL_PromptAssertion;
54 static void *assertion_userdata = NULL;
55
56 #ifdef __GNUC__
57 static void
58 debug_print(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
59 #endif
60
61 static void
62 debug_print(const char *fmt, ...)
63 {
64 va_list ap;
65 va_start(ap, fmt);
66 SDL_LogMessageV(SDL_LOG_CATEGORY_ASSERT, SDL_LOG_PRIORITY_WARN, fmt, ap);
67 va_end(ap);
68 }
69
70
71 static void SDL_AddAssertionToReport(SDL_assert_data *data)
72 {
73 /* (data) is always a static struct defined with the assert macros, so
74 we don't have to worry about copying or allocating them. */
75 data->trigger_count++;
76 if (data->trigger_count == 1) { /* not yet added? */
77 data->next = triggered_assertions;
78 triggered_assertions = data;
79 }
80 }
81
82
83 static void SDL_GenerateAssertionReport(void)
84 {
85 const SDL_assert_data *item = triggered_assertions;
86
87 /* only do this if the app hasn't assigned an assertion handler. */
88 if ((item != NULL) && (assertion_handler != SDL_PromptAssertion)) {
89 debug_print("\n\nSDL assertion report.\n");
90 debug_print("All SDL assertions between last init/quit:\n\n");
91
92 while (item != NULL) {
93 debug_print(
94 "'%s'\n"
95 " * %s (%s:%d)\n"
96 " * triggered %u time%s.\n"
97 " * always ignore: %s.\n",
98 item->condition, item->function, item->filename,
99 item->linenum, item->trigger_count,
100 (item->trigger_count == 1) ? "" : "s",
101 item->always_ignore ? "yes" : "no");
102 item = item->next;
103 }
104 debug_print("\n");
105
106 SDL_ResetAssertionReport();
107 }
108 }
109
110 static void SDL_ExitProcess(int exitcode)
111 {
112 #ifdef __WIN32__
113 ExitProcess(exitcode);
114 #else
115 _exit(exitcode);
116 #endif
117 }
118
119 static void SDL_AbortAssertion(void)
120 {
121 SDL_Quit();
122 SDL_ExitProcess(42);
123 }
124
125
126 static SDL_assert_state
127 SDL_PromptAssertion(const SDL_assert_data *data, void *userdata)
128 {
129 #ifdef __WIN32__
130 #define ENDLINE "\r\n"
131 #else
132 #define ENDLINE "\n"
133 #endif
134
135 const char *envr;
136 SDL_assert_state state = SDL_ASSERTION_ABORT;
137 SDL_Window *window;
138 SDL_MessageBoxData messagebox;
139 SDL_MessageBoxButtonData buttons[] = {
140 { 0, SDL_ASSERTION_RETRY, "Retry" },
141 { 0, SDL_ASSERTION_BREAK, "Break" },
142 { 0, SDL_ASSERTION_ABORT, "Abort" },
143 { SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT,
144 SDL_ASSERTION_IGNORE, "Ignore" },
145 { SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT,
146 SDL_ASSERTION_ALWAYS_IGNORE, "Always Ignore" }
147 };
148 char *message;
149 int selected;
150
151 (void) userdata; /* unused in default handler. */
152
153 message = SDL_stack_alloc(char, SDL_MAX_LOG_MESSAGE);
154 if (!message) {
155 /* Uh oh, we're in real trouble now... */
156 return SDL_ASSERTION_ABORT;
157 }
158 SDL_snprintf(message, SDL_MAX_LOG_MESSAGE,
159 "Assertion failure at %s (%s:%d), triggered %u %s:" ENDLINE
160 " '%s'",
161 data->function, data->filename, data->linenum,
162 data->trigger_count, (data->trigger_count == 1) ? "time" : "times",
163 data->condition);
164
165 debug_print("\n\n%s\n\n", message);
166
167 /* let env. variable override, so unit tests won't block in a GUI. */
168 envr = SDL_getenv("SDL_ASSERT");
169 if (envr != NULL) {
170 SDL_stack_free(message);
171
172 if (SDL_strcmp(envr, "abort") == 0) {
173 return SDL_ASSERTION_ABORT;
174 } else if (SDL_strcmp(envr, "break") == 0) {
175 return SDL_ASSERTION_BREAK;
176 } else if (SDL_strcmp(envr, "retry") == 0) {
177 return SDL_ASSERTION_RETRY;
178 } else if (SDL_strcmp(envr, "ignore") == 0) {
179 return SDL_ASSERTION_IGNORE;
180 } else if (SDL_strcmp(envr, "always_ignore") == 0) {
181 return SDL_ASSERTION_ALWAYS_IGNORE;
182 } else {
183 return SDL_ASSERTION_ABORT; /* oh well. */
184 }
185 }
186
187 /* Leave fullscreen mode, if possible (scary!) */
188 window = SDL_GetFocusWindow();
189 if (window) {
190 if (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) {
191 SDL_MinimizeWindow(window);
192 } else {
193 /* !!! FIXME: ungrab the input if we're not fullscreen? */
194 /* No need to mess with the window */
195 window = NULL;
196 }
197 }
198
199 /* Show a messagebox if we can, otherwise fall back to stdio */
200 SDL_zero(messagebox);
201 messagebox.flags = SDL_MESSAGEBOX_WARNING;
202 messagebox.window = window;
203 messagebox.title = "Assertion Failed";
204 messagebox.message = message;
205 messagebox.numbuttons = SDL_arraysize(buttons);
206 messagebox.buttons = buttons;
207
208 if (SDL_ShowMessageBox(&messagebox, &selected) == 0) {
209 if (selected == -1) {
210 state = SDL_ASSERTION_IGNORE;
211 } else {
212 state = (SDL_assert_state)selected;
213 }
214 }
215 #ifdef HAVE_STDIO_H
216 else
217 {
218 /* this is a little hacky. */
219 for ( ; ; ) {
220 char buf[32];
221 fprintf(stderr, "Abort/Break/Retry/Ignore/AlwaysIgnore? [abriA] : ");
222 fflush(stderr);
223 if (fgets(buf, sizeof (buf), stdin) == NULL) {
224 break;
225 }
226
227 if (SDL_strcmp(buf, "a") == 0) {
228 state = SDL_ASSERTION_ABORT;
229 break;
230 } else if (SDL_strcmp(buf, "b") == 0) {
231 state = SDL_ASSERTION_BREAK;
232 break;
233 } else if (SDL_strcmp(buf, "r") == 0) {
234 state = SDL_ASSERTION_RETRY;
235 break;
236 } else if (SDL_strcmp(buf, "i") == 0) {
237 state = SDL_ASSERTION_IGNORE;
238 break;
239 } else if (SDL_strcmp(buf, "A") == 0) {
240 state = SDL_ASSERTION_ALWAYS_IGNORE;
241 break;
242 }
243 }
244 }
245 #endif /* HAVE_STDIO_H */
246
247 /* Re-enter fullscreen mode */
248 if (window) {
249 SDL_RestoreWindow(window);
250 }
251
252 SDL_stack_free(message);
253
254 return state;
255 }
256
257
258 SDL_assert_state
259 SDL_ReportAssertion(SDL_assert_data *data, const char *func, const char *file,
260 int line)
261 {
262 static int assertion_running = 0;
263 static SDL_SpinLock spinlock = 0;
264 SDL_assert_state state = SDL_ASSERTION_IGNORE;
265
266 SDL_AtomicLock(&spinlock);
267 if (assertion_mutex == NULL) { /* never called SDL_Init()? */
268 assertion_mutex = SDL_CreateMutex();
269 if (assertion_mutex == NULL) {
270 SDL_AtomicUnlock(&spinlock);
271 return SDL_ASSERTION_IGNORE; /* oh well, I guess. */
272 }
273 }
274 SDL_AtomicUnlock(&spinlock);
275
276 if (SDL_LockMutex(assertion_mutex) < 0) {
277 return SDL_ASSERTION_IGNORE; /* oh well, I guess. */
278 }
279
280 /* doing this because Visual C is upset over assigning in the macro. */
281 if (data->trigger_count == 0) {
282 data->function = func;
283 data->filename = file;
284 data->linenum = line;
285 }
286
287 SDL_AddAssertionToReport(data);
288
289 assertion_running++;
290 if (assertion_running > 1) { /* assert during assert! Abort. */
291 if (assertion_running == 2) {
292 SDL_AbortAssertion();
293 } else if (assertion_running == 3) { /* Abort asserted! */
294 SDL_ExitProcess(42);
295 } else {
296 while (1) { /* do nothing but spin; what else can you do?! */ }
297 }
298 }
299
300 if (!data->always_ignore) {
301 state = assertion_handler(data, assertion_userdata);
302 }
303
304 switch (state)
305 {
306 case SDL_ASSERTION_ABORT:
307 SDL_AbortAssertion();
308 return SDL_ASSERTION_IGNORE; /* shouldn't return, but oh well. */
309
310 case SDL_ASSERTION_ALWAYS_IGNORE:
311 state = SDL_ASSERTION_IGNORE;
312 data->always_ignore = 1;
313 break;
314
315 case SDL_ASSERTION_IGNORE:
316 case SDL_ASSERTION_RETRY:
317 case SDL_ASSERTION_BREAK:
318 break; /* macro handles these. */
319 }
320
321 assertion_running--;
322 SDL_UnlockMutex(assertion_mutex);
323
324 return state;
325 }
326
327
328 void SDL_AssertionsQuit(void)
329 {
330 SDL_GenerateAssertionReport();
331 if (assertion_mutex != NULL) {
332 SDL_DestroyMutex(assertion_mutex);
333 assertion_mutex = NULL;
334 }
335 }
336
337 void SDL_SetAssertionHandler(SDL_AssertionHandler handler, void *userdata)
338 {
339 if (handler != NULL) {
340 assertion_handler = handler;
341 assertion_userdata = userdata;
342 } else {
343 assertion_handler = SDL_PromptAssertion;
344 assertion_userdata = NULL;
345 }
346 }
347
348 const SDL_assert_data *SDL_GetAssertionReport(void)
349 {
350 return triggered_assertions;
351 }
352
353 void SDL_ResetAssertionReport(void)
354 {
355 SDL_assert_data *next = NULL;
356 SDL_assert_data *item;
357 for (item = triggered_assertions; item != NULL; item = next) {
358 next = (SDL_assert_data *) item->next;
359 item->always_ignore = SDL_FALSE;
360 item->trigger_count = 0;
361 item->next = NULL;
362 }
363
364 triggered_assertions = NULL;
365 }
366
367 /* vi: set ts=4 sw=4 expandtab: */
assertion_handler
static SDL_AssertionHandler assertion_handler
Definition: SDL_assert.c:53
SDL_MessageBoxData::message
const char * message
Definition: SDL_messagebox.h:97
SDL_assert_c.h
SDL_MAX_LOG_MESSAGE
#define SDL_MAX_LOG_MESSAGE
The maximum size of a log message.
Definition: SDL_log.h:54
SDL_GenerateAssertionReport
static void SDL_GenerateAssertionReport(void)
Definition: SDL_assert.c:83
void
GLvoid **typedef void(GLAPIENTRY *PFNGLGETVERTEXATTRIBDVPROC)(GLuint
Definition: glew.h:1824
message
GLsizei GLenum GLuint GLuint GLsizei GLchar * message
Definition: glew.h:2540
triggered_assertions
static SDL_assert_data * triggered_assertions
Definition: SDL_assert.c:50
SDL_MessageBoxData::title
const char * title
Definition: SDL_messagebox.h:96
SDL_AtomicUnlock
DECLSPEC void SDLCALL SDL_AtomicUnlock(SDL_SpinLock *lock)
Unlock a spin lock by setting it to 0. Always returns immediately.
Definition: SDL_spinlock.c:109
SDL_MessageBoxData::window
SDL_Window * window
Definition: SDL_messagebox.h:95
NULL
#define NULL
Definition: ftobjs.h:61
SDL_snprintf
DECLSPEC int SDLCALL SDL_snprintf(char *text, size_t maxlen, const char *fmt,...)
Definition: SDL_string.c:1277
SDL_AbortAssertion
static void SDL_AbortAssertion(void)
Definition: SDL_assert.c:119
SDL_assert_data
Definition: SDL_assert.h:107
SDL_stack_free
#define SDL_stack_free(data)
Definition: SDL_stdinc.h:227
SDL_LockMutex
DECLSPEC int SDLCALL SDL_LockMutex(SDL_mutex *mutex)
Definition: SDL_sysmutex.c:73
SDL_MessageBoxData::flags
Uint32 flags
Definition: SDL_messagebox.h:94
SDL_assert_state
SDL_assert_state
Definition: SDL_assert.h:98
SDL_MESSAGEBOX_WARNING
Definition: SDL_messagebox.h:40
SDL_CreateMutex
DECLSPEC SDL_mutex *SDLCALL SDL_CreateMutex(void)
Definition: SDL_sysmutex.c:38
SDL_messagebox.h
file
FILE * file
Definition: visualinfo.c:88
SDL_assert_data::always_ignore
int always_ignore
Definition: SDL_assert.h:109
assertion_userdata
static void * assertion_userdata
Definition: SDL_assert.c:54
SDL_Quit
DECLSPEC void SDLCALL SDL_Quit(void)
Definition: SDL.c:342
SDL_FALSE
Definition: SDL_stdinc.h:118
func
GLenum func
Definition: SDL_opengl.h:5654
SDL_PromptAssertion
static SDL_assert_state SDL_PromptAssertion(const SDL_assert_data *data, void *userdata)
Definition: SDL_assert.c:127
debug_print
static void debug_print(const char *fmt,...)
Definition: SDL_assert.c:62
SDL_config.h
SDL_UnlockMutex
DECLSPEC int SDLCALL SDL_UnlockMutex(SDL_mutex *mutex)
Definition: SDL_sysmutex.c:160
SDL_assert_data::trigger_count
unsigned int trigger_count
Definition: SDL_assert.h:110
SDL_MessageBoxButtonData
Individual button data.
Definition: SDL_messagebox.h:56
SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT
Definition: SDL_messagebox.h:50
SDL_windows.h
SDL_atomic.h
SDL_assert_data::condition
const char * condition
Definition: SDL_assert.h:111
SDL_MinimizeWindow
DECLSPEC void SDLCALL SDL_MinimizeWindow(SDL_Window *window)
Minimize a window to an iconic representation.
Definition: SDL_video.c:1783
SDL_AssertionsQuit
void SDL_AssertionsQuit(void)
Definition: SDL_assert.c:328
SDL_video.h
SDL_LogMessageV
DECLSPEC void SDLCALL SDL_LogMessageV(int category, SDL_LogPriority priority, const char *fmt, va_list ap)
Log a message with the specified category and priority.
Definition: SDL_log.c:267
SDL_AtomicLock
DECLSPEC void SDLCALL SDL_AtomicLock(SDL_SpinLock *lock)
Lock a spin lock by setting it to a non-zero value.
Definition: SDL_spinlock.c:100
__attribute__
Definition: mmx.h:46
SDL_MessageBoxData::numbuttons
int numbuttons
Definition: SDL_messagebox.h:99
data
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl2ext.h:848
SDL_GetFocusWindow
SDL_Window * SDL_GetFocusWindow(void)
Definition: SDL_video.c:2138
SDL_RestoreWindow
DECLSPEC void SDLCALL SDL_RestoreWindow(SDL_Window *window)
Restore the size and position of a minimized or maximized window.
Definition: SDL_video.c:1799
SDL_SetAssertionHandler
DECLSPEC void SDLCALL SDL_SetAssertionHandler(SDL_AssertionHandler handler, void *userdata)
Set an application-defined assertion handler.
Definition: SDL_assert.c:337
SDL_ASSERTION_ABORT
Definition: SDL_assert.h:102
SDL_assert_data::linenum
int linenum
Definition: SDL_assert.h:113
format
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl2ext.h:845
SDL_strcmp
DECLSPEC int SDLCALL SDL_strcmp(const char *str1, const char *str2)
Definition: SDL_string.c:910
SDL_GetWindowFlags
DECLSPEC Uint32 SDLCALL SDL_GetWindowFlags(SDL_Window *window)
Get the window flags.
Definition: SDL_video.c:1409
SDL_sysvideo.h
SDL_ASSERTION_ALWAYS_IGNORE
Definition: SDL_assert.h:104
SDL_MessageBoxData::buttons
const SDL_MessageBoxButtonData * buttons
Definition: SDL_messagebox.h:100
SDL_MessageBoxData
MessageBox structure containing title, text, window, etc.
Definition: SDL_messagebox.h:92
SDL_AssertionHandler
SDL_assert_state(SDLCALL * SDL_AssertionHandler)(const SDL_assert_data *data, void *userdata)
Definition: SDL_assert.h:178
SDL_AddAssertionToReport
static void SDL_AddAssertionToReport(SDL_assert_data *data)
Definition: SDL_assert.c:71
SDL_LOG_CATEGORY_ASSERT
Definition: SDL_log.h:68
SDL_ASSERTION_RETRY
Definition: SDL_assert.h:100
SDL_arraysize
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:83
SDL_ASSERTION_IGNORE
Definition: SDL_assert.h:103
SDL_mutex
struct SDL_mutex SDL_mutex
Definition: SDL_mutex.h:59
buf
GLenum GLuint GLsizei const GLchar * buf
Definition: glew.h:2539
SDL_Window
Definition: SDL_sysvideo.h:71
assertion_mutex
static SDL_mutex * assertion_mutex
Definition: SDL_assert.c:52
SDL_assert_data::filename
const char * filename
Definition: SDL_assert.h:112
SDL_assert_data::next
struct SDL_assert_data * next
Definition: SDL_assert.h:115
SDL_WINDOW_FULLSCREEN
Definition: SDL_video.h:98
SDL_LOG_PRIORITY_WARN
Definition: SDL_log.h:107
SDL_ReportAssertion
DECLSPEC SDL_assert_state SDLCALL SDL_ReportAssertion(SDL_assert_data *, const char *, const char *, int)
Definition: SDL_assert.c:259
SDL_stack_alloc
#define SDL_stack_alloc(type, count)
Definition: SDL_stdinc.h:226
SDL_GetAssertionReport
DECLSPEC const SDL_assert_data *SDLCALL SDL_GetAssertionReport(void)
Get a list of all assertion failures.
Definition: SDL_assert.c:348
SDL_getenv
DECLSPEC char *SDLCALL SDL_getenv(const char *name)
Definition: SDL_getenv.c:179
SDL_zero
#define SDL_zero(x)
Definition: SDL_stdinc.h:254
SDL_DestroyMutex
DECLSPEC void SDLCALL SDL_DestroyMutex(SDL_mutex *mutex)
Definition: SDL_sysmutex.c:61
SDL_SpinLock
int SDL_SpinLock
Definition: SDL_atomic.h:96
ENDLINE
#define ENDLINE
SDL_ShowMessageBox
DECLSPEC int SDLCALL SDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
Create a modal message box.
Definition: SDL_video.c:3122
SDL_ResetAssertionReport
DECLSPEC void SDLCALL SDL_ResetAssertionReport(void)
Reset the list of all assertion failures.
Definition: SDL_assert.c:353
SDL_ExitProcess
static void SDL_ExitProcess(int exitcode)
Definition: SDL_assert.c:110
SDL_assert_data::function
const char * function
Definition: SDL_assert.h:114
SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT
Definition: SDL_messagebox.h:49
SDL_assert.h
SDL_ASSERTION_BREAK
Definition: SDL_assert.h:101