src/SDL_assert.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 16 Jan 2011 17:45:42 -0800
changeset 5006 8e8876e4aec6
parent 4472 791b3256fb22
child 5007 adf6f0c8ec35
permissions -rw-r--r--
Include windows.h in SDL_atomic.h by default, but don't include the atomic API in SDL.h
This allows all SDL code to take advantage of the atomic intrinsics on Windows, but doesn't cause applications just including SDL.h to pull in windows.h
slouken@3647
     1
/*
slouken@3647
     2
    SDL - Simple DirectMedia Layer
slouken@3697
     3
    Copyright (C) 1997-2010 Sam Lantinga
slouken@3647
     4
slouken@3647
     5
    This library is free software; you can redistribute it and/or
slouken@3647
     6
    modify it under the terms of the GNU Lesser General Public
slouken@3647
     7
    License as published by the Free Software Foundation; either
slouken@3647
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@3647
     9
slouken@3647
    10
    This library is distributed in the hope that it will be useful,
slouken@3647
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@3647
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@3647
    13
    Lesser General Public License for more details.
slouken@3647
    14
slouken@3647
    15
    You should have received a copy of the GNU Lesser General Public
slouken@3647
    16
    License along with this library; if not, write to the Free Software
slouken@3647
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@3647
    18
slouken@3647
    19
    Sam Lantinga
slouken@3647
    20
    slouken@libsdl.org
slouken@3647
    21
*/
slouken@3647
    22
slouken@3651
    23
#include "SDL.h"
slouken@5006
    24
#include "SDL_atomic.h"
slouken@3647
    25
#include "SDL_assert.h"
slouken@4472
    26
#include "SDL_assert_c.h"
slouken@3671
    27
#include "video/SDL_sysvideo.h"
slouken@3647
    28
slouken@3647
    29
#ifdef _WINDOWS
slouken@3647
    30
#define WIN32_LEAN_AND_MEAN 1
slouken@3647
    31
#include <windows.h>
slouken@3647
    32
#else  /* fprintf, _exit(), etc. */
slouken@3647
    33
#include <stdio.h>
slouken@3647
    34
#include <stdlib.h>
icculus@3648
    35
#include <unistd.h>
slouken@3647
    36
#endif
slouken@3647
    37
icculus@3670
    38
static SDL_assert_state
icculus@3670
    39
SDL_PromptAssertion(const SDL_assert_data *data, void *userdata);
icculus@3670
    40
icculus@3670
    41
/*
icculus@3670
    42
 * We keep all triggered assertions in a singly-linked list so we can
slouken@3647
    43
 *  generate a report later.
slouken@3647
    44
 */
slouken@3647
    45
static SDL_assert_data assertion_list_terminator = { 0, 0, 0, 0, 0, 0, 0 };
slouken@3647
    46
static SDL_assert_data *triggered_assertions = &assertion_list_terminator;
icculus@3670
    47
icculus@3670
    48
static SDL_mutex *assertion_mutex = NULL;
icculus@3670
    49
static SDL_AssertionHandler assertion_handler = SDL_PromptAssertion;
icculus@3670
    50
static void *assertion_userdata = NULL;
slouken@3647
    51
icculus@3648
    52
#ifdef __GNUC__
icculus@3661
    53
static void
icculus@3661
    54
