diff options
author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-03-25 10:43:25 +0100 |
---|---|---|
committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-03-25 10:43:25 +0100 |
commit | 0c060e6e4b9f99dc887b5dfebdae76fcde9524f1 (patch) | |
tree | 2ba9a1923e3e983375e33aa5f41d9fbc21451832 /src/macros_and_utils.h | |
parent | dad1d5fbf7c7a30caea00694de608c6036789aa5 (diff) | |
download | lanes-0c060e6e4b9f99dc887b5dfebdae76fcde9524f1.tar.gz lanes-0c060e6e4b9f99dc887b5dfebdae76fcde9524f1.tar.bz2 lanes-0c060e6e4b9f99dc887b5dfebdae76fcde9524f1.zip |
C++ migration: revamped stack checking macros
Diffstat (limited to 'src/macros_and_utils.h')
-rw-r--r-- | src/macros_and_utils.h | 116 |
1 files changed, 77 insertions, 39 deletions
diff --git a/src/macros_and_utils.h b/src/macros_and_utils.h index 9982693..c549d72 100644 --- a/src/macros_and_utils.h +++ b/src/macros_and_utils.h | |||
@@ -10,6 +10,8 @@ extern "C" { | |||
10 | } | 10 | } |
11 | #endif // __cplusplus | 11 | #endif // __cplusplus |
12 | 12 | ||
13 | #include <cassert> | ||
14 | |||
13 | #define USE_DEBUG_SPEW() 0 | 15 | #define USE_DEBUG_SPEW() 0 |
14 | #if USE_DEBUG_SPEW() | 16 | #if USE_DEBUG_SPEW() |
15 | extern char const* debugspew_indent; | 17 | extern char const* debugspew_indent; |
@@ -27,53 +29,89 @@ extern char const* debugspew_indent; | |||
27 | #ifdef NDEBUG | 29 | #ifdef NDEBUG |
28 | 30 | ||
29 | #define _ASSERT_L(lua,c) //nothing | 31 | #define _ASSERT_L(lua,c) //nothing |
30 | #define STACK_CHECK(L,o) //nothing | ||
31 | #define STACK_CHECK_ABS(L,o) //nothing | ||
32 | #define STACK_MID(L,c) //nothing | ||
33 | #define STACK_END(L,c) //nothing | ||
34 | #define STACK_DUMP(L) //nothing | 32 | #define STACK_DUMP(L) //nothing |
35 | 33 | ||
34 | #define STACK_CHECK_START_REL(L, offset_) | ||
35 | #define STACK_CHECK_START_ABS(L, offset_) | ||
36 | #define STACK_CHECK_RESET_REL(L, offset_) | ||
37 | #define STACK_CHECK_RESET_ABS(L, offset_) | ||
38 | #define STACK_CHECK(L, offset_) | ||
39 | |||
36 | #else // NDEBUG | 40 | #else // NDEBUG |
37 | 41 | ||
38 | #define _ASSERT_L( L, cond_) if( (cond_) == 0) { (void) luaL_error( L, "ASSERT failed: %s:%d '%s'", __FILE__, __LINE__, #cond_);} | 42 | #define _ASSERT_L( L, cond_) if( (cond_) == 0) { (void) luaL_error( L, "ASSERT failed: %s:%d '%s'", __FILE__, __LINE__, #cond_);} |
43 | #define STACK_DUMP( L) luaG_dump( L) | ||
44 | |||
45 | class StackChecker | ||
46 | { | ||
47 | private: | ||
48 | lua_State* const m_L; | ||
49 | int m_oldtop; | ||
50 | |||
51 | public: | ||
52 | struct Relative | ||
53 | { | ||
54 | int const m_offset; | ||
55 | |||
56 | operator int() const { return m_offset; } | ||
57 | }; | ||
58 | |||
59 | struct Absolute | ||
60 | { | ||
61 | int const m_offset; | ||
39 | 62 | ||
40 | #define STACK_CHECK( L, offset_) \ | 63 | operator int() const { return m_offset; } |
41 | { \ | 64 | }; |
42 | int const L##_delta = offset_; \ | 65 | |
43 | if( (L##_delta < 0) || (lua_gettop( L) < L##_delta)) \ | 66 | StackChecker(lua_State* const L_, Relative offset_, char const* file_, size_t const line_) |
44 | { \ | 67 | : m_L{ L_ } |
45 | assert( false); \ | 68 | , m_oldtop{ lua_gettop(L_) - offset_ } |
46 | (void) luaL_error( L, "STACK INIT ASSERT failed (%d not %d): %s:%d", lua_gettop( L), L##_delta, __FILE__, __LINE__); \ | 69 | { |
47 | } \ | 70 | if ((offset_ < 0) || (m_oldtop < 0)) |
48 | int const L##_oldtop = lua_gettop( L) - L##_delta | 71 | { |
49 | 72 | assert(false); | |
50 | #define STACK_CHECK_ABS( L, offset_) \ | 73 | (void) luaL_error(m_L, "STACK INIT ASSERT failed (%d not %d): %s:%d", lua_gettop(m_L), offset_, file_, line_); |
51 | { \ | 74 | } |
52 | int const L##_pos = offset_; \ | ||
53 | if( lua_gettop( L) < L##_pos) \ | ||
54 | { \ | ||
55 | assert( false); \ | ||
56 | (void) luaL_error( L, "STACK INIT ASSERT failed (%d not %d): %s:%d", lua_gettop( L), L##_pos, __FILE__, __LINE__); \ | ||
57 | } \ | ||
58 | int const L##_oldtop = 0 | ||
59 | |||
60 | #define STACK_MID( L, change) \ | ||
61 | do if( change != LUA_MULTRET) \ | ||
62 | { \ | ||
63 | int stack_check_a = lua_gettop( L) - L##_oldtop; \ | ||
64 | int stack_check_b = (change); \ | ||
65 | if( stack_check_a != stack_check_b) \ | ||
66 | { \ | ||
67 | assert( false); \ | ||
68 | luaL_error( L, "STACK ASSERT failed (%d not %d): %s:%d", stack_check_a, stack_check_b, __FILE__, __LINE__); \ | ||
69 | } \ | ||
70 | } while( 0) | ||
71 | |||
72 | #define STACK_END( L, change) \ | ||
73 | STACK_MID( L, change); \ | ||
74 | } | 75 | } |
75 | 76 | ||
76 | #define STACK_DUMP( L) luaG_dump( L) | 77 | StackChecker(lua_State* const L_, Absolute pos_, char const* file_, size_t const line_) |
78 | : m_L{ L_ } | ||
79 | , m_oldtop{ 0 } | ||
80 | { | ||
81 | if (lua_gettop(m_L) != pos_) | ||
82 | { | ||
83 | assert(false); | ||
84 | (void) luaL_error(m_L, "STACK INIT ASSERT failed (%d not %d): %s:%d", lua_gettop(m_L), pos_, file_, line_); | ||
85 | } | ||
86 | } | ||
87 | |||
88 | StackChecker& operator=(StackChecker const& rhs_) | ||
89 | { | ||
90 | assert(m_L == rhs_.m_L); | ||
91 | m_oldtop = rhs_.m_oldtop; | ||
92 | return *this; | ||
93 | } | ||
94 | |||
95 | // verify if the distance between the current top and the initial one is what we expect | ||
96 | void check(int expected_, char const* file_, size_t const line_) | ||
97 | { | ||
98 | if (expected_ != LUA_MULTRET) | ||
99 | { | ||
100 | int const actual{ lua_gettop(m_L) - m_oldtop }; | ||
101 | if (actual != expected_) | ||
102 | { | ||
103 | assert(false); | ||
104 | luaL_error(m_L, "STACK ASSERT failed (%d not %d): %s:%d", actual, expected_, file_, line_); | ||
105 | } | ||
106 | } | ||
107 | } | ||
108 | }; | ||
109 | |||
110 | #define STACK_CHECK_START_REL(L, offset_) StackChecker stackChecker_##L(L, StackChecker::Relative{ offset_ }, __FILE__, __LINE__) | ||
111 | #define STACK_CHECK_START_ABS(L, offset_) StackChecker stackChecker_##L(L, StackChecker::Absolute{ offset_ }, __FILE__, __LINE__) | ||
112 | #define STACK_CHECK_RESET_REL(L, offset_) stackChecker_##L = StackChecker{L, StackChecker::Relative{ offset_ }, __FILE__, __LINE__} | ||
113 | #define STACK_CHECK_RESET_ABS(L, offset_) stackChecker_##L = StackChecker{L, StackChecker::Absolute{ offset_ }, __FILE__, __LINE__} | ||
114 | #define STACK_CHECK(L, offset_) stackChecker_##L.check(offset_, __FILE__, __LINE__) | ||
77 | 115 | ||
78 | #endif // NDEBUG | 116 | #endif // NDEBUG |
79 | 117 | ||