From a1333360c584e89bc791798b3db60765dafbda09 Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Tue, 12 Sep 2017 18:00:07 +0200 Subject: [PATCH] rwlib: Add option to abort/break on failed checks or at request - RW_ABORT/RW_ASSERT/RW_BREAKPOINT are only defined in debug mode - the callback is needed to unlock the mouse when entering the debugger --- CMakeLists.txt | 12 ++++++++++ rwgame/GameBase.cpp | 3 +++ rwlib/CMakeLists.txt | 1 + rwlib/source/rw/abort.cpp | 5 ++++ rwlib/source/rw/defines.hpp | 46 +++++++++++++++++++++++++++++++++++-- 5 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 rwlib/source/rw/abort.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 21eb951d..6c6d85af 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,6 +22,8 @@ option(ENABLE_SCRIPT_DEBUG "Enable verbose script execution") option(ENABLE_PROFILING "Enable detailed profiling metrics") option(TESTS_NODATA "Build tests for no-data testing") +set(FAILED_CHECK_ACTION "IGNORE" CACHE STRING "What action to perform on a failed RW_CHECK (IGNORE, ABORT or BREAKPOINT) (only in debug mode)") + # # Build configuration # @@ -66,6 +68,16 @@ IF(${ENABLE_SCRIPT_DEBUG}) add_definitions(-DRW_SCRIPT_DEBUG) ENDIF() +if(FAILED_CHECK_ACTION STREQUAL "IGNORE") + add_definitions(-DRW_FAILED_CHECK_ACTION=0) +elseif(FAILED_CHECK_ACTION STREQUAL "ABORT") + add_definitions(-DRW_FAILED_CHECK_ACTION=1) +elseif(FAILED_CHECK_ACTION STREQUAL "BREAKPOINT") + add_definitions(-DRW_FAILED_CHECK_ACTION=2) +else() + message(FATAL_ERROR "Illegal FAILED_CHECK_ACTION option.") +endif() + if(${RW_VERBOSE_DEBUG_MESSAGES}) add_definitions(-DRW_VERBOSE_DEBUG_MESSAGES=1) else() diff --git a/rwgame/GameBase.cpp b/rwgame/GameBase.cpp index 9eb4e7b3..f3287fce 100644 --- a/rwgame/GameBase.cpp +++ b/rwgame/GameBase.cpp @@ -64,6 +64,9 @@ GameBase::GameBase(Logger &inlog, int argc, char *argv[]) : log(inlog) { throw std::runtime_error("Failed to initialize SDL2!"); window.create(kWindowTitle + " [" + kBuildStr + "]", w, h, fullscreen); + + SET_RW_ABORT_CB([this]() {window.showCursor();}, + [this]() {window.hideCursor();}); } GameBase::~GameBase() { diff --git a/rwlib/CMakeLists.txt b/rwlib/CMakeLists.txt index d978b715..439ae5f7 100644 --- a/rwlib/CMakeLists.txt +++ b/rwlib/CMakeLists.txt @@ -16,6 +16,7 @@ SET(RWLIB_SOURCES "source/gl/TextureData.hpp" "source/gl/TextureData.cpp" + "source/rw/abort.cpp" "source/rw/types.hpp" "source/rw/defines.hpp" diff --git a/rwlib/source/rw/abort.cpp b/rwlib/source/rw/abort.cpp new file mode 100644 index 00000000..12e7cf69 --- /dev/null +++ b/rwlib/source/rw/abort.cpp @@ -0,0 +1,5 @@ +#include "rw/defines.hpp" + +#if RW_DEBUG +std::function _rw_abort_cb[2] = {nullptr, nullptr}; +#endif diff --git a/rwlib/source/rw/defines.hpp b/rwlib/source/rw/defines.hpp index e407656f..7251e162 100644 --- a/rwlib/source/rw/defines.hpp +++ b/rwlib/source/rw/defines.hpp @@ -1,17 +1,59 @@ #ifndef _LIBRW_DEFINES_HPP_ #define _LIBRW_DEFINES_HPP_ +#if RW_DEBUG +#include +#include + +extern std::function _rw_abort_cb[2]; +#define SET_RW_ABORT_CB(cb0, cb1) do { _rw_abort_cb[0] = cb0; _rw_abort_cb[1] = cb1;} while (0) + +#define RW_ABORT() do { if(_rw_abort_cb[0]) _rw_abort_cb[0](); ::abort(); } while (0) +#define RW_ASSERT(cond) do { if (!(cond)) RW_ABORT();} while (0) + +#if defined(RW_WINDOWS) +#include +#define RW_BREAKPOINT() DebugBreak() +#else +#include +#define RW_BREAKPOINT() do { if(_rw_abort_cb[0]) _rw_abort_cb[0](); ::raise(SIGTRAP); if(_rw_abort_cb[1]) _rw_abort_cb[1](); } while (0) +#endif + +#define RW_FAILED_NO_ACTION 0 +#define RW_FAILED_ABORT_OPTION 1 +#define RW_FAILED_BREAKPOINT_OPTION 2 + +#if RW_FAILED_CHECK_ACTION == RW_FAILED_NO_ACTION +#define _RW_FAILED_CHECK_ACTION() +#elif RW_FAILED_CHECK_ACTION == RW_FAILED_ABORT_OPTION +#define _RW_FAILED_CHECK_ACTION() RW_ABORT() +#elif RW_FAILED_CHECK_ACTION == RW_FAILED_BREAKPOINT_OPTION +#define _RW_FAILED_CHECK_ACTION() RW_BREAKPOINT() +#endif + +#else +#define SET_RW_ABORT_CB(cb0, cb1) +#define RW_ABORT() +#define RW_ASSERT(cond) +#define RW_BREAKPOINT() +#define _RW_FAILED_CHECK_ACTION() +#endif + #if RW_DEBUG && RW_VERBOSE_DEBUG_MESSAGES #include #define RW_MESSAGE(msg) \ std::cout << __FILE__ << ":" << __LINE__ << ": " << msg << std::endl #define RW_ERROR(msg) \ std::cerr << __FILE__ << ":" << __LINE__ << ": " << msg << std::endl -#define RW_CHECK(cond, msg) \ - if (!(cond)) RW_ERROR(msg) #else #define RW_MESSAGE(msg) #define RW_ERROR(msg) +#endif + +#if RW_DEBUG +#define RW_CHECK(cond, msg) \ + do { if (!(cond)) { RW_ERROR(msg); _RW_FAILED_CHECK_ACTION();}} while (0) +#else #define RW_CHECK(cond, msg) #endif