aboutsummaryrefslogtreecommitdiff
path: root/src/intercopycontext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/intercopycontext.cpp')
-rw-r--r--src/intercopycontext.cpp87
1 files changed, 41 insertions, 46 deletions
diff --git a/src/intercopycontext.cpp b/src/intercopycontext.cpp
index 2f83400..1487afd 100644
--- a/src/intercopycontext.cpp
+++ b/src/intercopycontext.cpp
@@ -96,38 +96,37 @@ THE SOFTWARE.
96 lua_pushvalue(L1, L1_i); // L1: ... v ... {} v 96 lua_pushvalue(L1, L1_i); // L1: ... v ... {} v
97 lua_rawget(L1, -2); // L1: ... v ... {} "f.q.n" 97 lua_rawget(L1, -2); // L1: ... v ... {} "f.q.n"
98 } 98 }
99 size_t _len{ 0 }; 99 std::string_view _fqn{ lua_tostringview(L1, -1) };
100 char const* _fqn{ lua_tolstring(L1, -1, &_len) };
101 DEBUGSPEW_CODE(Universe* const _U = universe_get(L1)); 100 DEBUGSPEW_CODE(Universe* const _U = universe_get(L1));
102 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "function [C] %s \n" INDENT_END(_U), _fqn)); 101 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "function [C] %s \n" INDENT_END(_U), _fqn.data()));
103 // popping doesn't invalidate the pointer since this is an interned string gotten from the lookup database 102 // popping doesn't invalidate the pointer since this is an interned string gotten from the lookup database
104 lua_pop(L1, (mode == LookupMode::FromKeeper) ? 1 : 2); // L1: ... v ... 103 lua_pop(L1, (mode == LookupMode::FromKeeper) ? 1 : 2); // L1: ... v ...
105 STACK_CHECK(L1, 0); 104 STACK_CHECK(L1, 0);
106 if (nullptr == _fqn && !lua_istable(L1, L1_i)) { // raise an error if we try to send an unknown function (but not for tables) 105 if (_fqn.empty() && !lua_istable(L1, L1_i)) { // raise an error if we try to send an unknown function (but not for tables)
107 _len = 0; // just in case 106 _fqn = std::string_view{}; // just in case
108 // try to discover the name of the function we want to send 107 // try to discover the name of the function we want to send
109 lua_getglobal(L1, "decoda_name"); // L1: ... v ... decoda_name 108 lua_getglobal(L1, "decoda_name"); // L1: ... v ... decoda_name
110 char const* from{ lua_tostring(L1, -1) }; 109 char const* _from{ lua_tostring(L1, -1) };
111 lua_pushcfunction(L1, luaG_nameof); // L1: ... v ... decoda_name luaG_nameof 110 lua_pushcfunction(L1, luaG_nameof); // L1: ... v ... decoda_name luaG_nameof
112 lua_pushvalue(L1, L1_i); // L1: ... v ... decoda_name luaG_nameof t 111 lua_pushvalue(L1, L1_i); // L1: ... v ... decoda_name luaG_nameof t
113 lua_call(L1, 1, 2); // L1: ... v ... decoda_name "type" "name"|nil 112 lua_call(L1, 1, 2); // L1: ... v ... decoda_name "type" "name"|nil
114 char const* typewhat{ (lua_type(L1, -2) == LUA_TSTRING) ? lua_tostring(L1, -2) : luaL_typename(L1, -2) }; 113 char const* _typewhat{ (lua_type(L1, -2) == LUA_TSTRING) ? lua_tostring(L1, -2) : luaL_typename(L1, -2) };
115 // second return value can be nil if the table was not found 114 // second return value can be nil if the table was not found
116 // probable reason: the function was removed from the source Lua state before Lanes was required. 115 // probable reason: the function was removed from the source Lua state before Lanes was required.
117 char const *what, *gotchaA, *gotchaB; 116 char const *_what, *_gotchaA, *_gotchaB;
118 if (lua_isnil(L1, -1)) { 117 if (lua_isnil(L1, -1)) {
119 gotchaA = " referenced by"; 118 _gotchaA = " referenced by";
120 gotchaB = "\n(did you remove it from the source Lua state before requiring Lanes?)"; 119 _gotchaB = "\n(did you remove it from the source Lua state before requiring Lanes?)";
121 what = name; 120 _what = name;
122 } else { 121 } else {
123 gotchaA = ""; 122 _gotchaA = "";
124 gotchaB = ""; 123 _gotchaB = "";
125 what = (lua_type(L1, -1) == LUA_TSTRING) ? lua_tostring(L1, -1) : luaL_typename(L1, -1); 124 _what = (lua_type(L1, -1) == LUA_TSTRING) ? lua_tostring(L1, -1) : luaL_typename(L1, -1);
126 } 125 }
127 raise_luaL_error(L1, "%s%s '%s' not found in %s origin transfer database.%s", typewhat, gotchaA, what, from ? from : "main", gotchaB); 126 raise_luaL_error(L1, "%s%s '%s' not found in %s origin transfer database.%s", _typewhat, _gotchaA, _what, _from ? _from : "main", _gotchaB);
128 } 127 }
129 STACK_CHECK(L1, 0); 128 STACK_CHECK(L1, 0);
130 return std::string_view{ _fqn, _len }; 129 return _fqn;
131} 130}
132 131
133// ################################################################################################# 132// #################################################################################################
@@ -208,7 +207,7 @@ void InterCopyContext::copy_func() const
208 207
209 // transfer the bytecode, then the upvalues, to create a similar closure 208 // transfer the bytecode, then the upvalues, to create a similar closure
210 { 209 {
211 char const* fname = nullptr; 210 char const* _fname{};
212#define LOG_FUNC_INFO 0 211#define LOG_FUNC_INFO 0
213#if LOG_FUNC_INFO 212#if LOG_FUNC_INFO
214 // "To get information about a function you push it onto the 213 // "To get information about a function you push it onto the
@@ -219,14 +218,13 @@ void InterCopyContext::copy_func() const
219 lua_pushvalue(L1, L1_i); // L1: ... b f 218 lua_pushvalue(L1, L1_i); // L1: ... b f
220 // fills 'fname' 'namewhat' and 'linedefined', pops function 219 // fills 'fname' 'namewhat' and 'linedefined', pops function
221 lua_getinfo(L1, ">nS", &_ar); // L1: ... b 220 lua_getinfo(L1, ">nS", &_ar); // L1: ... b
222 fname = _ar.namewhat; 221 _fname = _ar.namewhat;
223 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "FNAME: %s @ %d" INDENT_END(U), _ar.short_src, _ar.linedefined)); // just gives nullptr 222 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "FNAME: %s @ %d" INDENT_END(U), _ar.short_src, _ar.linedefined)); // just gives nullptr
224 } 223 }
225#endif // LOG_FUNC_INFO 224#endif // LOG_FUNC_INFO
226 { 225 {
227 size_t _sz; 226 std::string_view const _bytecode{ lua_tostringview(L1, -1) }; // L1: ... b
228 char const* _s{ lua_tolstring(L1, -1, &_sz) }; // L1: ... b 227 LUA_ASSERT(L1, !_bytecode.empty());
229 LUA_ASSERT(L1, _s && _sz);
230 STACK_GROW(L2, 2); 228 STACK_GROW(L2, 2);
231 // Note: Line numbers seem to be taken precisely from the 229 // Note: Line numbers seem to be taken precisely from the
232 // original function. 'fname' is not used since the chunk 230 // original function. 'fname' is not used since the chunk
@@ -234,12 +232,12 @@ void InterCopyContext::copy_func() const
234 // 232 //
235 // TBD: Can we get the function's original name through, as well? 233 // TBD: Can we get the function's original name through, as well?
236 // 234 //
237 if (luaL_loadbuffer(L2, _s, _sz, fname) != 0) { // L2: ... {cache} ... p function 235 if (luaL_loadbuffer(L2, _bytecode.data(), _bytecode.size(), _fname) != 0) { // L2: ... {cache} ... p function
238 // chunk is precompiled so only LUA_ERRMEM can happen 236 // chunk is precompiled so only LUA_ERRMEM can happen
239 // "Otherwise, it pushes an error message" 237 // "Otherwise, it pushes an error message"
240 // 238 //
241 STACK_GROW(L1, 1); 239 STACK_GROW(L1, 1);
242 raise_luaL_error(getErrL(), "%s: %s", fname, lua_tostring(L2, -1)); 240 raise_luaL_error(getErrL(), "%s: %s", _fname, lua_tostring(L2, -1));
243 } 241 }
244 // remove the dumped string 242 // remove the dumped string
245 lua_pop(L1, 1); // ... 243 lua_pop(L1, 1); // ...
@@ -268,7 +266,7 @@ void InterCopyContext::copy_func() const
268 lua_pushglobaltable(L1); // L1: ... _G 266 lua_pushglobaltable(L1); // L1: ... _G
269#endif // LUA_VERSION_NUM 267#endif // LUA_VERSION_NUM
270 for (_n = 0; (_c.name = lua_getupvalue(L1, L1_i, 1 + _n)) != nullptr; ++_n) { // L1: ... _G up[n] 268 for (_n = 0; (_c.name = lua_getupvalue(L1, L1_i, 1 + _n)) != nullptr; ++_n) { // L1: ... _G up[n]
271 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "UPNAME[%d]: %s -> " INDENT_END(U), n, _c.name)); 269 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "UPNAME[%d]: %s -> " INDENT_END(U), _n, _c.name));
272#if LUA_VERSION_NUM >= 502 270#if LUA_VERSION_NUM >= 502
273 if (lua_rawequal(L1, -1, -2)) { // is the upvalue equal to the global table? 271 if (lua_rawequal(L1, -1, -2)) { // is the upvalue equal to the global table?
274 DEBUGSPEW_CODE(fprintf(stderr, "pushing destination global scope\n")); 272 DEBUGSPEW_CODE(fprintf(stderr, "pushing destination global scope\n"));
@@ -350,7 +348,7 @@ void InterCopyContext::lookup_native_func() const
350 "%s%s: function '%s' not found in %s destination transfer database.", 348 "%s%s: function '%s' not found in %s destination transfer database.",
351 lua_isnil(L2, -1) ? "" : "INTERNAL ERROR IN ", 349 lua_isnil(L2, -1) ? "" : "INTERNAL ERROR IN ",
352 _from ? _from : "main", 350 _from ? _from : "main",
353 _fqn, 351 _fqn.data(),
354 _to ? _to : "main"); 352 _to ? _to : "main");
355 return; 353 return;
356 } 354 }
@@ -499,47 +497,45 @@ void InterCopyContext::inter_copy_keyvaluepair() const
499 // maybe offer this possibility as a global configuration option, or a linda setting, or as a parameter of the call causing the transfer? 497 // maybe offer this possibility as a global configuration option, or a linda setting, or as a parameter of the call causing the transfer?
500 } 498 }
501 499
502 char* valPath{ nullptr }; 500 char* _valPath{ nullptr };
503 if (U->verboseErrors) { 501 if (U->verboseErrors) {
504 // for debug purposes, let's try to build a useful name 502 // for debug purposes, let's try to build a useful name
505 if (lua_type(L1, _key_i) == LUA_TSTRING) { 503 if (lua_type(L1, _key_i) == LUA_TSTRING) {
506 char const* key{ lua_tostring(L1, _key_i) }; 504 std::string_view const _key{ lua_tostringview(L1, _key_i) };
507 size_t const keyRawLen = lua_rawlen(L1, _key_i); 505 size_t const _bufLen{ strlen(name) + _key.size() + 2 }; // +2 for separator dot and terminating 0
508 size_t const bufLen = strlen(name) + keyRawLen + 2; 506 _valPath = static_cast<char*>(alloca(_bufLen));
509 valPath = (char*) alloca(bufLen); 507 sprintf(_valPath, "%s.%*s", name, static_cast<int>(_key.size()), _key.data());
510 sprintf(valPath, "%s.%*s", name, (int) keyRawLen, key);
511 key = nullptr;
512 } 508 }
513#if defined LUA_LNUM || LUA_VERSION_NUM >= 503 509#if defined LUA_LNUM || LUA_VERSION_NUM >= 503
514 else if (lua_isinteger(L1, _key_i)) { 510 else if (lua_isinteger(L1, _key_i)) {
515 lua_Integer const key{ lua_tointeger(L1, _key_i) }; 511 lua_Integer const key{ lua_tointeger(L1, _key_i) };
516 valPath = (char*) alloca(strlen(name) + 32 + 3); 512 _valPath = (char*) alloca(strlen(name) + 32 + 3); // +3 for [] and terminating 0
517 sprintf(valPath, "%s[" LUA_INTEGER_FMT "]", name, key); 513 sprintf(_valPath, "%s[" LUA_INTEGER_FMT "]", name, key);
518 } 514 }
519#endif // defined LUA_LNUM || LUA_VERSION_NUM >= 503 515#endif // defined LUA_LNUM || LUA_VERSION_NUM >= 503
520 else if (lua_type(L1, _key_i) == LUA_TNUMBER) { 516 else if (lua_type(L1, _key_i) == LUA_TNUMBER) {
521 lua_Number const key{ lua_tonumber(L1, _key_i) }; 517 lua_Number const key{ lua_tonumber(L1, _key_i) };
522 valPath = (char*) alloca(strlen(name) + 32 + 3); 518 _valPath = (char*) alloca(strlen(name) + 32 + 3); // +3 for [] and terminating 0
523 sprintf(valPath, "%s[" LUA_NUMBER_FMT "]", name, key); 519 sprintf(_valPath, "%s[" LUA_NUMBER_FMT "]", name, key);
524 } else if (lua_type(L1, _key_i) == LUA_TLIGHTUSERDATA) { 520 } else if (lua_type(L1, _key_i) == LUA_TLIGHTUSERDATA) {
525 void* const key{ lua_touserdata(L1, _key_i) }; 521 void* const key{ lua_touserdata(L1, _key_i) };
526 valPath = (char*) alloca(strlen(name) + 16 + 5); 522 _valPath = (char*) alloca(strlen(name) + 16 + 5); // +5 for [U:] and terminating 0
527 sprintf(valPath, "%s[U:%p]", name, key); 523 sprintf(_valPath, "%s[U:%p]", name, key);
528 } else if (lua_type(L1, _key_i) == LUA_TBOOLEAN) { 524 } else if (lua_type(L1, _key_i) == LUA_TBOOLEAN) {
529 int const key{ lua_toboolean(L1, _key_i) }; 525 int const key{ lua_toboolean(L1, _key_i) };
530 valPath = (char*) alloca(strlen(name) + 8); 526 _valPath = (char*) alloca(strlen(name) + 8); // +8 for [], 'false' and terminating 0
531 sprintf(valPath, "%s[%s]", name, key ? "true" : "false"); 527 sprintf(_valPath, "%s[%s]", name, key ? "true" : "false");
532 } 528 }
533 } 529 }
534 _c.L1_i = SourceIndex{ _val_i }; 530 _c.L1_i = SourceIndex{ _val_i };
535 // Contents of metatables are copied with cache checking. important to detect loops. 531 // Contents of metatables are copied with cache checking. important to detect loops.
536 _c.vt = VT::NORMAL; 532 _c.vt = VT::NORMAL;
537 _c.name = valPath ? valPath : name; 533 _c.name = _valPath ? _valPath : name;
538 if (_c.inter_copy_one()) { 534 if (_c.inter_copy_one()) {
539 LUA_ASSERT(L1, lua_istable(L2, -3)); 535 LUA_ASSERT(L1, lua_istable(L2, -3));
540 lua_rawset(L2, -3); // add to table (pops key & val) 536 lua_rawset(L2, -3); // add to table (pops key & val)
541 } else { 537 } else {
542 raise_luaL_error(getErrL(), "Unable to copy %s entry '%s' because of value is of type '%s'", (vt == VT::NORMAL) ? "table" : "metatable", valPath, luaL_typename(L1, _val_i)); 538 raise_luaL_error(getErrL(), "Unable to copy %s entry '%s' because of value is of type '%s'", (vt == VT::NORMAL) ? "table" : "metatable", _valPath, luaL_typename(L1, _val_i));
543 } 539 }
544} 540}
545 541
@@ -931,10 +927,9 @@ void InterCopyContext::inter_copy_keyvaluepair() const
931 927
932[[nodiscard]] bool InterCopyContext::inter_copy_string() const 928[[nodiscard]] bool InterCopyContext::inter_copy_string() const
933{ 929{
934 size_t _len{ 0 }; 930 std::string_view const _s{ lua_tostringview(L1, L1_i) };
935 char const* const _s{ lua_tolstring(L1, L1_i, &_len) }; 931 DEBUGSPEW_CODE(fprintf(stderr, "'%s'\n", _s.data()));
936 DEBUGSPEW_CODE(fprintf(stderr, "'%s'\n", _s)); 932 lua_pushlstring(L2, _s.data(), _s.size());
937 lua_pushlstring(L2, _s, _len);
938 return true; 933 return true;
939} 934}
940 935