SDL standard library

Dependents:   H261_encoder

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SDL_assert.h Source File

SDL_assert.h

00001 /*
00002   Simple DirectMedia Layer
00003   Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
00004 
00005   This software is provided 'as-is', without any express or implied
00006   warranty.  In no event will the authors be held liable for any damages
00007   arising from the use of this software.
00008 
00009   Permission is granted to anyone to use this software for any purpose,
00010   including commercial applications, and to alter it and redistribute it
00011   freely, subject to the following restrictions:
00012 
00013   1. The origin of this software must not be misrepresented; you must not
00014      claim that you wrote the original software. If you use this software
00015      in a product, an acknowledgment in the product documentation would be
00016      appreciated but is not required.
00017   2. Altered source versions must be plainly marked as such, and must not be
00018      misrepresented as being the original software.
00019   3. This notice may not be removed or altered from any source distribution.
00020 */
00021 
00022 #ifndef _SDL_assert_h
00023 #define _SDL_assert_h
00024 
00025 #include "SDL_config.h"
00026 
00027 #include "begin_code.h"
00028 /* Set up for C function definitions, even when using C++ */
00029 #ifdef __cplusplus
00030 extern "C" {
00031 #endif
00032 
00033 #ifndef SDL_ASSERT_LEVEL
00034 #ifdef SDL_DEFAULT_ASSERT_LEVEL
00035 #define SDL_ASSERT_LEVEL SDL_DEFAULT_ASSERT_LEVEL
00036 #elif defined(_DEBUG) || defined(DEBUG) || \
00037       (defined(__GNUC__) && !defined(__OPTIMIZE__))
00038 #define SDL_ASSERT_LEVEL 2
00039 #else
00040 #define SDL_ASSERT_LEVEL 1
00041 #endif
00042 #endif /* SDL_ASSERT_LEVEL */
00043 
00044 /*
00045 These are macros and not first class functions so that the debugger breaks
00046 on the assertion line and not in some random guts of SDL, and so each
00047 assert can have unique static variables associated with it.
00048 */
00049 
00050 #if defined(_MSC_VER)
00051 /* Don't include intrin.h here because it contains C++ code */
00052     extern void __cdecl __debugbreak(void);
00053     #define SDL_TriggerBreakpoint() __debugbreak()
00054 #elif (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)))
00055     #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "int $3\n\t" )
00056 #elif defined(HAVE_SIGNAL_H)
00057     #include <signal.h>
00058     #define SDL_TriggerBreakpoint() raise(SIGTRAP)
00059 #else
00060     /* How do we trigger breakpoints on this platform? */
00061     #define SDL_TriggerBreakpoint()
00062 #endif
00063 
00064 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 supports __func__ as a standard. */
00065 #   define SDL_FUNCTION __func__
00066 #elif ((__GNUC__ >= 2) || defined(_MSC_VER))
00067 #   define SDL_FUNCTION __FUNCTION__
00068 #else
00069 #   define SDL_FUNCTION "???"
00070 #endif
00071 #define SDL_FILE    __FILE__
00072 #define SDL_LINE    __LINE__
00073 
00074 /*
00075 sizeof (x) makes the compiler still parse the expression even without
00076 assertions enabled, so the code is always checked at compile time, but
00077 doesn't actually generate code for it, so there are no side effects or
00078 expensive checks at run time, just the constant size of what x WOULD be,
00079 which presumably gets optimized out as unused.
00080 This also solves the problem of...
00081 
00082     int somevalue = blah();
00083     SDL_assert(somevalue == 1);
00084 
00085 ...which would cause compiles to complain that somevalue is unused if we
00086 disable assertions.
00087 */
00088 
00089 #ifdef _MSC_VER  /* stupid /W4 warnings. */
00090 #define SDL_NULL_WHILE_LOOP_CONDITION (-1 == __LINE__)
00091 #else
00092 #define SDL_NULL_WHILE_LOOP_CONDITION (0)
00093 #endif
00094 
00095 #define SDL_disabled_assert(condition) \
00096     do { (void) sizeof ((condition)); } while (SDL_NULL_WHILE_LOOP_CONDITION)
00097 
00098 typedef enum
00099 {
00100     SDL_ASSERTION_RETRY,  /**< Retry the assert immediately. */
00101     SDL_ASSERTION_BREAK,  /**< Make the debugger trigger a breakpoint. */
00102     SDL_ASSERTION_ABORT,  /**< Terminate the program. */
00103     SDL_ASSERTION_IGNORE,  /**< Ignore the assert. */
00104     SDL_ASSERTION_ALWAYS_IGNORE  /**< Ignore the assert from now on. */
00105 } SDL_assert_state;
00106 
00107 typedef struct SDL_assert_data
00108 {
00109     int always_ignore;
00110     unsigned int trigger_count;
00111     const char *condition;
00112     const char *filename;
00113     int linenum;
00114     const char *function;
00115     const struct SDL_assert_data *next;
00116 } SDL_assert_data;
00117 
00118 #if (SDL_ASSERT_LEVEL > 0)
00119 
00120 /* Never call this directly. Use the SDL_assert* macros. */
00121 extern DECLSPEC SDL_assert_state SDLCALL SDL_ReportAssertion(SDL_assert_data *,
00122                                                              const char *,
00123                                                              const char *, int)
00124 #if defined(__clang__)
00125 #if __has_feature(attribute_analyzer_noreturn)
00126 /* this tells Clang's static analysis that we're a custom assert function,
00127    and that the analyzer should assume the condition was always true past this
00128    SDL_assert test. */
00129    __attribute__((analyzer_noreturn))
00130 #endif
00131 #endif
00132 ;
00133 
00134 /* the do {} while(0) avoids dangling else problems:
00135     if (x) SDL_assert(y); else blah();
00136        ... without the do/while, the "else" could attach to this macro's "if".
00137    We try to handle just the minimum we need here in a macro...the loop,
00138    the static vars, and break points. The heavy lifting is handled in
00139    SDL_ReportAssertion(), in SDL_assert.c.
00140 */
00141 #define SDL_enabled_assert(condition) \
00142     do { \
00143         while ( !(condition) ) { \
00144             static struct SDL_assert_data assert_data = { \
00145                 0, 0, #condition, 0, 0, 0, 0 \
00146             }; \
00147             const SDL_assert_state state = SDL_ReportAssertion(&assert_data, \
00148                                                                SDL_FUNCTION, \
00149                                                                SDL_FILE, \
00150                                                                SDL_LINE); \
00151             if (state == SDL_ASSERTION_RETRY) { \
00152                 continue; /* go again. */ \
00153             } else if (state == SDL_ASSERTION_BREAK) { \
00154                 SDL_TriggerBreakpoint(); \
00155             } \
00156             break; /* not retrying. */ \
00157         } \
00158     } while (SDL_NULL_WHILE_LOOP_CONDITION)
00159 
00160 #endif  /* enabled assertions support code */
00161 
00162 /* Enable various levels of assertions. */
00163 #if SDL_ASSERT_LEVEL == 0   /* assertions disabled */
00164 #   define SDL_assert(condition) SDL_disabled_assert(condition)
00165 #   define SDL_assert_release(condition) SDL_disabled_assert(condition)
00166 #   define SDL_assert_paranoid(condition) SDL_disabled_assert(condition)
00167 #elif SDL_ASSERT_LEVEL == 1  /* release settings. */
00168 #   define SDL_assert(condition) SDL_disabled_assert(condition)
00169 #   define SDL_assert_release(condition) SDL_enabled_assert(condition)
00170 #   define SDL_assert_paranoid(condition) SDL_disabled_assert(condition)
00171 #elif SDL_ASSERT_LEVEL == 2  /* normal settings. */
00172 #   define SDL_assert(condition) SDL_enabled_assert(condition)
00173 #   define SDL_assert_release(condition) SDL_enabled_assert(condition)
00174 #   define SDL_assert_paranoid(condition) SDL_disabled_assert(condition)
00175 #elif SDL_ASSERT_LEVEL == 3  /* paranoid settings. */
00176 #   define SDL_assert(condition) SDL_enabled_assert(condition)
00177 #   define SDL_assert_release(condition) SDL_enabled_assert(condition)
00178 #   define SDL_assert_paranoid(condition) SDL_enabled_assert(condition)
00179 #else
00180 #   error Unknown assertion level.
00181 #endif
00182 
00183 /* this assertion is never disabled at any level. */
00184 #define SDL_assert_always(condition) SDL_enabled_assert(condition)
00185 
00186 
00187 typedef SDL_assert_state (SDLCALL *SDL_AssertionHandler)(
00188                                  const SDL_assert_data* data, void* userdata);
00189 
00190 /**
00191  *  \brief Set an application-defined assertion handler.
00192  *
00193  *  This allows an app to show its own assertion UI and/or force the
00194  *  response to an assertion failure. If the app doesn't provide this, SDL
00195  *  will try to do the right thing, popping up a system-specific GUI dialog,
00196  *  and probably minimizing any fullscreen windows.
00197  *
00198  *  This callback may fire from any thread, but it runs wrapped in a mutex, so
00199  *  it will only fire from one thread at a time.
00200  *
00201  *  Setting the callback to NULL restores SDL's original internal handler.
00202  *
00203  *  This callback is NOT reset to SDL's internal handler upon SDL_Quit()!
00204  *
00205  *  \return SDL_assert_state value of how to handle the assertion failure.
00206  *
00207  *  \param handler Callback function, called when an assertion fails.
00208  *  \param userdata A pointer passed to the callback as-is.
00209  */
00210 extern DECLSPEC void SDLCALL SDL_SetAssertionHandler(
00211                                             SDL_AssertionHandler handler,
00212                                             void *userdata);
00213 
00214 /**
00215  *  \brief Get the default assertion handler.
00216  *
00217  *  This returns the function pointer that is called by default when an
00218  *   assertion is triggered. This is an internal function provided by SDL,
00219  *   that is used for assertions when SDL_SetAssertionHandler() hasn't been
00220  *   used to provide a different function.
00221  *
00222  *  \return The default SDL_AssertionHandler that is called when an assert triggers.
00223  */
00224 extern DECLSPEC SDL_AssertionHandler SDLCALL SDL_GetDefaultAssertionHandler(void);
00225 
00226 /**
00227  *  \brief Get the current assertion handler.
00228  *
00229  *  This returns the function pointer that is called when an assertion is
00230  *   triggered. This is either the value last passed to
00231  *   SDL_SetAssertionHandler(), or if no application-specified function is
00232  *   set, is equivalent to calling SDL_GetDefaultAssertionHandler().
00233  *
00234  *   \param puserdata Pointer to a void*, which will store the "userdata"
00235  *                    pointer that was passed to SDL_SetAssertionHandler().
00236  *                    This value will always be NULL for the default handler.
00237  *                    If you don't care about this data, it is safe to pass
00238  *                    a NULL pointer to this function to ignore it.
00239  *  \return The SDL_AssertionHandler that is called when an assert triggers.
00240  */
00241 extern DECLSPEC SDL_AssertionHandler SDLCALL SDL_GetAssertionHandler(void **puserdata);
00242 
00243 /**
00244  *  \brief Get a list of all assertion failures.
00245  *
00246  *  Get all assertions triggered since last call to SDL_ResetAssertionReport(),
00247  *  or the start of the program.
00248  *
00249  *  The proper way to examine this data looks something like this:
00250  *
00251  *  <code>
00252  *  const SDL_assert_data *item = SDL_GetAssertionReport();
00253  *  while (item) {
00254  *      printf("'%s', %s (%s:%d), triggered %u times, always ignore: %s.\n",
00255  *             item->condition, item->function, item->filename,
00256  *             item->linenum, item->trigger_count,
00257  *             item->always_ignore ? "yes" : "no");
00258  *      item = item->next;
00259  *  }
00260  *  </code>
00261  *
00262  *  \return List of all assertions.
00263  *  \sa SDL_ResetAssertionReport
00264  */
00265 extern DECLSPEC const SDL_assert_data * SDLCALL SDL_GetAssertionReport(void);
00266 
00267 /**
00268  *  \brief Reset the list of all assertion failures.
00269  *
00270  *  Reset list of all assertions triggered.
00271  *
00272  *  \sa SDL_GetAssertionReport
00273  */
00274 extern DECLSPEC void SDLCALL SDL_ResetAssertionReport(void);
00275 
00276 /* Ends C function definitions when using C++ */
00277 #ifdef __cplusplus
00278 }
00279 #endif
00280 #include "close_code.h"
00281 
00282 #endif /* _SDL_assert_h */
00283 
00284 /* vi: set ts=4 sw=4 expandtab: */