Mercurial > sdl-ios-xcode
comparison src/SDL_assert.c @ 3670:62b6a5b99918
Clean up assertion API for public use.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Wed, 13 Jan 2010 19:29:33 +0000 |
parents | 46d27a9571fa |
children | 0d6f520c0eb9 |
comparison
equal
deleted
inserted
replaced
3669:46d27a9571fa | 3670:62b6a5b99918 |
---|---|
20 slouken@libsdl.org | 20 slouken@libsdl.org |
21 */ | 21 */ |
22 | 22 |
23 #include "SDL.h" | 23 #include "SDL.h" |
24 #include "SDL_assert.h" | 24 #include "SDL_assert.h" |
25 | |
26 #if (SDL_ASSERT_LEVEL > 0) | |
27 | 25 |
28 #ifdef _WINDOWS | 26 #ifdef _WINDOWS |
29 #define WIN32_LEAN_AND_MEAN 1 | 27 #define WIN32_LEAN_AND_MEAN 1 |
30 #include <windows.h> | 28 #include <windows.h> |
31 #else /* fprintf, _exit(), etc. */ | 29 #else /* fprintf, _exit(), etc. */ |
32 #include <stdio.h> | 30 #include <stdio.h> |
33 #include <stdlib.h> | 31 #include <stdlib.h> |
34 #include <unistd.h> | 32 #include <unistd.h> |
35 #endif | 33 #endif |
36 | 34 |
37 /* We can keep all triggered assertions in a singly-linked list so we can | 35 static SDL_assert_state |
36 SDL_PromptAssertion(const SDL_assert_data *data, void *userdata); | |
37 | |
38 /* | |
39 * We keep all triggered assertions in a singly-linked list so we can | |
38 * generate a report later. | 40 * generate a report later. |
39 */ | 41 */ |
40 #if !SDL_ASSERTION_REPORT_DISABLED | |
41 static SDL_assert_data assertion_list_terminator = { 0, 0, 0, 0, 0, 0, 0 }; | 42 static SDL_assert_data assertion_list_terminator = { 0, 0, 0, 0, 0, 0, 0 }; |
42 static SDL_assert_data *triggered_assertions = &assertion_list_terminator; | 43 static SDL_assert_data *triggered_assertions = &assertion_list_terminator; |
43 #endif | 44 |
45 static SDL_mutex *assertion_mutex = NULL; | |
46 static SDL_AssertionHandler assertion_handler = SDL_PromptAssertion; | |
47 static void *assertion_userdata = NULL; | |
44 | 48 |
45 #ifdef __GNUC__ | 49 #ifdef __GNUC__ |
46 static void | 50 static void |
47 debug_print(const char *fmt, ...) __attribute__((format (printf, 1, 2))); | 51 debug_print(const char *fmt, ...) __attribute__((format (printf, 1, 2))); |
48 #endif | 52 #endif |
196 #endif | 200 #endif |
197 | 201 |
198 | 202 |
199 static void SDL_AddAssertionToReport(SDL_assert_data *data) | 203 static void SDL_AddAssertionToReport(SDL_assert_data *data) |
200 { | 204 { |
201 #if !SDL_ASSERTION_REPORT_DISABLED | |
202 /* (data) is always a static struct defined with the assert macros, so | 205 /* (data) is always a static struct defined with the assert macros, so |
203 we don't have to worry about copying or allocating them. */ | 206 we don't have to worry about copying or allocating them. */ |
204 if (data->next == NULL) { /* not yet added? */ | 207 if (data->next == NULL) { /* not yet added? */ |
205 data->next = triggered_assertions; | 208 data->next = triggered_assertions; |
206 triggered_assertions = data; | 209 triggered_assertions = data; |
207 } | 210 } |
208 #endif | 211 } |
209 } | 212 |
210 | 213 |
211 static void SDL_GenerateAssertionReport(void) | 214 static void SDL_GenerateAssertionReport(void) |
212 { | 215 { |
213 #if !SDL_ASSERTION_REPORT_DISABLED | 216 const SDL_assert_data *item; |
214 if (triggered_assertions != &assertion_list_terminator) | 217 |
218 /* only do this if the app hasn't assigned an assertion handler. */ | |
219 if (assertion_handler != SDL_PromptAssertion) | |
220 return; | |
221 | |
222 item = SDL_GetAssertionReport(); | |
223 if (item->condition) | |
215 { | 224 { |
216 SDL_assert_data *item = triggered_assertions; | |
217 | |
218 debug_print("\n\nSDL assertion report.\n"); | 225 debug_print("\n\nSDL assertion report.\n"); |
219 debug_print("All SDL assertions between last init/quit:\n\n"); | 226 debug_print("All SDL assertions between last init/quit:\n\n"); |
220 | 227 |
221 while (item != &assertion_list_terminator) { | 228 while (item->condition) { |
222 debug_print( | 229 debug_print( |
223 "'%s'\n" | 230 "'%s'\n" |
224 " * %s (%s:%d)\n" | 231 " * %s (%s:%d)\n" |
225 " * triggered %u time%s.\n" | 232 " * triggered %u time%s.\n" |
226 " * always ignore: %s.\n", | 233 " * always ignore: %s.\n", |
230 item->always_ignore ? "yes" : "no"); | 237 item->always_ignore ? "yes" : "no"); |
231 item = item->next; | 238 item = item->next; |
232 } | 239 } |
233 debug_print("\n"); | 240 debug_print("\n"); |
234 | 241 |
235 triggered_assertions = &assertion_list_terminator; | 242 SDL_ResetAssertionReport(); |
236 } | 243 } |
237 #endif | |
238 } | 244 } |
239 | 245 |
240 static void SDL_ExitProcess(int exitcode) | 246 static void SDL_ExitProcess(int exitcode) |
241 { | 247 { |
242 #ifdef _WINDOWS | 248 #ifdef _WINDOWS |
251 SDL_Quit(); | 257 SDL_Quit(); |
252 SDL_ExitProcess(42); | 258 SDL_ExitProcess(42); |
253 } | 259 } |
254 | 260 |
255 | 261 |
256 static SDL_assert_state SDL_PromptAssertion(const SDL_assert_data *data) | 262 static SDL_assert_state |
263 SDL_PromptAssertion(const SDL_assert_data *data, void *userdata) | |
257 { | 264 { |
258 const char *envr; | 265 const char *envr; |
259 SDL_assert_state state = SDL_ASSERTION_ABORT; | 266 SDL_assert_state state = SDL_ASSERTION_ABORT; |
260 SDL_WindowID window; | 267 SDL_WindowID window; |
268 | |
269 (void) userdata; /* unused in default handler. */ | |
261 | 270 |
262 debug_print("\n\n" | 271 debug_print("\n\n" |
263 "Assertion failure at %s (%s:%d), triggered %u time%s:\n" | 272 "Assertion failure at %s (%s:%d), triggered %u time%s:\n" |
264 " '%s'\n" | 273 " '%s'\n" |
265 "\n", | 274 "\n", |
289 window = SDL_GetFocusWindow(); | 298 window = SDL_GetFocusWindow(); |
290 if (window) { | 299 if (window) { |
291 if (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) { | 300 if (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) { |
292 SDL_MinimizeWindow(window); | 301 SDL_MinimizeWindow(window); |
293 } else { | 302 } else { |
303 /* !!! FIXME: ungrab the input if we're not fullscreen? */ | |
294 /* No need to mess with the window */ | 304 /* No need to mess with the window */ |
295 window = 0; | 305 window = 0; |
296 } | 306 } |
297 } | 307 } |
298 | 308 |
341 } | 351 } |
342 | 352 |
343 return state; | 353 return state; |
344 } | 354 } |
345 | 355 |
346 | |
347 static SDL_mutex *assertion_mutex = NULL; | |
348 | 356 |
349 SDL_assert_state | 357 SDL_assert_state |
350 SDL_ReportAssertion(SDL_assert_data *data, const char *func, const char *file, | 358 SDL_ReportAssertion(SDL_assert_data *data, const char *func, const char *file, |
351 int line) | 359 int line) |
352 { | 360 { |
389 while (1) { /* do nothing but spin; what else can you do?! */ } | 397 while (1) { /* do nothing but spin; what else can you do?! */ } |
390 } | 398 } |
391 } | 399 } |
392 | 400 |
393 if (!data->always_ignore) { | 401 if (!data->always_ignore) { |
394 state = SDL_PromptAssertion(data); | 402 state = assertion_handler(data, assertion_userdata); |
395 } | 403 } |
396 | 404 |
397 switch (state) | 405 switch (state) |
398 { | 406 { |
399 case SDL_ASSERTION_ABORT: | 407 case SDL_ASSERTION_ABORT: |
415 SDL_UnlockMutex(assertion_mutex); | 423 SDL_UnlockMutex(assertion_mutex); |
416 | 424 |
417 return state; | 425 return state; |
418 } | 426 } |
419 | 427 |
420 #endif /* SDL_ASSERT_LEVEL > 0 */ | |
421 | |
422 | 428 |
423 int SDL_AssertionsInit(void) | 429 int SDL_AssertionsInit(void) |
424 { | 430 { |
425 /* this is a no-op at the moment. */ | 431 /* this is a no-op at the moment. */ |
426 return 0; | 432 return 0; |
427 } | 433 } |
428 | 434 |
429 void SDL_AssertionsQuit(void) | 435 void SDL_AssertionsQuit(void) |
430 { | 436 { |
431 #if (SDL_ASSERT_LEVEL > 0) | |
432 SDL_GenerateAssertionReport(); | 437 SDL_GenerateAssertionReport(); |
433 if (assertion_mutex != NULL) { | 438 if (assertion_mutex != NULL) { |
434 SDL_DestroyMutex(assertion_mutex); | 439 SDL_DestroyMutex(assertion_mutex); |
435 assertion_mutex = NULL; | 440 assertion_mutex = NULL; |
436 } | 441 } |
437 #endif | 442 } |
443 | |
444 void SDL_SetAssertionHandler(SDL_AssertionHandler handler, void *userdata) | |
445 { | |
446 if (handler != NULL) { | |
447 assertion_handler = handler; | |
448 assertion_userdata = userdata; | |
449 } else { | |
450 assertion_handler = SDL_PromptAssertion; | |
451 assertion_userdata = NULL; | |
452 } | |
453 } | |
454 | |
455 const SDL_assert_data *SDL_GetAssertionReport(void) | |
456 { | |
457 return triggered_assertions; | |
458 } | |
459 | |
460 void SDL_ResetAssertionReport(void) | |
461 { | |
462 SDL_assert_data *item = triggered_assertions; | |
463 SDL_assert_data *next = NULL; | |
464 for (item = triggered_assertions; item->condition; item = next) { | |
465 next = (SDL_assert_data *) item->next; | |
466 item->always_ignore = SDL_FALSE; | |
467 item->trigger_count = 0; | |
468 item->next = NULL; | |
469 } | |
470 | |
471 triggered_assertions = &assertion_list_terminator; | |
438 } | 472 } |
439 | 473 |
440 /* vi: set ts=4 sw=4 expandtab: */ | 474 /* vi: set ts=4 sw=4 expandtab: */ |