diff options
Diffstat (limited to 'src/tools.cpp')
-rw-r--r-- | src/tools.cpp | 101 |
1 files changed, 64 insertions, 37 deletions
diff --git a/src/tools.cpp b/src/tools.cpp index cbfefb0..cd1c593 100644 --- a/src/tools.cpp +++ b/src/tools.cpp | |||
@@ -45,13 +45,29 @@ static constexpr RegistryUniqueKey kLookupCacheRegKey{ 0x9BF75F84E54B691Bull }; | |||
45 | 45 | ||
46 | // ################################################################################################# | 46 | // ################################################################################################# |
47 | 47 | ||
48 | static constexpr int kWriterReturnCode{ 666 }; | 48 | namespace { |
49 | [[nodiscard]] | 49 | namespace local { |
50 | static int dummy_writer([[maybe_unused]] lua_State* const L_, [[maybe_unused]] void const* p_, [[maybe_unused]] size_t sz_, [[maybe_unused]] void* ud_) | 50 | static int buf_writer([[maybe_unused]] lua_State* const L_, void const* b_, size_t size_, void* ud_) |
51 | { | 51 | { |
52 | // always fail with this code | 52 | auto* const _B{ static_cast<luaL_Buffer*>(ud_) }; |
53 | return kWriterReturnCode; | 53 | if (b_ && size_) { |
54 | } | 54 | luaL_addlstring(_B, static_cast<char const*>(b_), size_); |
55 | } | ||
56 | return 0; | ||
57 | } | ||
58 | |||
59 | static constexpr int kWriterReturnCode{ 666 }; | ||
60 | [[nodiscard]] | ||
61 | static int dummy_writer([[maybe_unused]] lua_State* const L_, [[maybe_unused]] void const* p_, [[maybe_unused]] size_t sz_, [[maybe_unused]] void* ud_) | ||
62 | { | ||
63 | // always fail with this code | ||
64 | return kWriterReturnCode; | ||
65 | } | ||
66 | |||
67 | } // namespace local | ||
68 | } // namespace | ||
69 | |||
70 | // ################################################################################################# | ||
55 | 71 | ||
56 | /* | 72 | /* |
57 | * differentiation between C, bytecode and JIT-fast functions | 73 | * differentiation between C, bytecode and JIT-fast functions |
@@ -59,30 +75,28 @@ static int dummy_writer([[maybe_unused]] lua_State* const L_, [[maybe_unused]] v | |||
59 | * +-------------------+------------+----------+ | 75 | * +-------------------+------------+----------+ |
60 | * | bytecode | C function | JIT-fast | | 76 | * | bytecode | C function | JIT-fast | |
61 | * +-----------------+-------------------+------------+----------+ | 77 | * +-----------------+-------------------+------------+----------+ |
62 | * | lua_topointer | | | | | 78 | * | lua_tocfunction | nullptr | <some p> | nullptr | |
63 | * +-----------------+-------------------+------------+----------+ | 79 | * +-----------------+-------------------+------------+----------+ |
64 | * | lua_tocfunction | nullptr | | nullptr | | 80 | * | luaW_dump | kWriterReturnCode | 1 | 1 | |
65 | * +-----------------+-------------------+------------+----------+ | ||
66 | * | luaG_dump | kWriterReturnCode | 1 | 1 | | ||
67 | * +-----------------+-------------------+------------+----------+ | 81 | * +-----------------+-------------------+------------+----------+ |
68 | */ | 82 | */ |
69 | 83 | ||
70 | [[nodiscard]] | 84 | [[nodiscard]] |
71 | FuncSubType luaG_getfuncsubtype(lua_State* const L_, StackIndex const i_) | 85 | FuncSubType luaW_getfuncsubtype(lua_State* const L_, StackIndex const i_) |
72 | { | 86 | { |
73 | if (lua_tocfunction(L_, i_)) { // nullptr for LuaJIT-fast && bytecode functions | 87 | if (lua_tocfunction(L_, i_)) { // nullptr for LuaJIT-fast && bytecode functions |
74 | return FuncSubType::Native; | 88 | return FuncSubType::Native; |
75 | } | 89 | } |
76 | 90 | ||
77 | // luaG_dump expects the function at the top of the stack | 91 | // luaW_dump expects the function at the top of the stack |
78 | int const _popCount{ (luaG_absindex(L_, i_) == lua_gettop(L_)) ? 0 : (lua_pushvalue(L_, i_), 1) }; | 92 | int const _popCount{ (luaW_absindex(L_, i_) == lua_gettop(L_)) ? 0 : (lua_pushvalue(L_, i_), 1) }; |
79 | // here we either have a Lua bytecode or a LuaJIT-compiled function | 93 | // here we either have a Lua bytecode or a LuaJIT-compiled function |
80 | int const _dumpres{ luaG_dump(L_, dummy_writer, nullptr, 0) }; | 94 | int const _dumpres{ luaW_dump(L_, local::dummy_writer, nullptr, 0) }; |
81 | if (_popCount > 0) { | 95 | if (_popCount > 0) { |
82 | lua_pop(L_, _popCount); | 96 | lua_pop(L_, _popCount); |
83 | } | 97 | } |
84 | if (_dumpres == kWriterReturnCode) { | 98 | if (_dumpres == local::kWriterReturnCode) { |
85 | // anytime we get kWriterReturnCode, this means that luaG_dump() attempted a dump | 99 | // anytime we get kWriterReturnCode, this means that luaW_dump() attempted a dump |
86 | return FuncSubType::Bytecode; | 100 | return FuncSubType::Bytecode; |
87 | } | 101 | } |
88 | // we didn't try to dump, therefore this is a LuaJIT-fast function | 102 | // we didn't try to dump, therefore this is a LuaJIT-fast function |
@@ -92,7 +106,6 @@ FuncSubType luaG_getfuncsubtype(lua_State* const L_, StackIndex const i_) | |||
92 | // ################################################################################################# | 106 | // ################################################################################################# |
93 | 107 | ||
94 | namespace tools { | 108 | namespace tools { |
95 | |||
96 | // inspired from tconcat() in ltablib.c | 109 | // inspired from tconcat() in ltablib.c |
97 | [[nodiscard]] | 110 | [[nodiscard]] |
98 | std::string_view PushFQN(lua_State* const L_, StackIndex const t_) | 111 | std::string_view PushFQN(lua_State* const L_, StackIndex const t_) |
@@ -115,9 +128,23 @@ namespace tools { | |||
115 | // &b is popped at that point (-> replaced by the result) | 128 | // &b is popped at that point (-> replaced by the result) |
116 | luaL_pushresult(&_b); // L_: ... {} ... "<result>" | 129 | luaL_pushresult(&_b); // L_: ... {} ... "<result>" |
117 | STACK_CHECK(L_, 1); | 130 | STACK_CHECK(L_, 1); |
118 | return luaG_tostring(L_, kIdxTop); | 131 | return luaW_tostring(L_, kIdxTop); |
119 | } | 132 | } |
120 | 133 | ||
134 | // ############################################################################################# | ||
135 | |||
136 | void PushFunctionBytecode(SourceState const L1_, DestState const L2_, int const strip_) | ||
137 | { | ||
138 | luaL_Buffer B{}; | ||
139 | STACK_CHECK_START_REL(L1_, 0); | ||
140 | STACK_CHECK_START_REL(L2_, 0); | ||
141 | STACK_GROW(L2_, 2); | ||
142 | luaL_buffinit(L2_, &B); // L1_: ... f L2_: ... <B stuff> | ||
143 | luaW_dump(L1_, local::buf_writer, &B, strip_); | ||
144 | luaL_pushresult(&B); // L2_: ... "<bytecode>" | ||
145 | STACK_CHECK(L2_, 1); | ||
146 | STACK_CHECK(L1_, 0); | ||
147 | } | ||
121 | } // namespace tools | 148 | } // namespace tools |
122 | 149 | ||
123 | // ################################################################################################# | 150 | // ################################################################################################# |
@@ -145,10 +172,10 @@ static void update_lookup_entry(lua_State* const L_, StackIndex const ctxBase_, | |||
145 | // first, raise an error if the function is already known | 172 | // first, raise an error if the function is already known |
146 | lua_pushvalue(L_, -1); // L_: ... {bfc} k o o | 173 | lua_pushvalue(L_, -1); // L_: ... {bfc} k o o |
147 | lua_rawget(L_, _dest); // L_: ... {bfc} k o name? | 174 | lua_rawget(L_, _dest); // L_: ... {bfc} k o name? |
148 | std::string_view const _prevName{ luaG_tostring(L_, kIdxTop) }; // nullptr if we got nil (first encounter of this object) | 175 | std::string_view const _prevName{ luaW_tostring(L_, kIdxTop) }; // nullptr if we got nil (first encounter of this object) |
149 | // push name in fqn stack (note that concatenation will crash if name is a not string or a number) | 176 | // push name in fqn stack (note that concatenation will crash if name is a not string or a number) |
150 | lua_pushvalue(L_, -3); // L_: ... {bfc} k o name? k | 177 | lua_pushvalue(L_, -3); // L_: ... {bfc} k o name? k |
151 | LUA_ASSERT(L_, luaG_type(L_, kIdxTop) == LuaType::NUMBER || luaG_type(L_, kIdxTop) == LuaType::STRING); | 178 | LUA_ASSERT(L_, luaW_type(L_, kIdxTop) == LuaType::NUMBER || luaW_type(L_, kIdxTop) == LuaType::STRING); |
152 | TableIndex const _deeper{ depth_ + 1 }; | 179 | TableIndex const _deeper{ depth_ + 1 }; |
153 | lua_rawseti(L_, _fqn, _deeper); // L_: ... {bfc} k o name? | 180 | lua_rawseti(L_, _fqn, _deeper); // L_: ... {bfc} k o name? |
154 | // generate name | 181 | // generate name |
@@ -161,7 +188,7 @@ static void update_lookup_entry(lua_State* const L_, StackIndex const ctxBase_, | |||
161 | // Therefore, when we encounter an object for which a name was previously registered, we need to select a single name | 188 | // Therefore, when we encounter an object for which a name was previously registered, we need to select a single name |
162 | // based on some sorting order so that we end up with the same name in all databases whatever order the table walk yielded | 189 | // based on some sorting order so that we end up with the same name in all databases whatever order the table walk yielded |
163 | if (!_prevName.empty() && ((_prevName.size() < _newName.size()) || (_prevName <= _newName))) { | 190 | if (!_prevName.empty() && ((_prevName.size() < _newName.size()) || (_prevName <= _newName))) { |
164 | DEBUGSPEW_CODE(DebugSpew(_U) << luaG_typename(L_, StackIndex{ -3 }) << " '" << _newName << "' remains named '" << _prevName << "'" << std::endl); | 191 | DEBUGSPEW_CODE(DebugSpew(_U) << luaW_typename(L_, StackIndex{ -3 }) << " '" << _newName << "' remains named '" << _prevName << "'" << std::endl); |
165 | // the previous name is 'smaller' than the one we just generated: keep it! | 192 | // the previous name is 'smaller' than the one we just generated: keep it! |
166 | lua_pop(L_, 3); // L_: ... {bfc} k | 193 | lua_pop(L_, 3); // L_: ... {bfc} k |
167 | } else { | 194 | } else { |
@@ -175,7 +202,7 @@ static void update_lookup_entry(lua_State* const L_, StackIndex const ctxBase_, | |||
175 | } else { | 202 | } else { |
176 | lua_remove(L_, -2); // L_: ... {bfc} k o "f.q.n" | 203 | lua_remove(L_, -2); // L_: ... {bfc} k o "f.q.n" |
177 | } | 204 | } |
178 | DEBUGSPEW_CODE(DebugSpew(_U) << luaG_typename(L_, StackIndex{ -2 }) << " '" << _newName << "'" << std::endl); | 205 | DEBUGSPEW_CODE(DebugSpew(_U) << luaW_typename(L_, StackIndex{ -2 }) << " '" << _newName << "'" << std::endl); |
179 | // prepare the stack for database feed | 206 | // prepare the stack for database feed |
180 | lua_pushvalue(L_, -1); // L_: ... {bfc} k o "f.q.n" "f.q.n" | 207 | lua_pushvalue(L_, -1); // L_: ... {bfc} k o "f.q.n" "f.q.n" |
181 | lua_pushvalue(L_, -3); // L_: ... {bfc} k o "f.q.n" "f.q.n" o | 208 | lua_pushvalue(L_, -3); // L_: ... {bfc} k o "f.q.n" "f.q.n" o |
@@ -210,7 +237,7 @@ static void populate_lookup_table_recur(lua_State* const L_, StackIndex const db | |||
210 | STACK_CHECK_START_REL(L_, 0); // L_: ... {i_} | 237 | STACK_CHECK_START_REL(L_, 0); // L_: ... {i_} |
211 | 238 | ||
212 | // if object is a userdata, replace it by its metatable | 239 | // if object is a userdata, replace it by its metatable |
213 | if (luaG_type(L_, i_) == LuaType::USERDATA) { | 240 | if (luaW_type(L_, i_) == LuaType::USERDATA) { |
214 | lua_getmetatable(L_, i_); // L_: ... {i_} mt | 241 | lua_getmetatable(L_, i_); // L_: ... {i_} mt |
215 | lua_replace(L_, i_); // L_: ... {i_} | 242 | lua_replace(L_, i_); // L_: ... {i_} |
216 | } | 243 | } |
@@ -239,7 +266,7 @@ static void populate_lookup_table_recur(lua_State* const L_, StackIndex const db | |||
239 | lua_pushnil(L_); // L_: ... {i_} {bfc} nil | 266 | lua_pushnil(L_); // L_: ... {i_} {bfc} nil |
240 | while (lua_next(L_, i_) != 0) { // L_: ... {i_} {bfc} k v | 267 | while (lua_next(L_, i_) != 0) { // L_: ... {i_} {bfc} k v |
241 | // just for debug, not actually needed | 268 | // just for debug, not actually needed |
242 | // std::string_view const _key{ (luaG_type(L_, -2) == LuaType::STRING) ? luaG_tostring(L_, -2) : "not a string" }; | 269 | // std::string_view const _key{ (luaW_type(L_, -2) == LuaType::STRING) ? luaW_tostring(L_, -2) : "not a string" }; |
243 | // subtable: process it recursively | 270 | // subtable: process it recursively |
244 | if (lua_istable(L_, kIdxTop)) { // L_: ... {i_} {bfc} k {} | 271 | if (lua_istable(L_, kIdxTop)) { // L_: ... {i_} {bfc} k {} |
245 | // increment visit count to make sure we will actually scan it at this recursive level | 272 | // increment visit count to make sure we will actually scan it at this recursive level |
@@ -256,11 +283,11 @@ static void populate_lookup_table_recur(lua_State* const L_, StackIndex const db | |||
256 | lua_rawset(L_, _breadthFirstCache); // L_: ... {i_} {bfc} k {} | 283 | lua_rawset(L_, _breadthFirstCache); // L_: ... {i_} {bfc} k {} |
257 | // generate a name, and if we already had one name, keep whichever is the shorter | 284 | // generate a name, and if we already had one name, keep whichever is the shorter |
258 | update_lookup_entry(L_, dbIdx_, depth_); // L_: ... {i_} {bfc} k | 285 | update_lookup_entry(L_, dbIdx_, depth_); // L_: ... {i_} {bfc} k |
259 | } else if (lua_isfunction(L_, kIdxTop) && (luaG_getfuncsubtype(L_, kIdxTop) != FuncSubType::Bytecode)) { | 286 | } else if (lua_isfunction(L_, kIdxTop) && (luaW_getfuncsubtype(L_, kIdxTop) != FuncSubType::Bytecode)) { |
260 | // generate a name, and if we already had one name, keep whichever is the shorter | 287 | // generate a name, and if we already had one name, keep whichever is the shorter |
261 | // this pops the function from the stack | 288 | // this pops the function from the stack |
262 | update_lookup_entry(L_, dbIdx_, depth_); // L_: ... {i_} {bfc} k | 289 | update_lookup_entry(L_, dbIdx_, depth_); // L_: ... {i_} {bfc} k |
263 | } else if (luaG_type(L_, kIdxTop) == LuaType::USERDATA) { | 290 | } else if (luaW_type(L_, kIdxTop) == LuaType::USERDATA) { |
264 | // generate a name, and if we already had one name, keep whichever is the shorter | 291 | // generate a name, and if we already had one name, keep whichever is the shorter |
265 | // this pops the userdata from the stack | 292 | // this pops the userdata from the stack |
266 | update_lookup_entry(L_, dbIdx_, depth_); // L_: ... {i_} {bfc} k | 293 | update_lookup_entry(L_, dbIdx_, depth_); // L_: ... {i_} {bfc} k |
@@ -273,13 +300,13 @@ static void populate_lookup_table_recur(lua_State* const L_, StackIndex const db | |||
273 | TableIndex const _deeper{ depth_ + 1 }; | 300 | TableIndex const _deeper{ depth_ + 1 }; |
274 | lua_pushnil(L_); // L_: ... {i_} {bfc} nil | 301 | lua_pushnil(L_); // L_: ... {i_} {bfc} nil |
275 | while (lua_next(L_, _breadthFirstCache) != 0) { // L_: ... {i_} {bfc} k {} | 302 | while (lua_next(L_, _breadthFirstCache) != 0) { // L_: ... {i_} {bfc} k {} |
276 | DEBUGSPEW_CODE(std::string_view const _key{ (luaG_type(L_, StackIndex{ -2 }) == LuaType::STRING) ? luaG_tostring(L_, StackIndex{ -2 }) : std::string_view{ "<not a string>" } }); | 303 | DEBUGSPEW_CODE(std::string_view const _key{ (luaW_type(L_, StackIndex{ -2 }) == LuaType::STRING) ? luaW_tostring(L_, StackIndex{ -2 }) : std::string_view{ "<not a string>" } }); |
277 | DEBUGSPEW_CODE(DebugSpew(_U) << "table '"<< _key <<"'" << std::endl); | 304 | DEBUGSPEW_CODE(DebugSpew(_U) << "table '"<< _key <<"'" << std::endl); |
278 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope2{ _U }); | 305 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope2{ _U }); |
279 | // un-visit this table in case we do need to process it | 306 | // un-visit this table in case we do need to process it |
280 | lua_pushvalue(L_, -1); // L_: ... {i_} {bfc} k {} {} | 307 | lua_pushvalue(L_, -1); // L_: ... {i_} {bfc} k {} {} |
281 | lua_rawget(L_, _cache); // L_: ... {i_} {bfc} k {} n | 308 | lua_rawget(L_, _cache); // L_: ... {i_} {bfc} k {} n |
282 | LUA_ASSERT(L_, luaG_type(L_, kIdxTop) == LuaType::NUMBER); | 309 | LUA_ASSERT(L_, luaW_type(L_, kIdxTop) == LuaType::NUMBER); |
283 | _visit_count = lua_tointeger(L_, -1) - 1; | 310 | _visit_count = lua_tointeger(L_, -1) - 1; |
284 | lua_pop(L_, 1); // L_: ... {i_} {bfc} k {} | 311 | lua_pop(L_, 1); // L_: ... {i_} {bfc} k {} |
285 | lua_pushvalue(L_, -1); // L_: ... {i_} {bfc} k {} {} | 312 | lua_pushvalue(L_, -1); // L_: ... {i_} {bfc} k {} {} |
@@ -312,7 +339,7 @@ namespace tools { | |||
312 | // create a "fully.qualified.name" <-> function equivalence database | 339 | // create a "fully.qualified.name" <-> function equivalence database |
313 | void PopulateFuncLookupTable(lua_State* const L_, StackIndex const i_, std::string_view const& name_) | 340 | void PopulateFuncLookupTable(lua_State* const L_, StackIndex const i_, std::string_view const& name_) |
314 | { | 341 | { |
315 | StackIndex const _in_base{ luaG_absindex(L_, i_) }; | 342 | StackIndex const _in_base{ luaW_absindex(L_, i_) }; |
316 | DEBUGSPEW_CODE(Universe* _U = Universe::Get(L_)); | 343 | DEBUGSPEW_CODE(Universe* _U = Universe::Get(L_)); |
317 | std::string_view _name{ name_.empty() ? std::string_view{} : name_ }; | 344 | std::string_view _name{ name_.empty() ? std::string_view{} : name_ }; |
318 | DEBUGSPEW_CODE(DebugSpew(_U) << L_ << ": PopulateFuncLookupTable('" << _name << "')" << std::endl); | 345 | DEBUGSPEW_CODE(DebugSpew(_U) << L_ << ": PopulateFuncLookupTable('" << _name << "')" << std::endl); |
@@ -323,24 +350,24 @@ namespace tools { | |||
323 | StackIndex const _dbIdx{ lua_gettop(L_) }; | 350 | StackIndex const _dbIdx{ lua_gettop(L_) }; |
324 | STACK_CHECK(L_, 1); | 351 | STACK_CHECK(L_, 1); |
325 | LUA_ASSERT(L_, lua_istable(L_, -1)); | 352 | LUA_ASSERT(L_, lua_istable(L_, -1)); |
326 | LuaType const _moduleType{ luaG_type(L_, _in_base) }; | 353 | LuaType const _moduleType{ luaW_type(L_, _in_base) }; |
327 | if ((_moduleType == LuaType::FUNCTION) || (_moduleType == LuaType::USERDATA)) { // for example when a module is a simple function | 354 | if ((_moduleType == LuaType::FUNCTION) || (_moduleType == LuaType::USERDATA)) { // for example when a module is a simple function |
328 | if (_name.empty()) { | 355 | if (_name.empty()) { |
329 | _name = "nullptr"; | 356 | _name = "nullptr"; |
330 | } | 357 | } |
331 | lua_pushvalue(L_, _in_base); // L_: {} f | 358 | lua_pushvalue(L_, _in_base); // L_: {} f |
332 | luaG_pushstring(L_, _name); // L_: {} f name_ | 359 | luaW_pushstring(L_, _name); // L_: {} f name_ |
333 | lua_rawset(L_, -3); // L_: {} | 360 | lua_rawset(L_, -3); // L_: {} |
334 | luaG_pushstring(L_, _name); // L_: {} name_ | 361 | luaW_pushstring(L_, _name); // L_: {} name_ |
335 | lua_pushvalue(L_, _in_base); // L_: {} name_ f | 362 | lua_pushvalue(L_, _in_base); // L_: {} name_ f |
336 | lua_rawset(L_, -3); // L_: {} | 363 | lua_rawset(L_, -3); // L_: {} |
337 | lua_pop(L_, 1); // L_: | 364 | lua_pop(L_, 1); // L_: |
338 | } else if (luaG_type(L_, _in_base) == LuaType::TABLE) { | 365 | } else if (luaW_type(L_, _in_base) == LuaType::TABLE) { |
339 | lua_newtable(L_); // L_: {} {fqn} | 366 | lua_newtable(L_); // L_: {} {fqn} |
340 | TableIndex _startDepth{ 0 }; | 367 | TableIndex _startDepth{ 0 }; |
341 | if (!_name.empty()) { | 368 | if (!_name.empty()) { |
342 | STACK_CHECK(L_, 2); | 369 | STACK_CHECK(L_, 2); |
343 | luaG_pushstring(L_, _name); // L_: {} {fqn} "name" | 370 | luaW_pushstring(L_, _name); // L_: {} {fqn} "name" |
344 | // generate a name, and if we already had one name, keep whichever is the shorter | 371 | // generate a name, and if we already had one name, keep whichever is the shorter |
345 | lua_pushvalue(L_, _in_base); // L_: {} {fqn} "name" t | 372 | lua_pushvalue(L_, _in_base); // L_: {} {fqn} "name" t |
346 | update_lookup_entry(L_, _dbIdx, _startDepth); // L_: {} {fqn} "name" | 373 | update_lookup_entry(L_, _dbIdx, _startDepth); // L_: {} {fqn} "name" |
@@ -355,7 +382,7 @@ namespace tools { | |||
355 | lua_pop(L_, 3); // L_: | 382 | lua_pop(L_, 3); // L_: |
356 | } else { | 383 | } else { |
357 | lua_pop(L_, 1); // L_: | 384 | lua_pop(L_, 1); // L_: |
358 | raise_luaL_error(L_, "unsupported module type %s", luaG_typename(L_, _in_base).data()); | 385 | raise_luaL_error(L_, "unsupported module type %s", luaW_typename(L_, _in_base).data()); |
359 | } | 386 | } |
360 | STACK_CHECK(L_, 0); | 387 | STACK_CHECK(L_, 0); |
361 | } | 388 | } |
@@ -373,7 +400,7 @@ namespace tools { | |||
373 | +[](lua_State* L_) | 400 | +[](lua_State* L_) |
374 | { | 401 | { |
375 | int const _args{ lua_gettop(L_) }; // L_: args... | 402 | int const _args{ lua_gettop(L_) }; // L_: args... |
376 | //[[maybe_unused]] std::string_view const _modname{ luaG_checkstring(L_, 1) }; | 403 | //[[maybe_unused]] std::string_view const _modname{ luaW_checkstring(L_, 1) }; |
377 | 404 | ||
378 | STACK_GROW(L_, 1); | 405 | STACK_GROW(L_, 1); |
379 | 406 | ||