Path: blob/main/system/include/SDL/SDL_assert.h
6169 views
/*1Simple DirectMedia Layer2Copyright (C) 1997-2011 Sam Lantinga <[email protected]>34This software is provided 'as-is', without any express or implied5warranty. In no event will the authors be held liable for any damages6arising from the use of this software.78Permission is granted to anyone to use this software for any purpose,9including commercial applications, and to alter it and redistribute it10freely, subject to the following restrictions:11121. The origin of this software must not be misrepresented; you must not13claim that you wrote the original software. If you use this software14in a product, an acknowledgment in the product documentation would be15appreciated but is not required.162. Altered source versions must be plainly marked as such, and must not be17misrepresented as being the original software.183. This notice may not be removed or altered from any source distribution.19*/2021#ifndef _SDL_assert_h22#define _SDL_assert_h2324#include "SDL_config.h"2526#include "begin_code.h"27/* Set up for C function definitions, even when using C++ */28#ifdef __cplusplus29/* *INDENT-OFF* */30extern "C" {31/* *INDENT-ON* */32#endif3334#ifndef SDL_ASSERT_LEVEL35#ifdef SDL_DEFAULT_ASSERT_LEVEL36#define SDL_ASSERT_LEVEL SDL_DEFAULT_ASSERT_LEVEL37#elif defined(_DEBUG) || defined(DEBUG) || \38(defined(__GNUC__) && !defined(__OPTIMIZE__))39#define SDL_ASSERT_LEVEL 240#else41#define SDL_ASSERT_LEVEL 142#endif43#endif /* SDL_ASSERT_LEVEL */4445/*46These are macros and not first class functions so that the debugger breaks47on the assertion line and not in some random guts of SDL, and so each48assert can have unique static variables associated with it.49*/5051#if defined(_MSC_VER) && !defined(_WIN32_WCE)52/* Don't include intrin.h here because it contains C++ code */53extern void __cdecl __debugbreak(void);54#define SDL_TriggerBreakpoint() __debugbreak()55#elif (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)))56#define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "int $3\n\t" )57#elif defined(HAVE_SIGNAL_H)58#include <signal.h>59#define SDL_TriggerBreakpoint() raise(SIGTRAP)60#else61/* How do we trigger breakpoints on this platform? */62#define SDL_TriggerBreakpoint()63#endif6465#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 supports __func__ as a standard. */66# define SDL_FUNCTION __func__67#elif ((__GNUC__ >= 2) || defined(_MSC_VER))68# define SDL_FUNCTION __FUNCTION__69#else70# define SDL_FUNCTION "???"71#endif72#define SDL_FILE __FILE__73#define SDL_LINE __LINE__7475/*76sizeof (x) makes the compiler still parse the expression even without77assertions enabled, so the code is always checked at compile time, but78doesn't actually generate code for it, so there are no side effects or79expensive checks at run time, just the constant size of what x WOULD be,80which presumably gets optimized out as unused.81This also solves the problem of...8283int somevalue = blah();84SDL_assert(somevalue == 1);8586...which would cause compiles to complain that somevalue is unused if we87disable assertions.88*/8990#define SDL_disabled_assert(condition) \91do { (void) sizeof ((condition)); } while (0)9293#if (SDL_ASSERT_LEVEL > 0)9495typedef enum96{97SDL_ASSERTION_RETRY, /**< Retry the assert immediately. */98SDL_ASSERTION_BREAK, /**< Make the debugger trigger a breakpoint. */99SDL_ASSERTION_ABORT, /**< Terminate the program. */100SDL_ASSERTION_IGNORE, /**< Ignore the assert. */101SDL_ASSERTION_ALWAYS_IGNORE /**< Ignore the assert from now on. */102} SDL_assert_state;103104typedef struct SDL_assert_data105{106int always_ignore;107unsigned int trigger_count;108const char *condition;109const char *filename;110int linenum;111const char *function;112const struct SDL_assert_data *next;113} SDL_assert_data;114115/* Never call this directly. Use the SDL_assert* macros. */116extern DECLSPEC SDL_assert_state SDLCALL SDL_ReportAssertion(SDL_assert_data *,117const char *,118const char *, int);119120/* the do {} while(0) avoids dangling else problems:121if (x) SDL_assert(y); else blah();122... without the do/while, the "else" could attach to this macro's "if".123We try to handle just the minimum we need here in a macro...the loop,124the static vars, and break points. The heavy lifting is handled in125SDL_ReportAssertion(), in SDL_assert.c.126*/127#define SDL_enabled_assert(condition) \128do { \129while ( !(condition) ) { \130static struct SDL_assert_data assert_data = { \1310, 0, #condition, 0, 0, 0, 0 \132}; \133const SDL_assert_state state = SDL_ReportAssertion(&assert_data, \134SDL_FUNCTION, \135SDL_FILE, \136SDL_LINE); \137if (state == SDL_ASSERTION_RETRY) { \138continue; /* go again. */ \139} else if (state == SDL_ASSERTION_BREAK) { \140SDL_TriggerBreakpoint(); \141} \142break; /* not retrying. */ \143} \144} while (0)145146#endif /* enabled assertions support code */147148/* Enable various levels of assertions. */149#if SDL_ASSERT_LEVEL == 0 /* assertions disabled */150# define SDL_assert(condition) SDL_disabled_assert(condition)151# define SDL_assert_release(condition) SDL_disabled_assert(condition)152# define SDL_assert_paranoid(condition) SDL_disabled_assert(condition)153#elif SDL_ASSERT_LEVEL == 1 /* release settings. */154# define SDL_assert(condition) SDL_disabled_assert(condition)155# define SDL_assert_release(condition) SDL_enabled_assert(condition)156# define SDL_assert_paranoid(condition) SDL_disabled_assert(condition)157#elif SDL_ASSERT_LEVEL == 2 /* normal settings. */158# define SDL_assert(condition) SDL_enabled_assert(condition)159# define SDL_assert_release(condition) SDL_enabled_assert(condition)160# define SDL_assert_paranoid(condition) SDL_disabled_assert(condition)161#elif SDL_ASSERT_LEVEL == 3 /* paranoid settings. */162# define SDL_assert(condition) SDL_enabled_assert(condition)163# define SDL_assert_release(condition) SDL_enabled_assert(condition)164# define SDL_assert_paranoid(condition) SDL_enabled_assert(condition)165#else166# error Unknown assertion level.167#endif168169170typedef SDL_assert_state (SDLCALL *SDL_AssertionHandler)(171const SDL_assert_data* data, void* userdata);172173/**174* \brief Set an application-defined assertion handler.175*176* This allows an app to show its own assertion UI and/or force the177* response to an assertion failure. If the app doesn't provide this, SDL178* will try to do the right thing, popping up a system-specific GUI dialog,179* and probably minimizing any fullscreen windows.180*181* This callback may fire from any thread, but it runs wrapped in a mutex, so182* it will only fire from one thread at a time.183*184* Setting the callback to NULL restores SDL's original internal handler.185*186* This callback is NOT reset to SDL's internal handler upon SDL_Quit()!187*188* \return SDL_assert_state value of how to handle the assertion failure.189*190* \param handler Callback function, called when an assertion fails.191* \param userdata A pointer passed to the callback as-is.192*/193extern DECLSPEC void SDLCALL SDL_SetAssertionHandler(194SDL_AssertionHandler handler,195void *userdata);196197/**198* \brief Get a list of all assertion failures.199*200* Get all assertions triggered since last call to SDL_ResetAssertionReport(),201* or the start of the program.202*203* The proper way to examine this data looks something like this:204*205* <code>206* const SDL_assert_data *item = SDL_GetAssertionReport();207* while (item) {208* printf("'%s', %s (%s:%d), triggered %u times, always ignore: %s.\n",209* item->condition, item->function, item->filename,210* item->linenum, item->trigger_count,211* item->always_ignore ? "yes" : "no");212* item = item->next;213* }214* </code>215*216* \return List of all assertions.217* \sa SDL_ResetAssertionReport218*/219extern DECLSPEC const SDL_assert_data * SDLCALL SDL_GetAssertionReport(void);220221/**222* \brief Reset the list of all assertion failures.223*224* Reset list of all assertions triggered.225*226* \sa SDL_GetAssertionReport227*/228extern DECLSPEC void SDLCALL SDL_ResetAssertionReport(void);229230/* Ends C function definitions when using C++ */231#ifdef __cplusplus232/* *INDENT-OFF* */233}234/* *INDENT-ON* */235#endif236#include "close_code.h"237238#endif /* _SDL_assert_h */239240/* vi: set ts=4 sw=4 expandtab: */241242243