debug_print(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
icculus@3648
    55
#endif
icculus@3648
    56
icculus@3648
    57
static void
icculus@3648
    58
debug_print(const char *fmt, ...)
slouken@3647
    59
{
slouken@3647
    60
#ifdef _WINDOWS
slouken@3647
    61
    /* Format into a buffer for OutputDebugStringA(). */
slouken@3647
    62
    char buf[1024];
slouken@3647
    63
    char *startptr;
slouken@3647
    64
    char *ptr;
slouken@3647
    65
    int len;
slouken@3647
    66
    va_list ap;
slouken@3647
    67
    va_start(ap, fmt);
slouken@3647
    68
    len = (int) SDL_vsnprintf(buf, sizeof (buf), fmt, ap);
slouken@3647
    69
    va_end(ap);
slouken@3647
    70
slouken@3647
    71
    /* Visual C's vsnprintf() may not null-terminate the buffer. */
slouken@3647
    72
    if ((len >= sizeof (buf)) || (len < 0)) {
slouken@3647
    73
        buf[sizeof (buf) - 1] = '\0';
slouken@3647
    74
    }
slouken@3647
    75
slouken@3647
    76
    /* Write it, sorting out the Unix newlines... */
slouken@3647
    77
    startptr = buf;
slouken@3647
    78
    for (ptr = startptr; *ptr; ptr++) {
slouken@3647
    79
        if (*ptr == '\n') {
slouken@3647
    80
            *ptr = '\0';
slouken@3647
    81
            OutputDebugStringA(startptr);
slouken@3647
    82
            OutputDebugStringA("\r\n");
slouken@3647
    83
            startptr = ptr+1;
slouken@3647
    84
        }
slouken@3647
    85
    }
slouken@3647
    86
slouken@3647
    87
    /* catch that last piece if it didn't have a newline... */
slouken@3647
    88
    if (startptr != ptr) {
slouken@3647
    89
        OutputDebugStringA(startptr);
slouken@3647
    90
    }
slouken@3647
    91
#else
slouken@3647
    92
    /* Unix has it easy. Just dump it to stderr. */
slouken@3647
    93
    va_list ap;
slouken@3647
    94
    va_start(ap, fmt);
icculus@3669
    95
    vfprintf(stderr, fmt, ap);
slouken@3647
    96
    va_end(ap);
slouken@3647
    97
    fflush(stderr);
slouken@3647
    98
#endif
slouken@3647
    99
}
slouken@3647
   100
slouken@3647
   101
slouken@3647
   102
#ifdef _WINDOWS
slouken@3647
   103
static SDL_assert_state SDL_Windows_AssertChoice = SDL_ASSERTION_ABORT;
slouken@3647
   104
static const SDL_assert_data *SDL_Windows_AssertData = NULL;
slouken@3647
   105
slouken@3647
   106
static LRESULT CALLBACK
slouken@3647
   107
SDL_Assertion_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
slouken@3647
   108
{
slouken@3647
   109
    switch (msg)
slouken@3647
   110
    {
slouken@3647
   111
        case WM_CREATE:
slouken@3647
   112
        {
slouken@3647
   113
            /* !!! FIXME: all this code stinks. */
slouken@3647
   114
            const SDL_assert_data *data = SDL_Windows_AssertData;
slouken@3647
   115
            char buf[1024];
slouken@3647
   116
            const int w = 100;
slouken@3647
   117
            const int h = 25;
slouken@3647
   118
            const int gap = 10;
slouken@3647
   119
            int x = gap;
slouken@3647
   120
            int y = 50;
slouken@3647
   121
            int len;
slouken@3647
   122
            int i;
slouken@3647
   123
            static const struct { 
slouken@3647
   124
                const char *name;
slouken@3647
   125
                SDL_assert_state state;
slouken@3647
   126
            } buttons[] = {
slouken@3647
   127
                {"Abort", SDL_ASSERTION_ABORT },
slouken@3647
   128
                {"Break", SDL_ASSERTION_BREAK },
slouken@3647
   129
                {"Retry", SDL_ASSERTION_RETRY },
slouken@3647
   130
                {"Ignore", SDL_ASSERTION_IGNORE },
slouken@3647
   131
                {"Always Ignore", SDL_ASSERTION_ALWAYS_IGNORE },
slouken@3647
   132
            };
slouken@3647
   133
slouken@3647
   134
            len = (int) SDL_snprintf(buf, sizeof (buf), 
slouken@3647
   135
                         "Assertion failure at %s (%s:%d), triggered %u time%s:\r\n  '%s'",
slouken@3647
   136
                         data->function, data->filename, data->linenum,
slouken@3647
   137
                         data->trigger_count, (data->trigger_count == 1) ? "" : "s",
slouken@3647
   138
                         data->condition);
slouken@3647
   139
            if ((len < 0) || (len >= sizeof (buf))) {
slouken@3647
   140
                buf[sizeof (buf) - 1] = '\0';
slouken@3647
   141
            }
slouken@3647
   142
slouken@3647
   143
            CreateWindowA("STATIC", buf,
slouken@3647
   144
                         WS_VISIBLE | WS_CHILD | SS_LEFT,
slouken@3647
   145
                         x, y, 550, 100,
slouken@3647
   146
                         hwnd, (HMENU) 1, NULL, NULL);
slouken@3647
   147
            y += 110;
slouken@3647
   148
slouken@3647
   149
            for (i = 0; i < (sizeof (buttons) / sizeof (buttons[0])); i++) {
slouken@3647
   150
                CreateWindowA("BUTTON", buttons[i].name,
slouken@3647
   151
                         WS_VISIBLE | WS_CHILD,
slouken@3647
   152
                         x, y, w, h,
slouken@3647
   153
                         hwnd, (HMENU) buttons[i].state, NULL, NULL);
slouken@3647
   154
                x += w + gap;
slouken@3647
   155
            }
slouken@3647
   156
            break;
slouken@3647
   157
        }
slouken@3647
   158
slouken@3647
   159
        case WM_COMMAND:
slouken@3647
   160
            SDL_Windows_AssertChoice = ((SDL_assert_state) (LOWORD(wParam)));
slouken@3647
   161
            SDL_Windows_AssertData = NULL;
slouken@3647
   162
            break;
slouken@3647
   163
slouken@3647
   164
        case WM_DESTROY:
slouken@3647
   165
            SDL_Windows_AssertData = NULL;
slouken@3647
   166
            break;
slouken@3647
   167
    }
slouken@3647
   168
slouken@3647
   169
    return DefWindowProc(hwnd, msg, wParam, lParam);
slouken@3647
   170
}
slouken@3647
   171
slouken@3647
   172
static SDL_assert_state
slouken@3647
   173
SDL_PromptAssertion_windows(const SDL_assert_data *data)
slouken@3647
   174
{
slouken@3647
   175
    HINSTANCE hInstance = 0;  /* !!! FIXME? */
slouken@3647
   176
    HWND hwnd;
slouken@3647
   177
    MSG msg;
slouken@3647
   178
    WNDCLASS wc = {0};
slouken@3647
   179
slouken@3647
   180
    SDL_Windows_AssertChoice = SDL_ASSERTION_ABORT;
slouken@3647
   181
    SDL_Windows_AssertData = data;
slouken@3647
   182
slouken@3647
   183
    wc.lpszClassName = TEXT("SDL_assert");
slouken@3647
   184
    wc.hInstance = hInstance ;
slouken@3647
   185
    wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
slouken@3647
   186
    wc.lpfnWndProc = SDL_Assertion_WndProc;
slouken@3647
   187
    wc.hCursor = LoadCursor(0, IDC_ARROW);
slouken@3647
   188
  
slouken@3647
   189
    RegisterClass(&wc);
slouken@3647
   190
    hwnd = CreateWindow(wc.lpszClassName, TEXT("SDL assertion failure"),
slouken@3647
   191
                 WS_OVERLAPPEDWINDOW | WS_VISIBLE,
slouken@3647
   192
                 150, 150, 570, 260, 0, 0, hInstance, 0);  
slouken@3647
   193
slouken@3647
   194
    while (GetMessage(&msg, NULL, 0, 0) && (SDL_Windows_AssertData != NULL)) {
slouken@3647
   195
        TranslateMessage(&msg);
slouken@3647
   196
        DispatchMessage(&msg);
slouken@3647
   197
    }
slouken@3647
   198
slouken@3647
   199
    DestroyWindow(hwnd);
slouken@3647
   200
    UnregisterClass(wc.lpszClassName, hInstance);
slouken@3647
   201
    return SDL_Windows_AssertChoice;
slouken@3647
   202
}
slouken@3647
   203
#endif
slouken@3647
   204
slouken@3647
   205
slouken@3647
   206
static void SDL_AddAssertionToReport(SDL_assert_data *data)
slouken@3647
   207
{
slouken@3647
   208
    /* (data) is always a static struct defined with the assert macros, so
slouken@3647
   209
       we don't have to worry about copying or allocating them. */
slouken@3647
   210
    if (data->next == NULL) {  /* not yet added? */
slouken@3647
   211
        data->next = triggered_assertions;
slouken@3647
   212
        triggered_assertions = data;
slouken@3647
   213
    }
slouken@3647
   214
}
slouken@3647
   215
icculus@3670
   216
slouken@3647
   217
static void SDL_GenerateAssertionReport(void)
slouken@3647
   218
{
icculus@3670
   219
    const SDL_assert_data *item;
icculus@3670
   220
icculus@3670
   221
    /* only do this if the app hasn't assigned an assertion handler. */
icculus@3670
   222
    if (assertion_handler != SDL_PromptAssertion)
icculus@3670
   223
        return;
icculus@3670
   224
icculus@3670
   225
    item = SDL_GetAssertionReport();
icculus@3670
   226
    if (item->condition)
slouken@3647
   227
    {
slouken@3647
   228
        debug_print("\n\nSDL assertion report.\n");
slouken@3647
   229
        debug_print("All SDL assertions between last init/quit:\n\n");
slouken@3647
   230
icculus@3670
   231
        while (item->condition) {
slouken@3647
   232
            debug_print(
slouken@3647
   233
                "'%s'\n"
slouken@3647
   234
                "    * %s (%s:%d)\n"
slouken@3647
   235
                "    * triggered %u time%s.\n"
slouken@3647
   236
                "    * always ignore: %s.\n",
slouken@3647
   237
                item->condition, item->function, item->filename,
slouken@3647
   238
                item->linenum, item->trigger_count,
slouken@3647
   239
                (item->trigger_count == 1) ? "" : "s",
slouken@3647
   240
                item->always_ignore ? "yes" : "no");
slouken@3647
   241
            item = item->next;
slouken@3647
   242
        }
slouken@3647
   243
        debug_print("\n");
slouken@3647
   244
icculus@3670
   245
        SDL_ResetAssertionReport();
slouken@3647
   246
    }
slouken@3647
   247
}
slouken@3647
   248
icculus@3661
   249
static void SDL_ExitProcess(int exitcode)
slouken@3647
   250
{
slouken@3647
   251
#ifdef _WINDOWS
slouken@3647
   252
    ExitProcess(42);
slouken@3656
   253
#else
slouken@3647
   254
    _exit(42);
slouken@3647
   255
#endif
slouken@3647
   256
}
icculus@3661
   257
icculus@3661
   258
static void SDL_AbortAssertion(void)
icculus@3661
   259
{
icculus@3661
   260
    SDL_Quit();
icculus@3661
   261
    SDL_ExitProcess(42);
icculus@3661
   262
}
icculus@3661
   263
slouken@3647
   264
icculus@3670
   265
static SDL_assert_state
icculus@3670
   266
SDL_PromptAssertion(const SDL_assert_data *data, void *userdata)
slouken@3647
   267
{
slouken@3647
   268
    const char *envr;
slouken@3657
   269
    SDL_assert_state state = SDL_ASSERTION_ABORT;
slouken@3685
   270
    SDL_Window *window;
slouken@3647
   271
icculus@3670
   272
    (void) userdata;  /* unused in default handler. */
icculus@3670
   273
slouken@3647
   274
    debug_print("\n\n"
slouken@3647
   275
                "Assertion failure at %s (%s:%d), triggered %u time%s:\n"
slouken@3647
   276
                "  '%s'\n"
slouken@3647
   277
                "\n",
slouken@3647
   278
                data->function, data->filename, data->linenum,
slouken@3647
   279
                data->trigger_count, (data->trigger_count == 1) ? "" : "s",
slouken@3647
   280
                data->condition);
slouken@3647
   281
slouken@3655
   282
    /* let env. variable override, so unit tests won't block in a GUI. */
slouken@3647
   283
    envr = SDL_getenv("SDL_ASSERT");
slouken@3647
   284
    if (envr != NULL) {
slouken@3647
   285
        if (SDL_strcmp(envr, "abort") == 0) {
slouken@3647
   286
            return SDL_ASSERTION_ABORT;
slouken@3647
   287
        } else if (SDL_strcmp(envr, "break") == 0) {
slouken@3647
   288
            return SDL_ASSERTION_BREAK;
slouken@3647
   289
        } else if (SDL_strcmp(envr, "retry") == 0) {
slouken@3647
   290
            return SDL_ASSERTION_RETRY;
slouken@3647
   291
        } else if (SDL_strcmp(envr, "ignore") == 0) {
slouken@3647
   292
            return SDL_ASSERTION_IGNORE;
slouken@3647
   293
        } else if (SDL_strcmp(envr, "always_ignore") == 0) {
slouken@3647
   294
            return SDL_ASSERTION_ALWAYS_IGNORE;
slouken@3647
   295
        } else {
slouken@3647
   296
            return SDL_ASSERTION_ABORT;  /* oh well. */
slouken@3647
   297
        }
slouken@3647
   298
    }
slouken@3647
   299
slouken@3657
   300
    /* Leave fullscreen mode, if possible (scary!) */
slouken@3657
   301
    window = SDL_GetFocusWindow();
slouken@3657
   302
    if (window) {
slouken@3657
   303
        if (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) {
slouken@3657
   304
            SDL_MinimizeWindow(window);
slouken@3657
   305
        } else {
icculus@3670
   306
            /* !!! FIXME: ungrab the input if we're not fullscreen? */
slouken@3657
   307
            /* No need to mess with the window */
slouken@3657
   308
            window = 0;
slouken@3657
   309
        }
slouken@3657
   310
    }
slouken@3657
   311
slouken@3647
   312
    /* platform-specific UI... */
slouken@3647
   313
slouken@3647
   314
#ifdef _WINDOWS
slouken@3657
   315
    state = SDL_PromptAssertion_windows(data);
slouken@3647
   316
slouken@3690
   317
#elif __MACOSX__
slouken@3647
   318
    /* This has to be done in an Objective-C (*.m) file, so we call out. */
slouken@3647
   319
    extern SDL_assert_state SDL_PromptAssertion_cocoa(const SDL_assert_data *);
slouken@3657
   320
    state = SDL_PromptAssertion_cocoa(data);
slouken@3647
   321
slouken@3657
   322
#else
slouken@3647
   323
    /* this is a little hacky. */
slouken@3647
   324
    for ( ; ; ) {
slouken@3647
   325
        char buf[32];
slouken@3647
   326
        fprintf(stderr, "Abort/Break/Retry/Ignore/AlwaysIgnore? [abriA] : ");
slouken@3647
   327
        fflush(stderr);
slouken@3647
   328
        if (fgets(buf, sizeof (buf), stdin) == NULL) {
slouken@3657
   329
            break;
slouken@3647
   330
        }
slouken@3647
   331
slouken@3647
   332
        if (SDL_strcmp(buf, "a") == 0) {
slouken@3657
   333
            state = SDL_ASSERTION_ABORT;
slouken@3657
   334
            break;
slouken@3647
   335
        } else if (SDL_strcmp(envr, "b") == 0) {
slouken@3657
   336
            state = SDL_ASSERTION_BREAK;
slouken@3657
   337
            break;
slouken@3647
   338
        } else if (SDL_strcmp(envr, "r") == 0) {
slouken@3657
   339
            state = SDL_ASSERTION_RETRY;
slouken@3657
   340
            break;
slouken@3647
   341
        } else if (SDL_strcmp(envr, "i") == 0) {
slouken@3657
   342
            state = SDL_ASSERTION_IGNORE;
slouken@3657
   343
            break;
slouken@3647
   344
        } else if (SDL_strcmp(envr, "A") == 0) {
slouken@3657
   345
            state = SDL_ASSERTION_ALWAYS_IGNORE;
slouken@3657
   346
            break;
slouken@3647
   347
        }
slouken@3647
   348
    }
slouken@3647
   349
#endif
slouken@3647
   350
slouken@3657
   351
    /* Re-enter fullscreen mode */
slouken@3657
   352
    if (window) {
slouken@3657
   353
        SDL_RestoreWindow(window);
slouken@3657
   354
    }
slouken@3657
   355
slouken@3657
   356
    return state;
slouken@3647
   357
}
slouken@3647
   358
slouken@3647
   359
slouken@3647
   360
SDL_assert_state
slouken@3655
   361
SDL_ReportAssertion(SDL_assert_data *data, const char *func, const char *file,
slouken@3655
   362
                    int line)
slouken@3647
   363
{
icculus@3661
   364
    static int assertion_running = 0;
icculus@3662
   365
    static SDL_SpinLock spinlock = 0;
icculus@3661
   366
    SDL_assert_state state = SDL_ASSERTION_IGNORE;
slouken@3647
   367
icculus@3662
   368
    SDL_AtomicLock(&spinlock);
icculus@3662
   369
    if (assertion_mutex == NULL) { /* never called SDL_Init()? */
icculus@3662
   370
        assertion_mutex = SDL_CreateMutex();
icculus@3662
   371
        if (assertion_mutex == NULL) {
icculus@3662
   372
            SDL_AtomicUnlock(&spinlock);
icculus@3662
   373
            return SDL_ASSERTION_IGNORE;   /* oh well, I guess. */
icculus@3662
   374
        }
icculus@3662
   375
    }
icculus@3662
   376
    SDL_AtomicUnlock(&spinlock);
icculus@3662
   377
slouken@3647
   378
    if (SDL_LockMutex(assertion_mutex) < 0) {
slouken@3647
   379
        return SDL_ASSERTION_IGNORE;   /* oh well, I guess. */
slouken@3647
   380
    }
slouken@3647
   381
slouken@3647
   382
    /* doing this because Visual C is upset over assigning in the macro. */
slouken@3647
   383
    if (data->trigger_count == 0) {
slouken@3647
   384
        data->function = func;
slouken@3655
   385
        data->filename = file;
slouken@3655
   386
        data->linenum = line;
slouken@3647
   387
    }
slouken@3647
   388
slouken@3647
   389
    SDL_AddAssertionToReport(data);
slouken@3647
   390
slouken@3647
   391
    data->trigger_count++;
icculus@3661
   392
icculus@3661
   393
    assertion_running++;
icculus@3661
   394
    if (assertion_running > 1) {   /* assert during assert! Abort. */
icculus@3661
   395
        if (assertion_running == 2) {
icculus@3661
   396
            SDL_AbortAssertion();
icculus@3661
   397
        } else if (assertion_running == 3) {  /* Abort asserted! */
icculus@3661
   398
            SDL_ExitProcess(42);
icculus@3661
   399
        } else {
icculus@3661
   400
            while (1) { /* do nothing but spin; what else can you do?! */ }
icculus@3661
   401
        }
slouken@3647
   402
    }
slouken@3647
   403
icculus@3661
   404
    if (!data->always_ignore) {
icculus@3670
   405
        state = assertion_handler(data, assertion_userdata);
icculus@3661
   406
    }
slouken@3647
   407
slouken@3647
   408
    switch (state)
slouken@3647
   409
    {
slouken@3647
   410
        case SDL_ASSERTION_ABORT:
slouken@3647
   411
            SDL_AbortAssertion();
slouken@3647
   412
            return SDL_ASSERTION_IGNORE;  /* shouldn't return, but oh well. */
slouken@3647
   413
slouken@3647
   414
        case SDL_ASSERTION_ALWAYS_IGNORE:
slouken@3647
   415
            state = SDL_ASSERTION_IGNORE;
slouken@3647
   416
            data->always_ignore = 1;
slouken@3647
   417
            break;
slouken@3647
   418
slouken@3647
   419
        case SDL_ASSERTION_IGNORE:
slouken@3647
   420
        case SDL_ASSERTION_RETRY:
slouken@3647
   421
        case SDL_ASSERTION_BREAK:
slouken@3647
   422
            break;  /* macro handles these. */
slouken@3647
   423
    }
slouken@3647
   424
icculus@3661
   425
    assertion_running--;
slouken@3647
   426
    SDL_UnlockMutex(assertion_mutex);
slouken@3647
   427
slouken@3647
   428
    return state;
slouken@3647
   429
}
slouken@3647
   430
slouken@3647
   431
slouken@3647
   432
int SDL_AssertionsInit(void)
slouken@3647
   433
{
icculus@3664
   434
    /* this is a no-op at the moment. */
slouken@3647
   435
    return 0;
slouken@3647
   436
}
slouken@3647
   437
slouken@3647
   438
void SDL_AssertionsQuit(void)
slouken@3647
   439
{
slouken@3647
   440
    SDL_GenerateAssertionReport();
icculus@3664
   441
    if (assertion_mutex != NULL) {
icculus@3664
   442
        SDL_DestroyMutex(assertion_mutex);
icculus@3664
   443
        assertion_mutex = NULL;
icculus@3664
   444
    }
icculus@3670
   445
}
icculus@3670
   446
icculus@3670
   447
void SDL_SetAssertionHandler(SDL_AssertionHandler handler, void *userdata)
icculus@3670
   448
{
icculus@3670
   449
    if (handler != NULL) {
icculus@3670
   450
        assertion_handler = handler;
icculus@3670
   451
        assertion_userdata = userdata;
icculus@3670
   452
    } else {
icculus@3670
   453
        assertion_handler = SDL_PromptAssertion;
icculus@3670
   454
        assertion_userdata = NULL;
icculus@3670
   455
    }
icculus@3670
   456
}
icculus@3670
   457
icculus@3670
   458
const SDL_assert_data *SDL_GetAssertionReport(void)
icculus@3670
   459
{
icculus@3670
   460
    return triggered_assertions;
icculus@3670
   461
}
icculus@3670
   462
icculus@3670
   463
void SDL_ResetAssertionReport(void)
icculus@3670
   464
{
icculus@3670
   465
    SDL_assert_data *item = triggered_assertions;
icculus@3670
   466
    SDL_assert_data *next = NULL;
icculus@3670
   467
    for (item = triggered_assertions; item->condition; item = next) {
icculus@3670
   468
        next = (SDL_assert_data *) item->next;
icculus@3670
   469
        item->always_ignore = SDL_FALSE;
icculus@3670
   470
        item->trigger_count = 0;
icculus@3670
   471
        item->next = NULL;
icculus@3670
   472
    }
icculus@3670
   473
icculus@3670
   474
    triggered_assertions = &assertion_list_terminator;
slouken@3647
   475
}
slouken@3647
   476
slouken@3647
   477
/* vi: set ts=4 sw=4 expandtab: */