include/SDL_assert.h
author Ryan C. Gordon <icculus@icculus.org>
Sat, 15 Sep 2012 10:59:39 -0400
changeset 6430 48d519500f7e
parent 6138 4c64952a58fb
child 6761 dacf27c78462
permissions -rw-r--r--
Removed Windows CE support from SDL 2.0.

It's a long-dead platform, and we don't have any way to build for, test, or
maintain it, so there's no sense in doing acrobatics to support it.

If you need Windows CE support, use SDL 1.2. If you need Windows Phone support,
send SDL 2.0 patches for the newer Windows Mobile platform.
slouken@3647
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@6138
     3
  Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
slouken@3647
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@3647
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@3647
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@3647
    20
*/
slouken@3647
    21
slouken@3647
    22
#ifndef _SDL_assert_h
slouken@3647
    23
#define _SDL_assert_h
slouken@3647
    24
slouken@3655
    25
#include "SDL_config.h"
slouken@3655
    26
slouken@3655
    27
#include "begin_code.h"
slouken@3655
    28
/* Set up for C function definitions, even when using C++ */
slouken@3655
    29
#ifdef __cplusplus
slouken@3655
    30
/* *INDENT-OFF* */
slouken@3655
    31
extern "C" {
slouken@3655
    32
/* *INDENT-ON* */
slouken@3655
    33
#endif
slouken@3655
    34
slouken@3647
    35
#ifndef SDL_ASSERT_LEVEL
slouken@3654
    36
#ifdef SDL_DEFAULT_ASSERT_LEVEL
slouken@3654
    37
#define SDL_ASSERT_LEVEL SDL_DEFAULT_ASSERT_LEVEL
slouken@3654
    38
#elif defined(_DEBUG) || defined(DEBUG) || \
slouken@3654
    39
      (defined(__GNUC__) && !defined(__OPTIMIZE__))
slouken@3653
    40
#define SDL_ASSERT_LEVEL 2
slouken@3653
    41
#else
slouken@3653
    42
#define SDL_ASSERT_LEVEL 1
slouken@3647
    43
#endif
slouken@3653
    44
#endif /* SDL_ASSERT_LEVEL */
slouken@3647
    45
slouken@3647
    46
/*
slouken@3655
    47
These are macros and not first class functions so that the debugger breaks
slouken@3655
    48
on the assertion line and not in some random guts of SDL, and so each
icculus@3665
    49
assert can have unique static variables associated with it.
slouken@3655
    50
*/
slouken@3655
    51
icculus@6430
    52
#if defined(_MSC_VER)
slouken@5491
    53
/* Don't include intrin.h here because it contains C++ code */
icculus@6430
    54
    extern void __cdecl __debugbreak(void);
slouken@5011
    55
    #define SDL_TriggerBreakpoint() __debugbreak()
icculus@5552
    56
#elif (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)))
slouken@3655
    57
    #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "int $3\n\t" )
slouken@3655
    58
#elif defined(HAVE_SIGNAL_H)
slouken@3655
    59
    #include <signal.h>
slouken@3655
    60
    #define SDL_TriggerBreakpoint() raise(SIGTRAP)
slouken@3655
    61
#else
slouken@3655
    62
    /* How do we trigger breakpoints on this platform? */
slouken@3655
    63
    #define SDL_TriggerBreakpoint()
slouken@3655
    64
#endif
slouken@3655
    65
icculus@5552
    66
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 supports __func__ as a standard. */
slouken@3655
    67
#   define SDL_FUNCTION __func__
slouken@3655
    68
#elif ((__GNUC__ >= 2) || defined(_MSC_VER))
slouken@3655
    69
#   define SDL_FUNCTION __FUNCTION__
slouken@3655
    70
#else
slouken@3655
    71
#   define SDL_FUNCTION "???"
slouken@3655
    72
#endif
slouken@3655
    73
#define SDL_FILE    __FILE__
slouken@3655
    74
#define SDL_LINE    __LINE__
slouken@3655
    75
slouken@3655
    76
/*
slouken@3647
    77
sizeof (x) makes the compiler still parse the expression even without
slouken@3647
    78
assertions enabled, so the code is always checked at compile time, but
slouken@3647
    79
doesn't actually generate code for it, so there are no side effects or
slouken@3647
    80
expensive checks at run time, just the constant size of what x WOULD be,
slouken@3647
    81
which presumably gets optimized out as unused.
slouken@3647
    82
This also solves the problem of...
slouken@3647
    83
slouken@3647
    84
    int somevalue = blah();
slouken@3647
    85
    SDL_assert(somevalue == 1);
slouken@3647
    86
slouken@3647
    87
...which would cause compiles to complain that somevalue is unused if we
slouken@3647
    88
disable assertions.
slouken@3647
    89
*/
slouken@3647
    90
slouken@3647
    91
#define SDL_disabled_assert(condition) \
slouken@3647
    92
    do { (void) sizeof ((condition)); } while (0)
slouken@3647
    93
slouken@3647
    94
#if (SDL_ASSERT_LEVEL > 0)
slouken@3647
    95
slouken@3647
    96
typedef enum
slouken@3647
    97
{
slouken@3647
    98
    SDL_ASSERTION_RETRY,  /**< Retry the assert immediately. */
slouken@3647
    99
    SDL_ASSERTION_BREAK,  /**< Make the debugger trigger a breakpoint. */
slouken@3647
   100
    SDL_ASSERTION_ABORT,  /**< Terminate the program. */
slouken@3647
   101
    SDL_ASSERTION_IGNORE,  /**< Ignore the assert. */
icculus@5625
   102
    SDL_ASSERTION_ALWAYS_IGNORE  /**< Ignore the assert from now on. */
slouken@3647
   103
} SDL_assert_state;
slouken@3647
   104
slouken@3647
   105
typedef struct SDL_assert_data
slouken@3647
   106
{
slouken@3647
   107
    int always_ignore;
slouken@3647
   108
    unsigned int trigger_count;
slouken@3647
   109
    const char *condition;
slouken@3647
   110
    const char *filename;
slouken@3647
   111
    int linenum;
slouken@3647
   112
    const char *function;
icculus@3670
   113
    const struct SDL_assert_data *next;
slouken@3647
   114
} SDL_assert_data;
slouken@3647
   115
icculus@3668
   116
/* Never call this directly. Use the SDL_assert* macros. */
slouken@3655
   117
extern DECLSPEC SDL_assert_state SDLCALL SDL_ReportAssertion(SDL_assert_data *,
slouken@3655
   118
                                                             const char *,
slouken@3655
   119
                                                             const char *, int);
slouken@3647
   120
slouken@3647
   121
/* the do {} while(0) avoids dangling else problems:
slouken@3647
   122
    if (x) SDL_assert(y); else blah();
slouken@3647
   123
       ... without the do/while, the "else" could attach to this macro's "if".
slouken@3647
   124
   We try to handle just the minimum we need here in a macro...the loop,
slouken@3647
   125
   the static vars, and break points. The heavy lifting is handled in
slouken@3647
   126
   SDL_ReportAssertion(), in SDL_assert.c.
slouken@3647
   127
*/
slouken@3647
   128
#define SDL_enabled_assert(condition) \
slouken@3647
   129
    do { \
slouken@3647
   130
        while ( !(condition) ) { \
slouken@3649
   131
            static struct SDL_assert_data assert_data = { \
slouken@3655
   132
                0, 0, #condition, 0, 0, 0, 0 \
slouken@3647
   133
            }; \
slouken@3649
   134
            const SDL_assert_state state = SDL_ReportAssertion(&assert_data, \
slouken@3647
   135
                                                               SDL_FUNCTION, \
slouken@3655
   136
                                                               SDL_FILE, \
slouken@3655
   137
                                                               SDL_LINE); \
slouken@3647
   138
            if (state == SDL_ASSERTION_RETRY) { \
slouken@3647
   139
                continue; /* go again. */ \
slouken@3647
   140
            } else if (state == SDL_ASSERTION_BREAK) { \
slouken@3647
   141
                SDL_TriggerBreakpoint(); \
slouken@3647
   142
            } \
slouken@3647
   143
            break; /* not retrying. */ \
slouken@3647
   144
        } \
slouken@3647
   145
    } while (0)
slouken@3647
   146
slouken@3647
   147
#endif  /* enabled assertions support code */
slouken@3647
   148
slouken@3647
   149
/* Enable various levels of assertions. */
slouken@3647
   150
#if SDL_ASSERT_LEVEL == 0   /* assertions disabled */
slouken@3647
   151
#   define SDL_assert(condition) SDL_disabled_assert(condition)
slouken@3647
   152
#   define SDL_assert_release(condition) SDL_disabled_assert(condition)
slouken@3647
   153
#   define SDL_assert_paranoid(condition) SDL_disabled_assert(condition)
slouken@3647
   154
#elif SDL_ASSERT_LEVEL == 1  /* release settings. */
slouken@3652
   155
#   define SDL_assert(condition) SDL_disabled_assert(condition)
slouken@3647
   156
#   define SDL_assert_release(condition) SDL_enabled_assert(condition)
slouken@3652
   157
#   define SDL_assert_paranoid(condition) SDL_disabled_assert(condition)
slouken@3647
   158
#elif SDL_ASSERT_LEVEL == 2  /* normal settings. */
slouken@3647
   159
#   define SDL_assert(condition) SDL_enabled_assert(condition)
slouken@3647
   160
#   define SDL_assert_release(condition) SDL_enabled_assert(condition)
slouken@3647
   161
#   define SDL_assert_paranoid(condition) SDL_disabled_assert(condition)
slouken@3647
   162
#elif SDL_ASSERT_LEVEL == 3  /* paranoid settings. */
slouken@3647
   163
#   define SDL_assert(condition) SDL_enabled_assert(condition)
slouken@3647
   164
#   define SDL_assert_release(condition) SDL_enabled_assert(condition)
slouken@3647
   165
#   define SDL_assert_paranoid(condition) SDL_enabled_assert(condition)
slouken@3647
   166
#else
slouken@3655
   167
#   error Unknown assertion level.
slouken@3647
   168
#endif
slouken@3647
   169
icculus@3670
   170
icculus@3670
   171
typedef SDL_assert_state (SDLCALL *SDL_AssertionHandler)(
slouken@5538
   172
                                 const SDL_assert_data* data, void* userdata);
icculus@3670
   173
icculus@3670
   174
/**
icculus@3670
   175
 *  \brief Set an application-defined assertion handler.
icculus@3670
   176
 *
icculus@3670
   177
 *  This allows an app to show its own assertion UI and/or force the
icculus@3670
   178
 *  response to an assertion failure. If the app doesn't provide this, SDL
icculus@3670
   179
 *  will try to do the right thing, popping up a system-specific GUI dialog,
icculus@3670
   180
 *  and probably minimizing any fullscreen windows.
icculus@3670
   181
 *
icculus@3670
   182
 *  This callback may fire from any thread, but it runs wrapped in a mutex, so
icculus@3670
   183
 *  it will only fire from one thread at a time.
icculus@3670
   184
 *
icculus@3670
   185
 *  Setting the callback to NULL restores SDL's original internal handler.
icculus@3670
   186
 *
icculus@3670
   187
 *  This callback is NOT reset to SDL's internal handler upon SDL_Quit()!
icculus@3670
   188
 *
icculus@3670
   189
 *  \return SDL_assert_state value of how to handle the assertion failure.
icculus@3670
   190
 *  
icculus@3670
   191
 *  \param handler Callback function, called when an assertion fails.
icculus@3670
   192
 *  \param userdata A pointer passed to the callback as-is.
icculus@3670
   193
 */
icculus@3670
   194
extern DECLSPEC void SDLCALL SDL_SetAssertionHandler(
icculus@3670
   195
                                            SDL_AssertionHandler handler,
icculus@3670
   196
                                            void *userdata);
icculus@3670
   197
icculus@3670
   198
/**
icculus@3670
   199
 *  \brief Get a list of all assertion failures.
icculus@3670
   200
 *
icculus@3670
   201
 *  Get all assertions triggered since last call to SDL_ResetAssertionReport(),
icculus@3670
   202
 *  or the start of the program.
icculus@3670
   203
 *
icculus@3670
   204
 *  The proper way to examine this data looks something like this:
icculus@3670
   205
 *
icculus@3670
   206
 *  <code>
icculus@3670
   207
 *  const SDL_assert_data *item = SDL_GetAssertionReport();
icculus@5541
   208
 *  while (item) {
icculus@3670
   209
 *      printf("'%s', %s (%s:%d), triggered %u times, always ignore: %s.\n",
icculus@3670
   210
 *             item->condition, item->function, item->filename,
icculus@3670
   211
 *             item->linenum, item->trigger_count,
icculus@3670
   212
 *             item->always_ignore ? "yes" : "no");
icculus@3670
   213
 *      item = item->next;
icculus@3670
   214
 *  }
icculus@3670
   215
 *  </code>
icculus@3670
   216
 *
icculus@5541
   217
 *  \return List of all assertions.
icculus@3670
   218
 *  \sa SDL_ResetAssertionReport
icculus@3670
   219
 */
icculus@3670
   220
extern DECLSPEC const SDL_assert_data * SDLCALL SDL_GetAssertionReport(void);
icculus@3670
   221
icculus@3670
   222
/**
icculus@3670
   223
 *  \brief Reset the list of all assertion failures.
icculus@3670
   224
 *
icculus@3670
   225
 *  Reset list of all assertions triggered.
icculus@3670
   226
 *
icculus@3670
   227
 *  \sa SDL_GetAssertionReport
icculus@3670
   228
 */
icculus@3670
   229
extern DECLSPEC void SDLCALL SDL_ResetAssertionReport(void);
icculus@3670
   230
slouken@3655
   231
/* Ends C function definitions when using C++ */
slouken@3655
   232
#ifdef __cplusplus
slouken@3655
   233
/* *INDENT-OFF* */
slouken@3655
   234
}
slouken@3655
   235
/* *INDENT-ON* */
slouken@3655
   236
#endif
slouken@3655
   237
#include "close_code.h"
slouken@3655
   238
slouken@3647
   239
#endif /* _SDL_assert_h */
slouken@3647
   240
slouken@3647
   241
/* vi: set ts=4 sw=4 expandtab: */