aboutsummaryrefslogtreecommitdiff
path: root/src/tools.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools.c')
-rw-r--r--src/tools.c3308
1 files changed, 1654 insertions, 1654 deletions
diff --git a/src/tools.c b/src/tools.c
index 1436e8d..acb78e6 100644
--- a/src/tools.c
+++ b/src/tools.c
@@ -106,50 +106,50 @@ void push_registry_subtable( lua_State* L, UniqueKey key_)
106#ifdef _DEBUG 106#ifdef _DEBUG
107void luaG_dump( lua_State* L) 107void luaG_dump( lua_State* L)
108{ 108{
109 int top = lua_gettop( L); 109 int top = lua_gettop( L);
110 int i; 110 int i;
111 111
112 fprintf( stderr, "\n\tDEBUG STACK:\n"); 112 fprintf( stderr, "\n\tDEBUG STACK:\n");
113 113
114 if( top == 0) 114 if( top == 0)
115 fprintf( stderr, "\t(none)\n"); 115 fprintf( stderr, "\t(none)\n");
116 116
117 for( i = 1; i <= top; ++ i) 117 for( i = 1; i <= top; ++ i)
118 { 118 {
119 int type = lua_type( L, i); 119 int type = lua_type( L, i);
120 120
121 fprintf( stderr, "\t[%d]= (%s) ", i, lua_typename( L, type)); 121 fprintf( stderr, "\t[%d]= (%s) ", i, lua_typename( L, type));
122 122
123 // Print item contents here... 123 // Print item contents here...
124 // 124 //
125 // Note: this requires 'tostring()' to be defined. If it is NOT, 125 // Note: this requires 'tostring()' to be defined. If it is NOT,
126 // enable it for more debugging. 126 // enable it for more debugging.
127 // 127 //
128 STACK_CHECK( L, 0); 128 STACK_CHECK( L, 0);
129 STACK_GROW( L, 2); 129 STACK_GROW( L, 2);
130 130
131 lua_getglobal( L, "tostring"); 131 lua_getglobal( L, "tostring");
132 // 132 //
133 // [-1]: tostring function, or nil 133 // [-1]: tostring function, or nil
134 134
135 if( !lua_isfunction( L, -1)) 135 if( !lua_isfunction( L, -1))
136 { 136 {
137 fprintf( stderr, "('tostring' not available)"); 137 fprintf( stderr, "('tostring' not available)");
138 } 138 }
139 else 139 else
140 { 140 {
141 lua_pushvalue( L, i); 141 lua_pushvalue( L, i);
142 lua_call( L, 1 /*args*/, 1 /*retvals*/); 142 lua_call( L, 1 /*args*/, 1 /*retvals*/);
143 143
144 // Don't trust the string contents 144 // Don't trust the string contents
145 // 145 //
146 fprintf( stderr, "%s", lua_tostring( L, -1)); 146 fprintf( stderr, "%s", lua_tostring( L, -1));
147 } 147 }
148 lua_pop( L, 1); 148 lua_pop( L, 1);
149 STACK_END( L, 0); 149 STACK_END( L, 0);
150 fprintf( stderr, "\n"); 150 fprintf( stderr, "\n");
151 } 151 }
152 fprintf( stderr, "\n"); 152 fprintf( stderr, "\n");
153} 153}
154#endif // _DEBUG 154#endif // _DEBUG
155 155
@@ -157,79 +157,79 @@ void luaG_dump( lua_State* L)
157 157
158static void* protected_lua_Alloc( void *ud, void *ptr, size_t osize, size_t nsize) 158static void* protected_lua_Alloc( void *ud, void *ptr, size_t osize, size_t nsize)
159{ 159{
160 void* p; 160 void* p;
161 ProtectedAllocator* s = (ProtectedAllocator*) ud; 161 ProtectedAllocator* s = (ProtectedAllocator*) ud;
162 MUTEX_LOCK( &s->lock); 162 MUTEX_LOCK( &s->lock);
163 p = s->definition.allocF( s->definition.allocUD, ptr, osize, nsize); 163 p = s->definition.allocF( s->definition.allocUD, ptr, osize, nsize);
164 MUTEX_UNLOCK( &s->lock); 164 MUTEX_UNLOCK( &s->lock);
165 return p; 165 return p;
166} 166}
167 167
168static int luaG_provide_protected_allocator( lua_State* L) 168static int luaG_provide_protected_allocator( lua_State* L)
169{ 169{
170 Universe* U = universe_get( L); 170 Universe* U = universe_get( L);
171 AllocatorDefinition* def = lua_newuserdatauv( L, sizeof(AllocatorDefinition), 0); 171 AllocatorDefinition* def = lua_newuserdatauv( L, sizeof(AllocatorDefinition), 0);
172 def->allocF = protected_lua_Alloc; 172 def->allocF = protected_lua_Alloc;
173 def->allocUD = &U->protected_allocator; 173 def->allocUD = &U->protected_allocator;
174 return 1; 174 return 1;
175} 175}
176 176
177// Do I need to disable this when compiling for LuaJIT to prevent issues? 177// Do I need to disable this when compiling for LuaJIT to prevent issues?
178void initialize_allocator_function( Universe* U, lua_State* L) 178void initialize_allocator_function( Universe* U, lua_State* L)
179{ 179{
180 STACK_CHECK( L, 0); 180 STACK_CHECK( L, 0);
181 lua_getfield( L, -1, "allocator"); // settings allocator|nil|"protected" 181 lua_getfield( L, -1, "allocator"); // settings allocator|nil|"protected"
182 if( !lua_isnil( L, -1)) 182 if( !lua_isnil( L, -1))
183 { 183 {
184 // store C function pointer in an internal variable 184 // store C function pointer in an internal variable
185 U->provide_allocator = lua_tocfunction( L, -1); // settings allocator 185 U->provide_allocator = lua_tocfunction( L, -1); // settings allocator
186 if( U->provide_allocator != NULL) 186 if( U->provide_allocator != NULL)
187 { 187 {
188 // make sure the function doesn't have upvalues 188 // make sure the function doesn't have upvalues
189 char const* upname = lua_getupvalue( L, -1, 1); // settings allocator upval? 189 char const* upname = lua_getupvalue( L, -1, 1); // settings allocator upval?
190 if( upname != NULL) // should be "" for C functions with upvalues if any 190 if( upname != NULL) // should be "" for C functions with upvalues if any
191 { 191 {
192 (void) luaL_error( L, "config.allocator() shouldn't have upvalues"); 192 (void) luaL_error( L, "config.allocator() shouldn't have upvalues");
193 } 193 }
194 // remove this C function from the config table so that it doesn't cause problems 194 // remove this C function from the config table so that it doesn't cause problems
195 // when we transfer the config table in newly created Lua states 195 // when we transfer the config table in newly created Lua states
196 lua_pushnil( L); // settings allocator nil 196 lua_pushnil( L); // settings allocator nil
197 lua_setfield( L, -3, "allocator"); // settings allocator 197 lua_setfield( L, -3, "allocator"); // settings allocator
198 } 198 }
199 else if( lua_type( L, -1) == LUA_TSTRING) 199 else if( lua_type( L, -1) == LUA_TSTRING)
200 { 200 {
201 // initialize all we need for the protected allocator 201 // initialize all we need for the protected allocator
202 MUTEX_INIT( &U->protected_allocator.lock); // the mutex 202 MUTEX_INIT( &U->protected_allocator.lock); // the mutex
203 // and the original allocator to call from inside protection by the mutex 203 // and the original allocator to call from inside protection by the mutex
204 U->protected_allocator.definition.allocF = lua_getallocf( L, &U->protected_allocator.definition.allocUD); 204 U->protected_allocator.definition.allocF = lua_getallocf( L, &U->protected_allocator.definition.allocUD);
205 // before a state is created, this function will be called to obtain the allocator 205 // before a state is created, this function will be called to obtain the allocator
206 U->provide_allocator = luaG_provide_protected_allocator; 206 U->provide_allocator = luaG_provide_protected_allocator;
207 207
208 lua_setallocf( L, protected_lua_Alloc, &U->protected_allocator); 208 lua_setallocf( L, protected_lua_Alloc, &U->protected_allocator);
209 } 209 }
210 } 210 }
211 lua_pop( L, 1); // settings 211 lua_pop( L, 1); // settings
212 STACK_END( L, 0); 212 STACK_END( L, 0);
213} 213}
214 214
215void cleanup_allocator_function( Universe* U, lua_State* L) 215void cleanup_allocator_function( Universe* U, lua_State* L)
216{ 216{
217 // remove the protected allocator, if any 217 // remove the protected allocator, if any
218 if( U->protected_allocator.definition.allocF != NULL) 218 if( U->protected_allocator.definition.allocF != NULL)
219 { 219 {
220 // install the non-protected allocator 220 // install the non-protected allocator
221 lua_setallocf( L, U->protected_allocator.definition.allocF, U->protected_allocator.definition.allocUD); 221 lua_setallocf( L, U->protected_allocator.definition.allocF, U->protected_allocator.definition.allocUD);
222 // release the mutex 222 // release the mutex
223 MUTEX_FREE( &U->protected_allocator.lock); 223 MUTEX_FREE( &U->protected_allocator.lock);
224 } 224 }
225} 225}
226 226
227// ################################################################################################ 227// ################################################################################################
228 228
229static int dummy_writer( lua_State* L, void const* p, size_t sz, void* ud) 229static int dummy_writer( lua_State* L, void const* p, size_t sz, void* ud)
230{ 230{
231 (void)L; (void)p; (void)sz; (void) ud; // unused 231 (void)L; (void)p; (void)sz; (void) ud; // unused
232 return 666; 232 return 666;
233} 233}
234 234
235 235
@@ -250,42 +250,42 @@ static int dummy_writer( lua_State* L, void const* p, size_t sz, void* ud)
250 250
251typedef enum 251typedef enum
252{ 252{
253 FST_Bytecode, 253 FST_Bytecode,
254 FST_Native, 254 FST_Native,
255 FST_FastJIT 255 FST_FastJIT
256} FuncSubType; 256} FuncSubType;
257 257
258FuncSubType luaG_getfuncsubtype( lua_State *L, int _i) 258FuncSubType luaG_getfuncsubtype( lua_State *L, int _i)
259{ 259{
260 if( lua_tocfunction( L, _i)) 260 if( lua_tocfunction( L, _i))
261 { 261 {
262 return FST_Native; 262 return FST_Native;
263 } 263 }
264 { 264 {
265 int mustpush = 0, dumpres; 265 int mustpush = 0, dumpres;
266 if( lua_absindex( L, _i) != lua_gettop( L)) 266 if( lua_absindex( L, _i) != lua_gettop( L))
267 { 267 {
268 lua_pushvalue( L, _i); 268 lua_pushvalue( L, _i);
269 mustpush = 1; 269 mustpush = 1;
270 } 270 }
271 // the provided writer fails with code 666 271 // the provided writer fails with code 666
272 // therefore, anytime we get 666, this means that lua_dump() attempted a dump 272 // therefore, anytime we get 666, this means that lua_dump() attempted a dump
273 // all other cases mean this is either a C or LuaJIT-fast function 273 // all other cases mean this is either a C or LuaJIT-fast function
274 dumpres = lua504_dump( L, dummy_writer, NULL, 0); 274 dumpres = lua504_dump( L, dummy_writer, NULL, 0);
275 lua_pop( L, mustpush); 275 lua_pop( L, mustpush);
276 if( dumpres == 666) 276 if( dumpres == 666)
277 { 277 {
278 return FST_Bytecode; 278 return FST_Bytecode;
279 } 279 }
280 } 280 }
281 return FST_FastJIT; 281 return FST_FastJIT;
282} 282}
283 283
284static lua_CFunction luaG_tocfunction( lua_State *L, int _i, FuncSubType *_out) 284static lua_CFunction luaG_tocfunction( lua_State *L, int _i, FuncSubType *_out)
285{ 285{
286 lua_CFunction p = lua_tocfunction( L, _i); 286 lua_CFunction p = lua_tocfunction( L, _i);
287 *_out = luaG_getfuncsubtype( L, _i); 287 *_out = luaG_getfuncsubtype( L, _i);
288 return p; 288 return p;
289} 289}
290 290
291// crc64/we of string "LOOKUPCACHE_REGKEY" generated at http://www.nitrxgen.net/hashgen/ 291// crc64/we of string "LOOKUPCACHE_REGKEY" generated at http://www.nitrxgen.net/hashgen/
@@ -294,26 +294,26 @@ static DECLARE_CONST_UNIQUE_KEY( LOOKUPCACHE_REGKEY, 0x837a68dfc6fcb716);
294// inspired from tconcat() in ltablib.c 294// inspired from tconcat() in ltablib.c
295static char const* luaG_pushFQN( lua_State* L, int t, int last, size_t* length) 295static char const* luaG_pushFQN( lua_State* L, int t, int last, size_t* length)
296{ 296{
297 int i = 1; 297 int i = 1;
298 luaL_Buffer b; 298 luaL_Buffer b;
299 STACK_CHECK( L, 0); 299 STACK_CHECK( L, 0);
300 // Lua 5.4 pushes &b as light userdata on the stack. be aware of it... 300 // Lua 5.4 pushes &b as light userdata on the stack. be aware of it...
301 luaL_buffinit( L, &b); // ... {} ... &b? 301 luaL_buffinit( L, &b); // ... {} ... &b?
302 for( ; i < last; ++ i) 302 for( ; i < last; ++ i)
303 { 303 {
304 lua_rawgeti( L, t, i); 304 lua_rawgeti( L, t, i);
305 luaL_addvalue( &b); 305 luaL_addvalue( &b);
306 luaL_addlstring(&b, "/", 1); 306 luaL_addlstring(&b, "/", 1);
307 } 307 }
308 if( i == last) // add last value (if interval was not empty) 308 if( i == last) // add last value (if interval was not empty)
309 { 309 {
310 lua_rawgeti( L, t, i); 310 lua_rawgeti( L, t, i);
311 luaL_addvalue( &b); 311 luaL_addvalue( &b);
312 } 312 }
313 // &b is popped at that point (-> replaced by the result) 313 // &b is popped at that point (-> replaced by the result)
314 luaL_pushresult( &b); // ... {} ... "<result>" 314 luaL_pushresult( &b); // ... {} ... "<result>"
315 STACK_END( L, 1); 315 STACK_END( L, 1);
316 return lua_tolstring( L, -1, length); 316 return lua_tolstring( L, -1, length);
317} 317}
318 318
319/* 319/*
@@ -326,199 +326,199 @@ static char const* luaG_pushFQN( lua_State* L, int t, int last, size_t* length)
326 */ 326 */
327static void update_lookup_entry( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L, int _ctx_base, int _depth) 327static void update_lookup_entry( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L, int _ctx_base, int _depth)
328{ 328{
329 // slot 1 in the stack contains the table that receives everything we found 329 // slot 1 in the stack contains the table that receives everything we found
330 int const dest = _ctx_base; 330 int const dest = _ctx_base;
331 // slot 2 contains a table that, when concatenated, produces the fully qualified name of scanned elements in the table provided at slot _i 331 // slot 2 contains a table that, when concatenated, produces the fully qualified name of scanned elements in the table provided at slot _i
332 int const fqn = _ctx_base + 1; 332 int const fqn = _ctx_base + 1;
333 333
334 size_t prevNameLength, newNameLength; 334 size_t prevNameLength, newNameLength;
335 char const* prevName; 335 char const* prevName;
336 DEBUGSPEW_CODE( char const *newName); 336 DEBUGSPEW_CODE( char const *newName);
337 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "update_lookup_entry()\n" INDENT_END)); 337 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "update_lookup_entry()\n" INDENT_END));
338 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); 338 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth);
339 339
340 STACK_CHECK( L, 0); 340 STACK_CHECK( L, 0);
341 // first, raise an error if the function is already known 341 // first, raise an error if the function is already known
342 lua_pushvalue( L, -1); // ... {bfc} k o o 342 lua_pushvalue( L, -1); // ... {bfc} k o o
343 lua_rawget( L, dest); // ... {bfc} k o name? 343 lua_rawget( L, dest); // ... {bfc} k o name?
344 prevName = lua_tolstring( L, -1, &prevNameLength); // NULL if we got nil (first encounter of this object) 344 prevName = lua_tolstring( L, -1, &prevNameLength); // NULL if we got nil (first encounter of this object)
345 // push name in fqn stack (note that concatenation will crash if name is a not string or a number) 345 // push name in fqn stack (note that concatenation will crash if name is a not string or a number)
346 lua_pushvalue( L, -3); // ... {bfc} k o name? k 346 lua_pushvalue( L, -3); // ... {bfc} k o name? k
347 ASSERT_L( lua_type( L, -1) == LUA_TNUMBER || lua_type( L, -1) == LUA_TSTRING); 347 ASSERT_L( lua_type( L, -1) == LUA_TNUMBER || lua_type( L, -1) == LUA_TSTRING);
348 ++ _depth; 348 ++ _depth;
349 lua_rawseti( L, fqn, _depth); // ... {bfc} k o name? 349 lua_rawseti( L, fqn, _depth); // ... {bfc} k o name?
350 // generate name 350 // generate name
351 DEBUGSPEW_CODE( newName =) luaG_pushFQN( L, fqn, _depth, &newNameLength); // ... {bfc} k o name? "f.q.n" 351 DEBUGSPEW_CODE( newName =) luaG_pushFQN( L, fqn, _depth, &newNameLength); // ... {bfc} k o name? "f.q.n"
352 // Lua 5.2 introduced a hash randomizer seed which causes table iteration to yield a different key order 352 // Lua 5.2 introduced a hash randomizer seed which causes table iteration to yield a different key order
353 // on different VMs even when the tables are populated the exact same way. 353 // on different VMs even when the tables are populated the exact same way.
354 // When Lua is built with compatibility options (such as LUA_COMPAT_ALL), 354 // When Lua is built with compatibility options (such as LUA_COMPAT_ALL),
355 // this causes several base libraries to register functions under multiple names. 355 // this causes several base libraries to register functions under multiple names.
356 // This, with the randomizer, can cause the first generated name of an object to be different on different VMs, 356 // This, with the randomizer, can cause the first generated name of an object to be different on different VMs,
357 // which breaks function transfer. 357 // which breaks function transfer.
358 // Also, nothing prevents any external module from exposing a given object under several names, so... 358 // Also, nothing prevents any external module from exposing a given object under several names, so...
359 // Therefore, when we encounter an object for which a name was previously registered, we need to select the names 359 // Therefore, when we encounter an object for which a name was previously registered, we need to select the names
360 // based on some sorting order so that we end up with the same name in all databases whatever order the table walk yielded 360 // based on some sorting order so that we end up with the same name in all databases whatever order the table walk yielded
361 if( prevName != NULL && (prevNameLength < newNameLength || lua_lessthan( L, -2, -1))) 361 if( prevName != NULL && (prevNameLength < newNameLength || lua_lessthan( L, -2, -1)))
362 { 362 {
363 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%s '%s' remained named '%s'\n" INDENT_END, lua_typename( L, lua_type( L, -3)), newName, prevName)); 363 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%s '%s' remained named '%s'\n" INDENT_END, lua_typename( L, lua_type( L, -3)), newName, prevName));
364 // the previous name is 'smaller' than the one we just generated: keep it! 364 // the previous name is 'smaller' than the one we just generated: keep it!
365 lua_pop( L, 3); // ... {bfc} k 365 lua_pop( L, 3); // ... {bfc} k
366 } 366 }
367 else 367 else
368 { 368 {
369 // the name we generated is either the first one, or a better fit for our purposes 369 // the name we generated is either the first one, or a better fit for our purposes
370 if( prevName) 370 if( prevName)
371 { 371 {
372 // clear the previous name for the database to avoid clutter 372 // clear the previous name for the database to avoid clutter
373 lua_insert( L, -2); // ... {bfc} k o "f.q.n" prevName 373 lua_insert( L, -2); // ... {bfc} k o "f.q.n" prevName
374 // t[prevName] = nil 374 // t[prevName] = nil
375 lua_pushnil( L); // ... {bfc} k o "f.q.n" prevName nil 375 lua_pushnil( L); // ... {bfc} k o "f.q.n" prevName nil
376 lua_rawset( L, dest); // ... {bfc} k o "f.q.n" 376 lua_rawset( L, dest); // ... {bfc} k o "f.q.n"
377 } 377 }
378 else 378 else
379 { 379 {
380 lua_remove( L, -2); // ... {bfc} k o "f.q.n" 380 lua_remove( L, -2); // ... {bfc} k o "f.q.n"
381 } 381 }
382 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%s '%s'\n" INDENT_END, lua_typename( L, lua_type( L, -2)), newName)); 382 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%s '%s'\n" INDENT_END, lua_typename( L, lua_type( L, -2)), newName));
383 // prepare the stack for database feed 383 // prepare the stack for database feed
384 lua_pushvalue( L, -1); // ... {bfc} k o "f.q.n" "f.q.n" 384 lua_pushvalue( L, -1); // ... {bfc} k o "f.q.n" "f.q.n"
385 lua_pushvalue( L, -3); // ... {bfc} k o "f.q.n" "f.q.n" o 385 lua_pushvalue( L, -3); // ... {bfc} k o "f.q.n" "f.q.n" o
386 ASSERT_L( lua_rawequal( L, -1, -4)); 386 ASSERT_L( lua_rawequal( L, -1, -4));
387 ASSERT_L( lua_rawequal( L, -2, -3)); 387 ASSERT_L( lua_rawequal( L, -2, -3));
388 // t["f.q.n"] = o 388 // t["f.q.n"] = o
389 lua_rawset( L, dest); // ... {bfc} k o "f.q.n" 389 lua_rawset( L, dest); // ... {bfc} k o "f.q.n"
390 // t[o] = "f.q.n" 390 // t[o] = "f.q.n"
391 lua_rawset( L, dest); // ... {bfc} k 391 lua_rawset( L, dest); // ... {bfc} k
392 // remove table name from fqn stack 392 // remove table name from fqn stack
393 lua_pushnil( L); // ... {bfc} k nil 393 lua_pushnil( L); // ... {bfc} k nil
394 lua_rawseti( L, fqn, _depth); // ... {bfc} k 394 lua_rawseti( L, fqn, _depth); // ... {bfc} k
395 } 395 }
396 -- _depth; 396 -- _depth;
397 STACK_END( L, -1); 397 STACK_END( L, -1);
398 DEBUGSPEW_CODE( -- U->debugspew_indent_depth); 398 DEBUGSPEW_CODE( -- U->debugspew_indent_depth);
399} 399}
400 400
401static void populate_func_lookup_table_recur( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L, int _ctx_base, int _i, int _depth) 401static void populate_func_lookup_table_recur( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L, int _ctx_base, int _i, int _depth)
402{ 402{
403 lua_Integer visit_count; 403 lua_Integer visit_count;
404 // slot 2 contains a table that, when concatenated, produces the fully qualified name of scanned elements in the table provided at slot _i 404 // slot 2 contains a table that, when concatenated, produces the fully qualified name of scanned elements in the table provided at slot _i
405 int const fqn = _ctx_base + 1; 405 int const fqn = _ctx_base + 1;
406 // slot 3 contains a cache that stores all already visited tables to avoid infinite recursion loops 406 // slot 3 contains a cache that stores all already visited tables to avoid infinite recursion loops
407 int const cache = _ctx_base + 2; 407 int const cache = _ctx_base + 2;
408 // we need to remember subtables to process them after functions encountered at the current depth (breadth-first search) 408 // we need to remember subtables to process them after functions encountered at the current depth (breadth-first search)
409 int const breadth_first_cache = lua_gettop( L) + 1; 409 int const breadth_first_cache = lua_gettop( L) + 1;
410 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "populate_func_lookup_table_recur()\n" INDENT_END)); 410 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "populate_func_lookup_table_recur()\n" INDENT_END));
411 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); 411 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth);
412 412
413 STACK_GROW( L, 6); 413 STACK_GROW( L, 6);
414 // slot _i contains a table where we search for functions (or a full userdata with a metatable) 414 // slot _i contains a table where we search for functions (or a full userdata with a metatable)
415 STACK_CHECK( L, 0); // ... {_i} 415 STACK_CHECK( L, 0); // ... {_i}
416 416
417 // if object is a userdata, replace it by its metatable 417 // if object is a userdata, replace it by its metatable
418 if( lua_type( L, _i) == LUA_TUSERDATA) 418 if( lua_type( L, _i) == LUA_TUSERDATA)
419 { 419 {
420 lua_getmetatable( L, _i); // ... {_i} mt 420 lua_getmetatable( L, _i); // ... {_i} mt
421 lua_replace( L, _i); // ... {_i} 421 lua_replace( L, _i); // ... {_i}
422 } 422 }
423 423
424 // if table is already visited, we are done 424 // if table is already visited, we are done
425 lua_pushvalue( L, _i); // ... {_i} {} 425 lua_pushvalue( L, _i); // ... {_i} {}
426 lua_rawget( L, cache); // ... {_i} nil|n 426 lua_rawget( L, cache); // ... {_i} nil|n
427 visit_count = lua_tointeger( L, -1); // 0 if nil, else n 427 visit_count = lua_tointeger( L, -1); // 0 if nil, else n
428 lua_pop( L, 1); // ... {_i} 428 lua_pop( L, 1); // ... {_i}
429 STACK_MID( L, 0); 429 STACK_MID( L, 0);
430 if( visit_count > 0) 430 if( visit_count > 0)
431 { 431 {
432 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "already visited\n" INDENT_END)); 432 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "already visited\n" INDENT_END));
433 DEBUGSPEW_CODE( -- U->debugspew_indent_depth); 433 DEBUGSPEW_CODE( -- U->debugspew_indent_depth);
434 return; 434 return;
435 } 435 }
436 436
437 // remember we visited this table (1-visit count) 437 // remember we visited this table (1-visit count)
438 lua_pushvalue( L, _i); // ... {_i} {} 438 lua_pushvalue( L, _i); // ... {_i} {}
439 lua_pushinteger( L, visit_count + 1); // ... {_i} {} 1 439 lua_pushinteger( L, visit_count + 1); // ... {_i} {} 1
440 lua_rawset( L, cache); // ... {_i} 440 lua_rawset( L, cache); // ... {_i}
441 STACK_MID( L, 0); 441 STACK_MID( L, 0);
442 442
443 // this table is at breadth_first_cache index 443 // this table is at breadth_first_cache index
444 lua_newtable( L); // ... {_i} {bfc} 444 lua_newtable( L); // ... {_i} {bfc}
445 ASSERT_L( lua_gettop( L) == breadth_first_cache); 445 ASSERT_L( lua_gettop( L) == breadth_first_cache);
446 // iterate over all entries in the processed table 446 // iterate over all entries in the processed table
447 lua_pushnil( L); // ... {_i} {bfc} nil 447 lua_pushnil( L); // ... {_i} {bfc} nil
448 while( lua_next( L, _i) != 0) // ... {_i} {bfc} k v 448 while( lua_next( L, _i) != 0) // ... {_i} {bfc} k v
449 { 449 {
450 // just for debug, not actually needed 450 // just for debug, not actually needed
451 //char const* key = (lua_type( L, -2) == LUA_TSTRING) ? lua_tostring( L, -2) : "not a string"; 451 //char const* key = (lua_type( L, -2) == LUA_TSTRING) ? lua_tostring( L, -2) : "not a string";
452 // subtable: process it recursively 452 // subtable: process it recursively
453 if( lua_istable( L, -1)) // ... {_i} {bfc} k {} 453 if( lua_istable( L, -1)) // ... {_i} {bfc} k {}
454 { 454 {
455 // increment visit count to make sure we will actually scan it at this recursive level 455 // increment visit count to make sure we will actually scan it at this recursive level
456 lua_pushvalue( L, -1); // ... {_i} {bfc} k {} {} 456 lua_pushvalue( L, -1); // ... {_i} {bfc} k {} {}
457 lua_pushvalue( L, -1); // ... {_i} {bfc} k {} {} {} 457 lua_pushvalue( L, -1); // ... {_i} {bfc} k {} {} {}
458 lua_rawget( L, cache); // ... {_i} {bfc} k {} {} n? 458 lua_rawget( L, cache); // ... {_i} {bfc} k {} {} n?
459 visit_count = lua_tointeger( L, -1) + 1; // 1 if we got nil, else n+1 459 visit_count = lua_tointeger( L, -1) + 1; // 1 if we got nil, else n+1
460 lua_pop( L, 1); // ... {_i} {bfc} k {} {} 460 lua_pop( L, 1); // ... {_i} {bfc} k {} {}
461 lua_pushinteger( L, visit_count); // ... {_i} {bfc} k {} {} n 461 lua_pushinteger( L, visit_count); // ... {_i} {bfc} k {} {} n
462 lua_rawset( L, cache); // ... {_i} {bfc} k {} 462 lua_rawset( L, cache); // ... {_i} {bfc} k {}
463 // store the table in the breadth-first cache 463 // store the table in the breadth-first cache
464 lua_pushvalue( L, -2); // ... {_i} {bfc} k {} k 464 lua_pushvalue( L, -2); // ... {_i} {bfc} k {} k
465 lua_pushvalue( L, -2); // ... {_i} {bfc} k {} k {} 465 lua_pushvalue( L, -2); // ... {_i} {bfc} k {} k {}
466 lua_rawset( L, breadth_first_cache); // ... {_i} {bfc} k {} 466 lua_rawset( L, breadth_first_cache); // ... {_i} {bfc} k {}
467 // generate a name, and if we already had one name, keep whichever is the shorter 467 // generate a name, and if we already had one name, keep whichever is the shorter
468 update_lookup_entry( DEBUGSPEW_PARAM_COMMA( U) L, _ctx_base, _depth); // ... {_i} {bfc} k 468 update_lookup_entry( DEBUGSPEW_PARAM_COMMA( U) L, _ctx_base, _depth); // ... {_i} {bfc} k
469 } 469 }
470 else if( lua_isfunction( L, -1) && (luaG_getfuncsubtype( L, -1) != FST_Bytecode)) // ... {_i} {bfc} k func 470 else if( lua_isfunction( L, -1) && (luaG_getfuncsubtype( L, -1) != FST_Bytecode)) // ... {_i} {bfc} k func
471 { 471 {
472 // generate a name, and if we already had one name, keep whichever is the shorter 472 // generate a name, and if we already had one name, keep whichever is the shorter
473 update_lookup_entry( DEBUGSPEW_PARAM_COMMA( U) L, _ctx_base, _depth); // ... {_i} {bfc} k 473 update_lookup_entry( DEBUGSPEW_PARAM_COMMA( U) L, _ctx_base, _depth); // ... {_i} {bfc} k
474 } 474 }
475 else 475 else
476 { 476 {
477 lua_pop( L, 1); // ... {_i} {bfc} k 477 lua_pop( L, 1); // ... {_i} {bfc} k
478 } 478 }
479 STACK_MID( L, 2); 479 STACK_MID( L, 2);
480 } 480 }
481 // now process the tables we encountered at that depth 481 // now process the tables we encountered at that depth
482 ++ _depth; 482 ++ _depth;
483 lua_pushnil( L); // ... {_i} {bfc} nil 483 lua_pushnil( L); // ... {_i} {bfc} nil
484 while( lua_next( L, breadth_first_cache) != 0) // ... {_i} {bfc} k {} 484 while( lua_next( L, breadth_first_cache) != 0) // ... {_i} {bfc} k {}
485 { 485 {
486 DEBUGSPEW_CODE( char const* key = (lua_type( L, -2) == LUA_TSTRING) ? lua_tostring( L, -2) : "not a string"); 486 DEBUGSPEW_CODE( char const* key = (lua_type( L, -2) == LUA_TSTRING) ? lua_tostring( L, -2) : "not a string");
487 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "table '%s'\n" INDENT_END, key)); 487 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "table '%s'\n" INDENT_END, key));
488 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); 488 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth);
489 // un-visit this table in case we do need to process it 489 // un-visit this table in case we do need to process it
490 lua_pushvalue( L, -1); // ... {_i} {bfc} k {} {} 490 lua_pushvalue( L, -1); // ... {_i} {bfc} k {} {}
491 lua_rawget( L, cache); // ... {_i} {bfc} k {} n 491 lua_rawget( L, cache); // ... {_i} {bfc} k {} n
492 ASSERT_L( lua_type( L, -1) == LUA_TNUMBER); 492 ASSERT_L( lua_type( L, -1) == LUA_TNUMBER);
493 visit_count = lua_tointeger( L, -1) - 1; 493 visit_count = lua_tointeger( L, -1) - 1;
494 lua_pop( L, 1); // ... {_i} {bfc} k {} 494 lua_pop( L, 1); // ... {_i} {bfc} k {}
495 lua_pushvalue( L, -1); // ... {_i} {bfc} k {} {} 495 lua_pushvalue( L, -1); // ... {_i} {bfc} k {} {}
496 if( visit_count > 0) 496 if( visit_count > 0)
497 { 497 {
498 lua_pushinteger( L, visit_count); // ... {_i} {bfc} k {} {} n 498 lua_pushinteger( L, visit_count); // ... {_i} {bfc} k {} {} n
499 } 499 }
500 else 500 else
501 { 501 {
502 lua_pushnil( L); // ... {_i} {bfc} k {} {} nil 502 lua_pushnil( L); // ... {_i} {bfc} k {} {} nil
503 } 503 }
504 lua_rawset( L, cache); // ... {_i} {bfc} k {} 504 lua_rawset( L, cache); // ... {_i} {bfc} k {}
505 // push table name in fqn stack (note that concatenation will crash if name is a not string!) 505 // push table name in fqn stack (note that concatenation will crash if name is a not string!)
506 lua_pushvalue( L, -2); // ... {_i} {bfc} k {} k 506 lua_pushvalue( L, -2); // ... {_i} {bfc} k {} k
507 lua_rawseti( L, fqn, _depth); // ... {_i} {bfc} k {} 507 lua_rawseti( L, fqn, _depth); // ... {_i} {bfc} k {}
508 populate_func_lookup_table_recur( DEBUGSPEW_PARAM_COMMA( U) L, _ctx_base, lua_gettop( L), _depth); 508 populate_func_lookup_table_recur( DEBUGSPEW_PARAM_COMMA( U) L, _ctx_base, lua_gettop( L), _depth);
509 lua_pop( L, 1); // ... {_i} {bfc} k 509 lua_pop( L, 1); // ... {_i} {bfc} k
510 STACK_MID( L, 2); 510 STACK_MID( L, 2);
511 DEBUGSPEW_CODE( -- U->debugspew_indent_depth); 511 DEBUGSPEW_CODE( -- U->debugspew_indent_depth);
512 } 512 }
513 // remove table name from fqn stack 513 // remove table name from fqn stack
514 lua_pushnil( L); // ... {_i} {bfc} nil 514 lua_pushnil( L); // ... {_i} {bfc} nil
515 lua_rawseti( L, fqn, _depth); // ... {_i} {bfc} 515 lua_rawseti( L, fqn, _depth); // ... {_i} {bfc}
516 -- _depth; 516 -- _depth;
517 // we are done with our cache 517 // we are done with our cache
518 lua_pop( L, 1); // ... {_i} 518 lua_pop( L, 1); // ... {_i}
519 STACK_END( L, 0); 519 STACK_END( L, 0);
520 // we are done // ... {_i} {bfc} 520 // we are done // ... {_i} {bfc}
521 DEBUGSPEW_CODE( -- U->debugspew_indent_depth); 521 DEBUGSPEW_CODE( -- U->debugspew_indent_depth);
522} 522}
523 523
524/* 524/*
@@ -526,63 +526,63 @@ static void populate_func_lookup_table_recur( DEBUGSPEW_PARAM_COMMA( Universe* U
526 */ 526 */
527void populate_func_lookup_table( lua_State* L, int _i, char const* name_) 527void populate_func_lookup_table( lua_State* L, int _i, char const* name_)
528{ 528{
529 int const ctx_base = lua_gettop( L) + 1; 529 int const ctx_base = lua_gettop( L) + 1;
530 int const in_base = lua_absindex( L, _i); 530 int const in_base = lua_absindex( L, _i);
531 int start_depth = 0; 531 int start_depth = 0;
532 DEBUGSPEW_CODE( Universe* U = universe_get( L)); 532 DEBUGSPEW_CODE( Universe* U = universe_get( L));
533 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: populate_func_lookup_table('%s')\n" INDENT_END, L, name_ ? name_ : "NULL")); 533 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: populate_func_lookup_table('%s')\n" INDENT_END, L, name_ ? name_ : "NULL"));
534 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); 534 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth);
535 STACK_GROW( L, 3); 535 STACK_GROW( L, 3);
536 STACK_CHECK( L, 0); 536 STACK_CHECK( L, 0);
537 REGISTRY_GET( L, LOOKUP_REGKEY); // {} 537 REGISTRY_GET( L, LOOKUP_REGKEY); // {}
538 STACK_MID( L, 1); 538 STACK_MID( L, 1);
539 ASSERT_L( lua_istable( L, -1)); 539 ASSERT_L( lua_istable( L, -1));
540 if( lua_type( L, in_base) == LUA_TFUNCTION) // for example when a module is a simple function 540 if( lua_type( L, in_base) == LUA_TFUNCTION) // for example when a module is a simple function
541 { 541 {
542 name_ = name_ ? name_ : "NULL"; 542 name_ = name_ ? name_ : "NULL";
543 lua_pushvalue( L, in_base); // {} f 543 lua_pushvalue( L, in_base); // {} f
544 lua_pushstring( L, name_); // {} f _name 544 lua_pushstring( L, name_); // {} f _name
545 lua_rawset( L, -3); // {} 545 lua_rawset( L, -3); // {}
546 lua_pushstring( L, name_); // {} _name 546 lua_pushstring( L, name_); // {} _name
547 lua_pushvalue( L, in_base); // {} _name f 547 lua_pushvalue( L, in_base); // {} _name f
548 lua_rawset( L, -3); // {} 548 lua_rawset( L, -3); // {}
549 lua_pop( L, 1); // 549 lua_pop( L, 1); //
550 } 550 }
551 else if( lua_type( L, in_base) == LUA_TTABLE) 551 else if( lua_type( L, in_base) == LUA_TTABLE)
552 { 552 {
553 lua_newtable( L); // {} {fqn} 553 lua_newtable( L); // {} {fqn}
554 if( name_) 554 if( name_)
555 { 555 {
556 STACK_MID( L, 2); 556 STACK_MID( L, 2);
557 lua_pushstring( L, name_); // {} {fqn} "name" 557 lua_pushstring( L, name_); // {} {fqn} "name"
558 // generate a name, and if we already had one name, keep whichever is the shorter 558 // generate a name, and if we already had one name, keep whichever is the shorter
559 lua_pushvalue( L, in_base); // {} {fqn} "name" t 559 lua_pushvalue( L, in_base); // {} {fqn} "name" t
560 update_lookup_entry( DEBUGSPEW_PARAM_COMMA( U) L, ctx_base, start_depth); // {} {fqn} "name" 560 update_lookup_entry( DEBUGSPEW_PARAM_COMMA( U) L, ctx_base, start_depth); // {} {fqn} "name"
561 // don't forget to store the name at the bottom of the fqn stack 561 // don't forget to store the name at the bottom of the fqn stack
562 ++ start_depth; 562 ++ start_depth;
563 lua_rawseti( L, -2, start_depth); // {} {fqn} 563 lua_rawseti( L, -2, start_depth); // {} {fqn}
564 STACK_MID( L, 2); 564 STACK_MID( L, 2);
565 } 565 }
566 // retrieve the cache, create it if we haven't done it yet 566 // retrieve the cache, create it if we haven't done it yet
567 REGISTRY_GET( L, LOOKUPCACHE_REGKEY); // {} {fqn} {cache}? 567 REGISTRY_GET( L, LOOKUPCACHE_REGKEY); // {} {fqn} {cache}?
568 if( lua_isnil( L, -1)) 568 if( lua_isnil( L, -1))
569 { 569 {
570 lua_pop( L, 1); // {} {fqn} 570 lua_pop( L, 1); // {} {fqn}
571 lua_newtable( L); // {} {fqn} {cache} 571 lua_newtable( L); // {} {fqn} {cache}
572 REGISTRY_SET( L, LOOKUPCACHE_REGKEY, lua_pushvalue( L, -2)); 572 REGISTRY_SET( L, LOOKUPCACHE_REGKEY, lua_pushvalue( L, -2));
573 STACK_MID( L, 3); 573 STACK_MID( L, 3);
574 } 574 }
575 // process everything we find in that table, filling in lookup data for all functions and tables we see there 575 // process everything we find in that table, filling in lookup data for all functions and tables we see there
576 populate_func_lookup_table_recur( DEBUGSPEW_PARAM_COMMA( U) L, ctx_base, in_base, start_depth); 576 populate_func_lookup_table_recur( DEBUGSPEW_PARAM_COMMA( U) L, ctx_base, in_base, start_depth);
577 lua_pop( L, 3); 577 lua_pop( L, 3);
578 } 578 }
579 else 579 else
580 { 580 {
581 lua_pop( L, 1); // 581 lua_pop( L, 1); //
582 (void) luaL_error( L, "unsupported module type %s", lua_typename( L, lua_type( L, in_base))); 582 (void) luaL_error( L, "unsupported module type %s", lua_typename( L, lua_type( L, in_base)));
583 } 583 }
584 STACK_END( L, 0); 584 STACK_END( L, 0);
585 DEBUGSPEW_CODE( -- U->debugspew_indent_depth); 585 DEBUGSPEW_CODE( -- U->debugspew_indent_depth);
586} 586}
587 587
588/*---=== Inter-state copying ===---*/ 588/*---=== Inter-state copying ===---*/
@@ -595,61 +595,61 @@ static DECLARE_CONST_UNIQUE_KEY( REG_MTID, 0x2e68f9b4751584dc);
595*/ 595*/
596static lua_Integer get_mt_id( Universe* U, lua_State* L, int i) 596static lua_Integer get_mt_id( Universe* U, lua_State* L, int i)
597{ 597{
598 lua_Integer id; 598 lua_Integer id;
599 599
600 i = lua_absindex( L, i); 600 i = lua_absindex( L, i);
601 601
602 STACK_GROW( L, 3); 602 STACK_GROW( L, 3);
603 603
604 STACK_CHECK( L, 0); 604 STACK_CHECK( L, 0);
605 push_registry_subtable( L, REG_MTID); // ... _R[REG_MTID] 605 push_registry_subtable( L, REG_MTID); // ... _R[REG_MTID]
606 lua_pushvalue( L, i); // ... _R[REG_MTID] {mt} 606 lua_pushvalue( L, i); // ... _R[REG_MTID] {mt}
607 lua_rawget( L, -2); // ... _R[REG_MTID] mtk? 607 lua_rawget( L, -2); // ... _R[REG_MTID] mtk?
608 608
609 id = lua_tointeger( L, -1); // 0 for nil 609 id = lua_tointeger( L, -1); // 0 for nil
610 lua_pop( L, 1); // ... _R[REG_MTID] 610 lua_pop( L, 1); // ... _R[REG_MTID]
611 STACK_MID( L, 1); 611 STACK_MID( L, 1);
612
613 if( id == 0)
614 {
615 MUTEX_LOCK( &U->mtid_lock);
616 id = ++ U->last_mt_id;
617 MUTEX_UNLOCK( &U->mtid_lock);
618
619 /* Create two-way references: id_uint <-> table
620 */
621 lua_pushvalue( L, i); // ... _R[REG_MTID] {mt}
622 lua_pushinteger( L, id); // ... _R[REG_MTID] {mt} id
623 lua_rawset( L, -3); // ... _R[REG_MTID]
624 612
625 lua_pushinteger( L, id); // ... _R[REG_MTID] id 613 if( id == 0)
626 lua_pushvalue( L, i); // ... _R[REG_MTID] id {mt} 614 {
627 lua_rawset( L, -3); // ... _R[REG_MTID] 615 MUTEX_LOCK( &U->mtid_lock);
628 } 616 id = ++ U->last_mt_id;
629 lua_pop( L, 1); // ... 617 MUTEX_UNLOCK( &U->mtid_lock);
618
619 /* Create two-way references: id_uint <-> table
620 */
621 lua_pushvalue( L, i); // ... _R[REG_MTID] {mt}
622 lua_pushinteger( L, id); // ... _R[REG_MTID] {mt} id
623 lua_rawset( L, -3); // ... _R[REG_MTID]
624
625 lua_pushinteger( L, id); // ... _R[REG_MTID] id
626 lua_pushvalue( L, i); // ... _R[REG_MTID] id {mt}
627 lua_rawset( L, -3); // ... _R[REG_MTID]
628 }
629 lua_pop( L, 1); // ...
630 630
631 STACK_END( L, 0); 631 STACK_END( L, 0);
632 632
633 return id; 633 return id;
634} 634}
635 635
636// function sentinel used to transfer native functions from/to keeper states 636// function sentinel used to transfer native functions from/to keeper states
637static int func_lookup_sentinel( lua_State* L) 637static int func_lookup_sentinel( lua_State* L)
638{ 638{
639 return luaL_error( L, "function lookup sentinel for %s, should never be called", lua_tostring( L, lua_upvalueindex( 1))); 639 return luaL_error( L, "function lookup sentinel for %s, should never be called", lua_tostring( L, lua_upvalueindex( 1)));
640} 640}
641 641
642 642
643// function sentinel used to transfer native table from/to keeper states 643// function sentinel used to transfer native table from/to keeper states
644static int table_lookup_sentinel( lua_State* L) 644static int table_lookup_sentinel( lua_State* L)
645{ 645{
646 return luaL_error( L, "table lookup sentinel for %s, should never be called", lua_tostring( L, lua_upvalueindex( 1))); 646 return luaL_error( L, "table lookup sentinel for %s, should never be called", lua_tostring( L, lua_upvalueindex( 1)));
647} 647}
648 648
649// function sentinel used to transfer cloned full userdata from/to keeper states 649// function sentinel used to transfer cloned full userdata from/to keeper states
650static int userdata_clone_sentinel( lua_State* L) 650static int userdata_clone_sentinel( lua_State* L)
651{ 651{
652 return luaL_error( L, "userdata clone sentinel for %s, should never be called", lua_tostring( L, lua_upvalueindex( 1))); 652 return luaL_error( L, "userdata clone sentinel for %s, should never be called", lua_tostring( L, lua_upvalueindex( 1)));
653} 653}
654 654
655/* 655/*
@@ -657,70 +657,70 @@ static int userdata_clone_sentinel( lua_State* L)
657 */ 657 */
658static char const* find_lookup_name( lua_State* L, uint_t i, LookupMode mode_, char const* upName_, size_t* len_) 658static char const* find_lookup_name( lua_State* L, uint_t i, LookupMode mode_, char const* upName_, size_t* len_)
659{ 659{
660 DEBUGSPEW_CODE( Universe* const U = universe_get( L)); 660 DEBUGSPEW_CODE( Universe* const U = universe_get( L));
661 char const* fqn; 661 char const* fqn;
662 ASSERT_L( lua_isfunction( L, i) || lua_istable( L, i)); // ... v ... 662 ASSERT_L( lua_isfunction( L, i) || lua_istable( L, i)); // ... v ...
663 STACK_CHECK( L, 0); 663 STACK_CHECK( L, 0);
664 STACK_GROW( L, 3); // up to 3 slots are necessary on error 664 STACK_GROW( L, 3); // up to 3 slots are necessary on error
665 if( mode_ == eLM_FromKeeper) 665 if( mode_ == eLM_FromKeeper)
666 { 666 {
667 lua_CFunction f = lua_tocfunction( L, i); // should *always* be func_lookup_sentinel or table_lookup_sentinel! 667 lua_CFunction f = lua_tocfunction( L, i); // should *always* be func_lookup_sentinel or table_lookup_sentinel!
668 if( f == func_lookup_sentinel || f == table_lookup_sentinel || f == userdata_clone_sentinel) 668 if( f == func_lookup_sentinel || f == table_lookup_sentinel || f == userdata_clone_sentinel)
669 { 669 {
670 lua_getupvalue( L, i, 1); // ... v ... "f.q.n" 670 lua_getupvalue( L, i, 1); // ... v ... "f.q.n"
671 } 671 }
672 else 672 else
673 { 673 {
674 // if this is not a sentinel, this is some user-created table we wanted to lookup 674 // if this is not a sentinel, this is some user-created table we wanted to lookup
675 ASSERT_L( NULL == f && lua_istable( L, i)); 675 ASSERT_L( NULL == f && lua_istable( L, i));
676 // push anything that will convert to NULL string 676 // push anything that will convert to NULL string
677 lua_pushnil( L); // ... v ... nil 677 lua_pushnil( L); // ... v ... nil
678 } 678 }
679 } 679 }
680 else 680 else
681 { 681 {
682 // fetch the name from the source state's lookup table 682 // fetch the name from the source state's lookup table
683 REGISTRY_GET( L, LOOKUP_REGKEY); // ... v ... {} 683 REGISTRY_GET( L, LOOKUP_REGKEY); // ... v ... {}
684 STACK_MID( L, 1); 684 STACK_MID( L, 1);
685 ASSERT_L( lua_istable( L, -1)); 685 ASSERT_L( lua_istable( L, -1));
686 lua_pushvalue( L, i); // ... v ... {} v 686 lua_pushvalue( L, i); // ... v ... {} v
687 lua_rawget( L, -2); // ... v ... {} "f.q.n" 687 lua_rawget( L, -2); // ... v ... {} "f.q.n"
688 } 688 }
689 fqn = lua_tolstring( L, -1, len_); 689 fqn = lua_tolstring( L, -1, len_);
690 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "function [C] %s \n" INDENT_END, fqn)); 690 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "function [C] %s \n" INDENT_END, fqn));
691 // popping doesn't invalidate the pointer since this is an interned string gotten from the lookup database 691 // popping doesn't invalidate the pointer since this is an interned string gotten from the lookup database
692 lua_pop( L, (mode_ == eLM_FromKeeper) ? 1 : 2); // ... v ... 692 lua_pop( L, (mode_ == eLM_FromKeeper) ? 1 : 2); // ... v ...
693 STACK_MID( L, 0); 693 STACK_MID( L, 0);
694 if( NULL == fqn && !lua_istable( L, i)) // raise an error if we try to send an unknown function (but not for tables) 694 if( NULL == fqn && !lua_istable( L, i)) // raise an error if we try to send an unknown function (but not for tables)
695 { 695 {
696 char const *from, *typewhat, *what, *gotchaA, *gotchaB; 696 char const *from, *typewhat, *what, *gotchaA, *gotchaB;
697 // try to discover the name of the function we want to send 697 // try to discover the name of the function we want to send
698 lua_getglobal( L, "decoda_name"); // ... v ... decoda_name 698 lua_getglobal( L, "decoda_name"); // ... v ... decoda_name
699 from = lua_tostring( L, -1); 699 from = lua_tostring( L, -1);
700 lua_pushcfunction( L, luaG_nameof); // ... v ... decoda_name luaG_nameof 700 lua_pushcfunction( L, luaG_nameof); // ... v ... decoda_name luaG_nameof
701 lua_pushvalue( L, i); // ... v ... decoda_name luaG_nameof t 701 lua_pushvalue( L, i); // ... v ... decoda_name luaG_nameof t
702 lua_call( L, 1, 2); // ... v ... decoda_name "type" "name"|nil 702 lua_call( L, 1, 2); // ... v ... decoda_name "type" "name"|nil
703 typewhat = (lua_type( L, -2) == LUA_TSTRING) ? lua_tostring( L, -2) : luaL_typename( L, -2); 703 typewhat = (lua_type( L, -2) == LUA_TSTRING) ? lua_tostring( L, -2) : luaL_typename( L, -2);
704 // second return value can be nil if the table was not found 704 // second return value can be nil if the table was not found
705 // probable reason: the function was removed from the source Lua state before Lanes was required. 705 // probable reason: the function was removed from the source Lua state before Lanes was required.
706 if( lua_isnil( L, -1)) 706 if( lua_isnil( L, -1))
707 { 707 {
708 gotchaA = " referenced by"; 708 gotchaA = " referenced by";
709 gotchaB = "\n(did you remove it from the source Lua state before requiring Lanes?)"; 709 gotchaB = "\n(did you remove it from the source Lua state before requiring Lanes?)";
710 what = upName_; 710 what = upName_;
711 } 711 }
712 else 712 else
713 { 713 {
714 gotchaA = ""; 714 gotchaA = "";
715 gotchaB = ""; 715 gotchaB = "";
716 what = (lua_type( L, -1) == LUA_TSTRING) ? lua_tostring( L, -1) : luaL_typename( L, -1); 716 what = (lua_type( L, -1) == LUA_TSTRING) ? lua_tostring( L, -1) : luaL_typename( L, -1);
717 } 717 }
718 (void) luaL_error( L, "%s%s '%s' not found in %s origin transfer database.%s", typewhat, gotchaA, what, from ? from : "main", gotchaB); 718 (void) luaL_error( L, "%s%s '%s' not found in %s origin transfer database.%s", typewhat, gotchaA, what, from ? from : "main", gotchaB);
719 *len_ = 0; 719 *len_ = 0;
720 return NULL; 720 return NULL;
721 } 721 }
722 STACK_END( L, 0); 722 STACK_END( L, 0);
723 return fqn; 723 return fqn;
724} 724}
725 725
726 726
@@ -729,67 +729,67 @@ static char const* find_lookup_name( lua_State* L, uint_t i, LookupMode mode_, c
729 */ 729 */
730static bool_t lookup_table( lua_State* L2, lua_State* L, uint_t i, LookupMode mode_, char const* upName_) 730static bool_t lookup_table( lua_State* L2, lua_State* L, uint_t i, LookupMode mode_, char const* upName_)
731{ 731{
732 // get the name of the table we want to send 732 // get the name of the table we want to send
733 size_t len; 733 size_t len;
734 char const* fqn = find_lookup_name( L, i, mode_, upName_, &len); 734 char const* fqn = find_lookup_name( L, i, mode_, upName_, &len);
735 if( NULL == fqn) // name not found, it is some user-created table 735 if( NULL == fqn) // name not found, it is some user-created table
736 { 736 {
737 return FALSE; 737 return FALSE;
738 } 738 }
739 // push the equivalent table in the destination's stack, retrieved from the lookup table 739 // push the equivalent table in the destination's stack, retrieved from the lookup table
740 STACK_CHECK( L2, 0); // L // L2 740 STACK_CHECK( L2, 0); // L // L2
741 STACK_GROW( L2, 3); // up to 3 slots are necessary on error 741 STACK_GROW( L2, 3); // up to 3 slots are necessary on error
742 switch( mode_) 742 switch( mode_)
743 { 743 {
744 default: // shouldn't happen, in theory... 744 default: // shouldn't happen, in theory...
745 (void) luaL_error( L, "internal error: unknown lookup mode"); 745 (void) luaL_error( L, "internal error: unknown lookup mode");
746 return FALSE; 746 return FALSE;
747 747
748 case eLM_ToKeeper: 748 case eLM_ToKeeper:
749 // push a sentinel closure that holds the lookup name as upvalue 749 // push a sentinel closure that holds the lookup name as upvalue
750 lua_pushlstring( L2, fqn, len); // "f.q.n" 750 lua_pushlstring( L2, fqn, len); // "f.q.n"
751 lua_pushcclosure( L2, table_lookup_sentinel, 1); // f 751 lua_pushcclosure( L2, table_lookup_sentinel, 1); // f
752 break; 752 break;
753 753
754 case eLM_LaneBody: 754 case eLM_LaneBody:
755 case eLM_FromKeeper: 755 case eLM_FromKeeper:
756 REGISTRY_GET( L2, LOOKUP_REGKEY); // {} 756 REGISTRY_GET( L2, LOOKUP_REGKEY); // {}
757 STACK_MID( L2, 1); 757 STACK_MID( L2, 1);
758 ASSERT_L( lua_istable( L2, -1)); 758 ASSERT_L( lua_istable( L2, -1));
759 lua_pushlstring( L2, fqn, len); // {} "f.q.n" 759 lua_pushlstring( L2, fqn, len); // {} "f.q.n"
760 lua_rawget( L2, -2); // {} t 760 lua_rawget( L2, -2); // {} t
761 // we accept destination lookup failures in the case of transfering the Lanes body function (this will result in the source table being cloned instead) 761 // we accept destination lookup failures in the case of transfering the Lanes body function (this will result in the source table being cloned instead)
762 // but not when we extract something out of a keeper, as there is nothing to clone! 762 // but not when we extract something out of a keeper, as there is nothing to clone!
763 if( lua_isnil( L2, -1) && mode_ == eLM_LaneBody) 763 if( lua_isnil( L2, -1) && mode_ == eLM_LaneBody)
764 { 764 {
765 lua_pop( L2, 2); // 765 lua_pop( L2, 2); //
766 STACK_MID( L2, 0); 766 STACK_MID( L2, 0);
767 return FALSE; 767 return FALSE;
768 } 768 }
769 else if( !lua_istable( L2, -1)) 769 else if( !lua_istable( L2, -1))
770 { 770 {
771 char const* from, *to; 771 char const* from, *to;
772 lua_getglobal( L, "decoda_name"); // ... t ... decoda_name 772 lua_getglobal( L, "decoda_name"); // ... t ... decoda_name
773 from = lua_tostring( L, -1); 773 from = lua_tostring( L, -1);
774 lua_pop( L, 1); // ... t ... 774 lua_pop( L, 1); // ... t ...
775 lua_getglobal( L2, "decoda_name"); // {} t decoda_name 775 lua_getglobal( L2, "decoda_name"); // {} t decoda_name
776 to = lua_tostring( L2, -1); 776 to = lua_tostring( L2, -1);
777 lua_pop( L2, 1); // {} t 777 lua_pop( L2, 1); // {} t
778 // when mode_ == eLM_FromKeeper, L is a keeper state and L2 is not, therefore L2 is the state where we want to raise the error 778 // when mode_ == eLM_FromKeeper, L is a keeper state and L2 is not, therefore L2 is the state where we want to raise the error
779 (void) luaL_error( 779 (void) luaL_error(
780 (mode_ == eLM_FromKeeper) ? L2 : L 780 (mode_ == eLM_FromKeeper) ? L2 : L
781 , "INTERNAL ERROR IN %s: table '%s' not found in %s destination transfer database." 781 , "INTERNAL ERROR IN %s: table '%s' not found in %s destination transfer database."
782 , from ? from : "main" 782 , from ? from : "main"
783 , fqn 783 , fqn
784 , to ? to : "main" 784 , to ? to : "main"
785 ); 785 );
786 return FALSE; 786 return FALSE;
787 } 787 }
788 lua_remove( L2, -2); // t 788 lua_remove( L2, -2); // t
789 break; 789 break;
790 } 790 }
791 STACK_END( L2, 1); 791 STACK_END( L2, 1);
792 return TRUE; 792 return TRUE;
793} 793}
794 794
795 795
@@ -805,33 +805,33 @@ static bool_t lookup_table( lua_State* L2, lua_State* L, uint_t i, LookupMode mo
805 */ 805 */
806static bool_t push_cached_table( lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i) 806static bool_t push_cached_table( lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i)
807{ 807{
808 bool_t not_found_in_cache; // L2 808 bool_t not_found_in_cache; // L2
809 DECLARE_CONST_UNIQUE_KEY( p, lua_topointer( L, i)); 809 DECLARE_CONST_UNIQUE_KEY( p, lua_topointer( L, i));
810 810
811 ASSERT_L( L2_cache_i != 0); 811 ASSERT_L( L2_cache_i != 0);
812 STACK_GROW( L2, 3); 812 STACK_GROW( L2, 3);
813 STACK_CHECK( L2, 0); 813 STACK_CHECK( L2, 0);
814 814
815 // We don't need to use the from state ('L') in ID since the life span 815 // We don't need to use the from state ('L') in ID since the life span
816 // is only for the duration of a copy (both states are locked). 816 // is only for the duration of a copy (both states are locked).
817 // push a light userdata uniquely representing the table 817 // push a light userdata uniquely representing the table
818 push_unique_key( L2, p); // ... p 818 push_unique_key( L2, p); // ... p
819 819
820 //fprintf( stderr, "<< ID: %s >>\n", lua_tostring( L2, -1)); 820 //fprintf( stderr, "<< ID: %s >>\n", lua_tostring( L2, -1));
821 821
822 lua_rawget( L2, L2_cache_i); // ... {cached|nil} 822 lua_rawget( L2, L2_cache_i); // ... {cached|nil}
823 not_found_in_cache = lua_isnil( L2, -1); 823 not_found_in_cache = lua_isnil( L2, -1);
824 if( not_found_in_cache) 824 if( not_found_in_cache)
825 { 825 {
826 lua_pop( L2, 1); // ... 826 lua_pop( L2, 1); // ...
827 lua_newtable( L2); // ... {} 827 lua_newtable( L2); // ... {}
828 push_unique_key( L2, p); // ... {} p 828 push_unique_key( L2, p); // ... {} p
829 lua_pushvalue( L2, -2); // ... {} p {} 829 lua_pushvalue( L2, -2); // ... {} p {}
830 lua_rawset( L2, L2_cache_i); // ... {} 830 lua_rawset( L2, L2_cache_i); // ... {}
831 } 831 }
832 STACK_END( L2, 1); 832 STACK_END( L2, 1);
833 ASSERT_L( lua_istable( L2, -1)); 833 ASSERT_L( lua_istable( L2, -1));
834 return !not_found_in_cache; 834 return !not_found_in_cache;
835} 835}
836 836
837 837
@@ -840,144 +840,144 @@ static bool_t push_cached_table( lua_State* L2, uint_t L2_cache_i, lua_State* L,
840 */ 840 */
841static int discover_object_name_recur( lua_State* L, int shortest_, int depth_) 841static int discover_object_name_recur( lua_State* L, int shortest_, int depth_)
842{ 842{
843 int const what = 1; // o "r" {c} {fqn} ... {?} 843 int const what = 1; // o "r" {c} {fqn} ... {?}
844 int const result = 2; 844 int const result = 2;
845 int const cache = 3; 845 int const cache = 3;
846 int const fqn = 4; 846 int const fqn = 4;
847 // no need to scan this table if the name we will discover is longer than one we already know 847 // no need to scan this table if the name we will discover is longer than one we already know
848 if( shortest_ <= depth_ + 1) 848 if( shortest_ <= depth_ + 1)
849 { 849 {
850 return shortest_; 850 return shortest_;
851 } 851 }
852 STACK_GROW( L, 3); 852 STACK_GROW( L, 3);
853 STACK_CHECK( L, 0); 853 STACK_CHECK( L, 0);
854 // stack top contains the table to search in 854 // stack top contains the table to search in
855 lua_pushvalue( L, -1); // o "r" {c} {fqn} ... {?} {?} 855 lua_pushvalue( L, -1); // o "r" {c} {fqn} ... {?} {?}
856 lua_rawget( L, cache); // o "r" {c} {fqn} ... {?} nil/1 856 lua_rawget( L, cache); // o "r" {c} {fqn} ... {?} nil/1
857 // if table is already visited, we are done 857 // if table is already visited, we are done
858 if( !lua_isnil( L, -1)) 858 if( !lua_isnil( L, -1))
859 { 859 {
860 lua_pop( L, 1); // o "r" {c} {fqn} ... {?} 860 lua_pop( L, 1); // o "r" {c} {fqn} ... {?}
861 return shortest_; 861 return shortest_;
862 } 862 }
863 // examined table is not in the cache, add it now 863 // examined table is not in the cache, add it now
864 lua_pop( L, 1); // o "r" {c} {fqn} ... {?} 864 lua_pop( L, 1); // o "r" {c} {fqn} ... {?}
865 lua_pushvalue( L, -1); // o "r" {c} {fqn} ... {?} {?} 865 lua_pushvalue( L, -1); // o "r" {c} {fqn} ... {?} {?}
866 lua_pushinteger( L, 1); // o "r" {c} {fqn} ... {?} {?} 1 866 lua_pushinteger( L, 1); // o "r" {c} {fqn} ... {?} {?} 1
867 lua_rawset( L, cache); // o "r" {c} {fqn} ... {?} 867 lua_rawset( L, cache); // o "r" {c} {fqn} ... {?}
868 // scan table contents 868 // scan table contents
869 lua_pushnil( L); // o "r" {c} {fqn} ... {?} nil 869 lua_pushnil( L); // o "r" {c} {fqn} ... {?} nil
870 while( lua_next( L, -2)) // o "r" {c} {fqn} ... {?} k v 870 while( lua_next( L, -2)) // o "r" {c} {fqn} ... {?} k v
871 { 871 {
872 //char const *const strKey = (lua_type( L, -2) == LUA_TSTRING) ? lua_tostring( L, -2) : NULL; // only for debugging 872 //char const *const strKey = (lua_type( L, -2) == LUA_TSTRING) ? lua_tostring( L, -2) : NULL; // only for debugging
873 //lua_Number const numKey = (lua_type( L, -2) == LUA_TNUMBER) ? lua_tonumber( L, -2) : -6666; // only for debugging 873 //lua_Number const numKey = (lua_type( L, -2) == LUA_TNUMBER) ? lua_tonumber( L, -2) : -6666; // only for debugging
874 STACK_MID( L, 2); 874 STACK_MID( L, 2);
875 // append key name to fqn stack 875 // append key name to fqn stack
876 ++ depth_; 876 ++ depth_;
877 lua_pushvalue( L, -2); // o "r" {c} {fqn} ... {?} k v k 877 lua_pushvalue( L, -2); // o "r" {c} {fqn} ... {?} k v k
878 lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k v 878 lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k v
879 if( lua_rawequal( L, -1, what)) // is it what we are looking for? 879 if( lua_rawequal( L, -1, what)) // is it what we are looking for?
880 { 880 {
881 STACK_MID( L, 2); 881 STACK_MID( L, 2);
882 // update shortest name 882 // update shortest name
883 if( depth_ < shortest_) 883 if( depth_ < shortest_)
884 { 884 {
885 shortest_ = depth_; 885 shortest_ = depth_;
886 luaG_pushFQN( L, fqn, depth_, NULL); // o "r" {c} {fqn} ... {?} k v "fqn" 886 luaG_pushFQN( L, fqn, depth_, NULL); // o "r" {c} {fqn} ... {?} k v "fqn"
887 lua_replace( L, result); // o "r" {c} {fqn} ... {?} k v 887 lua_replace( L, result); // o "r" {c} {fqn} ... {?} k v
888 } 888 }
889 // no need to search further at this level 889 // no need to search further at this level
890 lua_pop( L, 2); // o "r" {c} {fqn} ... {?} 890 lua_pop( L, 2); // o "r" {c} {fqn} ... {?}
891 STACK_MID( L, 0); 891 STACK_MID( L, 0);
892 break; 892 break;
893 } 893 }
894 switch( lua_type( L, -1)) // o "r" {c} {fqn} ... {?} k v 894 switch( lua_type( L, -1)) // o "r" {c} {fqn} ... {?} k v
895 { 895 {
896 default: // nil, boolean, light userdata, number and string aren't identifiable 896 default: // nil, boolean, light userdata, number and string aren't identifiable
897 break; 897 break;
898 898
899 case LUA_TTABLE: // o "r" {c} {fqn} ... {?} k {} 899 case LUA_TTABLE: // o "r" {c} {fqn} ... {?} k {}
900 STACK_MID( L, 2); 900 STACK_MID( L, 2);
901 shortest_ = discover_object_name_recur( L, shortest_, depth_); 901 shortest_ = discover_object_name_recur( L, shortest_, depth_);
902 // search in the table's metatable too 902 // search in the table's metatable too
903 if( lua_getmetatable( L, -1)) // o "r" {c} {fqn} ... {?} k {} {mt} 903 if( lua_getmetatable( L, -1)) // o "r" {c} {fqn} ... {?} k {} {mt}
904 { 904 {
905 if( lua_istable( L, -1)) 905 if( lua_istable( L, -1))
906 { 906 {
907 ++ depth_; 907 ++ depth_;
908 lua_pushliteral( L, "__metatable"); // o "r" {c} {fqn} ... {?} k {} {mt} "__metatable" 908 lua_pushliteral( L, "__metatable"); // o "r" {c} {fqn} ... {?} k {} {mt} "__metatable"
909 lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k {} {mt} 909 lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k {} {mt}
910 shortest_ = discover_object_name_recur( L, shortest_, depth_); 910 shortest_ = discover_object_name_recur( L, shortest_, depth_);
911 lua_pushnil( L); // o "r" {c} {fqn} ... {?} k {} {mt} nil 911 lua_pushnil( L); // o "r" {c} {fqn} ... {?} k {} {mt} nil
912 lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k {} {mt} 912 lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k {} {mt}
913 -- depth_; 913 -- depth_;
914 } 914 }
915 lua_pop( L, 1); // o "r" {c} {fqn} ... {?} k {} 915 lua_pop( L, 1); // o "r" {c} {fqn} ... {?} k {}
916 } 916 }
917 STACK_MID( L, 2); 917 STACK_MID( L, 2);
918 break; 918 break;
919 919
920 case LUA_TTHREAD: // o "r" {c} {fqn} ... {?} k T 920 case LUA_TTHREAD: // o "r" {c} {fqn} ... {?} k T
921 // TODO: explore the thread's stack frame looking for our culprit? 921 // TODO: explore the thread's stack frame looking for our culprit?
922 break; 922 break;
923 923
924 case LUA_TUSERDATA: // o "r" {c} {fqn} ... {?} k U 924 case LUA_TUSERDATA: // o "r" {c} {fqn} ... {?} k U
925 STACK_MID( L, 2); 925 STACK_MID( L, 2);
926 // search in the object's metatable (some modules are built that way) 926 // search in the object's metatable (some modules are built that way)
927 if( lua_getmetatable( L, -1)) // o "r" {c} {fqn} ... {?} k U {mt} 927 if( lua_getmetatable( L, -1)) // o "r" {c} {fqn} ... {?} k U {mt}
928 { 928 {
929 if( lua_istable( L, -1)) 929 if( lua_istable( L, -1))
930 { 930 {
931 ++ depth_; 931 ++ depth_;
932 lua_pushliteral( L, "__metatable"); // o "r" {c} {fqn} ... {?} k U {mt} "__metatable" 932 lua_pushliteral( L, "__metatable"); // o "r" {c} {fqn} ... {?} k U {mt} "__metatable"
933 lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k U {mt} 933 lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k U {mt}
934 shortest_ = discover_object_name_recur( L, shortest_, depth_); 934 shortest_ = discover_object_name_recur( L, shortest_, depth_);
935 lua_pushnil( L); // o "r" {c} {fqn} ... {?} k U {mt} nil 935 lua_pushnil( L); // o "r" {c} {fqn} ... {?} k U {mt} nil
936 lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k U {mt} 936 lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k U {mt}
937 -- depth_; 937 -- depth_;
938 } 938 }
939 lua_pop( L, 1); // o "r" {c} {fqn} ... {?} k U 939 lua_pop( L, 1); // o "r" {c} {fqn} ... {?} k U
940 } 940 }
941 STACK_MID( L, 2); 941 STACK_MID( L, 2);
942 // search in the object's uservalues 942 // search in the object's uservalues
943 { 943 {
944 int uvi = 1; 944 int uvi = 1;
945 while( lua_getiuservalue( L, -1, uvi) != LUA_TNONE) // o "r" {c} {fqn} ... {?} k U {u} 945 while( lua_getiuservalue( L, -1, uvi) != LUA_TNONE) // o "r" {c} {fqn} ... {?} k U {u}
946 { 946 {
947 if( lua_istable( L, -1)) // if it is a table, look inside 947 if( lua_istable( L, -1)) // if it is a table, look inside
948 { 948 {
949 ++ depth_; 949 ++ depth_;
950 lua_pushliteral( L, "uservalue"); // o "r" {c} {fqn} ... {?} k v {u} "uservalue" 950 lua_pushliteral( L, "uservalue"); // o "r" {c} {fqn} ... {?} k v {u} "uservalue"
951 lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k v {u} 951 lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k v {u}
952 shortest_ = discover_object_name_recur( L, shortest_, depth_); 952 shortest_ = discover_object_name_recur( L, shortest_, depth_);
953 lua_pushnil( L); // o "r" {c} {fqn} ... {?} k v {u} nil 953 lua_pushnil( L); // o "r" {c} {fqn} ... {?} k v {u} nil
954 lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k v {u} 954 lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k v {u}
955 -- depth_; 955 -- depth_;
956 } 956 }
957 lua_pop( L, 1); // o "r" {c} {fqn} ... {?} k U 957 lua_pop( L, 1); // o "r" {c} {fqn} ... {?} k U
958 ++ uvi; 958 ++ uvi;
959 } 959 }
960 // when lua_getiuservalue() returned LUA_TNONE, it pushed a nil. pop it now 960 // when lua_getiuservalue() returned LUA_TNONE, it pushed a nil. pop it now
961 lua_pop( L, 1); // o "r" {c} {fqn} ... {?} k U 961 lua_pop( L, 1); // o "r" {c} {fqn} ... {?} k U
962 } 962 }
963 STACK_MID( L, 2); 963 STACK_MID( L, 2);
964 break; 964 break;
965 } 965 }
966 // make ready for next iteration 966 // make ready for next iteration
967 lua_pop( L, 1); // o "r" {c} {fqn} ... {?} k 967 lua_pop( L, 1); // o "r" {c} {fqn} ... {?} k
968 // remove name from fqn stack 968 // remove name from fqn stack
969 lua_pushnil( L); // o "r" {c} {fqn} ... {?} k nil 969 lua_pushnil( L); // o "r" {c} {fqn} ... {?} k nil
970 lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k 970 lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k
971 STACK_MID( L, 1); 971 STACK_MID( L, 1);
972 -- depth_; 972 -- depth_;
973 } // o "r" {c} {fqn} ... {?} 973 } // o "r" {c} {fqn} ... {?}
974 STACK_MID( L, 0); 974 STACK_MID( L, 0);
975 // remove the visited table from the cache, in case a shorter path to the searched object exists 975 // remove the visited table from the cache, in case a shorter path to the searched object exists
976 lua_pushvalue( L, -1); // o "r" {c} {fqn} ... {?} {?} 976 lua_pushvalue( L, -1); // o "r" {c} {fqn} ... {?} {?}
977 lua_pushnil( L); // o "r" {c} {fqn} ... {?} {?} nil 977 lua_pushnil( L); // o "r" {c} {fqn} ... {?} {?} nil
978 lua_rawset( L, cache); // o "r" {c} {fqn} ... {?} 978 lua_rawset( L, cache); // o "r" {c} {fqn} ... {?}
979 STACK_END( L, 0); 979 STACK_END( L, 0);
980 return shortest_; 980 return shortest_;
981} 981}
982 982
983 983
@@ -986,46 +986,46 @@ static int discover_object_name_recur( lua_State* L, int shortest_, int depth_)
986 */ 986 */
987int luaG_nameof( lua_State* L) 987int luaG_nameof( lua_State* L)
988{ 988{
989 int what = lua_gettop( L); 989 int what = lua_gettop( L);
990 if( what > 1) 990 if( what > 1)
991 { 991 {
992 luaL_argerror( L, what, "too many arguments."); 992 luaL_argerror( L, what, "too many arguments.");
993 } 993 }
994 994
995 // nil, boolean, light userdata, number and string aren't identifiable 995 // nil, boolean, light userdata, number and string aren't identifiable
996 if( lua_type( L, 1) < LUA_TTABLE) 996 if( lua_type( L, 1) < LUA_TTABLE)
997 { 997 {
998 lua_pushstring( L, luaL_typename( L, 1)); // o "type" 998 lua_pushstring( L, luaL_typename( L, 1)); // o "type"
999 lua_insert( L, -2); // "type" o 999 lua_insert( L, -2); // "type" o
1000 return 2; 1000 return 2;
1001 } 1001 }
1002 1002
1003 STACK_GROW( L, 4); 1003 STACK_GROW( L, 4);
1004 STACK_CHECK( L, 0); 1004 STACK_CHECK( L, 0);
1005 // this slot will contain the shortest name we found when we are done 1005 // this slot will contain the shortest name we found when we are done
1006 lua_pushnil( L); // o nil 1006 lua_pushnil( L); // o nil
1007 // push a cache that will contain all already visited tables 1007 // push a cache that will contain all already visited tables
1008 lua_newtable( L); // o nil {c} 1008 lua_newtable( L); // o nil {c}
1009 // push a table whose contents are strings that, when concatenated, produce unique name 1009 // push a table whose contents are strings that, when concatenated, produce unique name
1010 lua_newtable( L); // o nil {c} {fqn} 1010 lua_newtable( L); // o nil {c} {fqn}
1011 lua_pushliteral( L, "_G"); // o nil {c} {fqn} "_G" 1011 lua_pushliteral( L, "_G"); // o nil {c} {fqn} "_G"
1012 lua_rawseti( L, -2, 1); // o nil {c} {fqn} 1012 lua_rawseti( L, -2, 1); // o nil {c} {fqn}
1013 // this is where we start the search 1013 // this is where we start the search
1014 lua_pushglobaltable( L); // o nil {c} {fqn} _G 1014 lua_pushglobaltable( L); // o nil {c} {fqn} _G
1015 (void) discover_object_name_recur( L, 6666, 1); 1015 (void) discover_object_name_recur( L, 6666, 1);
1016 if( lua_isnil( L, 2)) // try again with registry, just in case... 1016 if( lua_isnil( L, 2)) // try again with registry, just in case...
1017 { 1017 {
1018 lua_pop( L, 1); // o nil {c} {fqn} 1018 lua_pop( L, 1); // o nil {c} {fqn}
1019 lua_pushliteral( L, "_R"); // o nil {c} {fqn} "_R" 1019 lua_pushliteral( L, "_R"); // o nil {c} {fqn} "_R"
1020 lua_rawseti( L, -2, 1); // o nil {c} {fqn} 1020 lua_rawseti( L, -2, 1); // o nil {c} {fqn}
1021 lua_pushvalue( L, LUA_REGISTRYINDEX); // o nil {c} {fqn} _R 1021 lua_pushvalue( L, LUA_REGISTRYINDEX); // o nil {c} {fqn} _R
1022 (void) discover_object_name_recur( L, 6666, 1); 1022 (void) discover_object_name_recur( L, 6666, 1);
1023 } 1023 }
1024 lua_pop( L, 3); // o "result" 1024 lua_pop( L, 3); // o "result"
1025 STACK_END( L, 1); 1025 STACK_END( L, 1);
1026 lua_pushstring( L, luaL_typename( L, 1)); // o "result" "type" 1026 lua_pushstring( L, luaL_typename( L, 1)); // o "result" "type"
1027 lua_replace( L, -3); // "type" "result" 1027 lua_replace( L, -3); // "type" "result"
1028 return 2; 1028 return 2;
1029} 1029}
1030 1030
1031 1031
@@ -1034,73 +1034,73 @@ int luaG_nameof( lua_State* L)
1034 */ 1034 */
1035static void lookup_native_func( lua_State* L2, lua_State* L, uint_t i, LookupMode mode_, char const* upName_) 1035static void lookup_native_func( lua_State* L2, lua_State* L, uint_t i, LookupMode mode_, char const* upName_)
1036{ 1036{
1037 // get the name of the function we want to send 1037 // get the name of the function we want to send
1038 size_t len; 1038 size_t len;
1039 char const* fqn = find_lookup_name( L, i, mode_, upName_, &len); 1039 char const* fqn = find_lookup_name( L, i, mode_, upName_, &len);
1040 // push the equivalent function in the destination's stack, retrieved from the lookup table 1040 // push the equivalent function in the destination's stack, retrieved from the lookup table
1041 STACK_CHECK( L2, 0); // L // L2 1041 STACK_CHECK( L2, 0); // L // L2
1042 STACK_GROW( L2, 3); // up to 3 slots are necessary on error 1042 STACK_GROW( L2, 3); // up to 3 slots are necessary on error
1043 switch( mode_) 1043 switch( mode_)
1044 { 1044 {
1045 default: // shouldn't happen, in theory... 1045 default: // shouldn't happen, in theory...
1046 (void) luaL_error( L, "internal error: unknown lookup mode"); 1046 (void) luaL_error( L, "internal error: unknown lookup mode");
1047 return; 1047 return;
1048 1048
1049 case eLM_ToKeeper: 1049 case eLM_ToKeeper:
1050 // push a sentinel closure that holds the lookup name as upvalue 1050 // push a sentinel closure that holds the lookup name as upvalue
1051 lua_pushlstring( L2, fqn, len); // "f.q.n" 1051 lua_pushlstring( L2, fqn, len); // "f.q.n"
1052 lua_pushcclosure( L2, func_lookup_sentinel, 1); // f 1052 lua_pushcclosure( L2, func_lookup_sentinel, 1); // f
1053 break; 1053 break;
1054 1054
1055 case eLM_LaneBody: 1055 case eLM_LaneBody:
1056 case eLM_FromKeeper: 1056 case eLM_FromKeeper:
1057 REGISTRY_GET( L2, LOOKUP_REGKEY); // {} 1057 REGISTRY_GET( L2, LOOKUP_REGKEY); // {}
1058 STACK_MID( L2, 1); 1058 STACK_MID( L2, 1);
1059 ASSERT_L( lua_istable( L2, -1)); 1059 ASSERT_L( lua_istable( L2, -1));
1060 lua_pushlstring( L2, fqn, len); // {} "f.q.n" 1060 lua_pushlstring( L2, fqn, len); // {} "f.q.n"
1061 lua_rawget( L2, -2); // {} f 1061 lua_rawget( L2, -2); // {} f
1062 // nil means we don't know how to transfer stuff: user should do something 1062 // nil means we don't know how to transfer stuff: user should do something
1063 // anything other than function or table should not happen! 1063 // anything other than function or table should not happen!
1064 if( !lua_isfunction( L2, -1) && !lua_istable( L2, -1)) 1064 if( !lua_isfunction( L2, -1) && !lua_istable( L2, -1))
1065 { 1065 {
1066 char const* from, * to; 1066 char const* from, * to;
1067 lua_getglobal( L, "decoda_name"); // ... f ... decoda_name 1067 lua_getglobal( L, "decoda_name"); // ... f ... decoda_name
1068 from = lua_tostring( L, -1); 1068 from = lua_tostring( L, -1);
1069 lua_pop( L, 1); // ... f ... 1069 lua_pop( L, 1); // ... f ...
1070 lua_getglobal( L2, "decoda_name"); // {} f decoda_name 1070 lua_getglobal( L2, "decoda_name"); // {} f decoda_name
1071 to = lua_tostring( L2, -1); 1071 to = lua_tostring( L2, -1);
1072 lua_pop( L2, 1); // {} f 1072 lua_pop( L2, 1); // {} f
1073 // when mode_ == eLM_FromKeeper, L is a keeper state and L2 is not, therefore L2 is the state where we want to raise the error 1073 // when mode_ == eLM_FromKeeper, L is a keeper state and L2 is not, therefore L2 is the state where we want to raise the error
1074 (void) luaL_error( 1074 (void) luaL_error(
1075 (mode_ == eLM_FromKeeper) ? L2 : L 1075 (mode_ == eLM_FromKeeper) ? L2 : L
1076 , "%s%s: function '%s' not found in %s destination transfer database." 1076 , "%s%s: function '%s' not found in %s destination transfer database."
1077 , lua_isnil( L2, -1) ? "" : "INTERNAL ERROR IN " 1077 , lua_isnil( L2, -1) ? "" : "INTERNAL ERROR IN "
1078 , from ? from : "main" 1078 , from ? from : "main"
1079 , fqn 1079 , fqn
1080 , to ? to : "main" 1080 , to ? to : "main"
1081 ); 1081 );
1082 return; 1082 return;
1083 } 1083 }
1084 lua_remove( L2, -2); // f 1084 lua_remove( L2, -2); // f
1085 break; 1085 break;
1086 1086
1087 /* keep it in case I need it someday, who knows... 1087 /* keep it in case I need it someday, who knows...
1088 case eLM_RawFunctions: 1088 case eLM_RawFunctions:
1089 { 1089 {
1090 int n; 1090 int n;
1091 char const* upname; 1091 char const* upname;
1092 lua_CFunction f = lua_tocfunction( L, i); 1092 lua_CFunction f = lua_tocfunction( L, i);
1093 // copy upvalues 1093 // copy upvalues
1094 for( n = 0; (upname = lua_getupvalue( L, i, 1 + n)) != NULL; ++ n) 1094 for( n = 0; (upname = lua_getupvalue( L, i, 1 + n)) != NULL; ++ n)
1095 { 1095 {
1096 luaG_inter_move( U, L, L2, 1, mode_); // [up[,up ...]] 1096 luaG_inter_move( U, L, L2, 1, mode_); // [up[,up ...]]
1097 } 1097 }
1098 lua_pushcclosure( L2, f, n); // 1098 lua_pushcclosure( L2, f, n); //
1099 } 1099 }
1100 break; 1100 break;
1101 */ 1101 */
1102 } 1102 }
1103 STACK_END( L2, 1); 1103 STACK_END( L2, 1);
1104} 1104}
1105 1105
1106 1106
@@ -1112,23 +1112,23 @@ static void lookup_native_func( lua_State* L2, lua_State* L, uint_t i, LookupMod
1112#if USE_DEBUG_SPEW 1112#if USE_DEBUG_SPEW
1113static char const* lua_type_names[] = 1113static char const* lua_type_names[] =
1114{ 1114{
1115 "LUA_TNIL" 1115 "LUA_TNIL"
1116 , "LUA_TBOOLEAN" 1116 , "LUA_TBOOLEAN"
1117 , "LUA_TLIGHTUSERDATA" 1117 , "LUA_TLIGHTUSERDATA"
1118 , "LUA_TNUMBER" 1118 , "LUA_TNUMBER"
1119 , "LUA_TSTRING" 1119 , "LUA_TSTRING"
1120 , "LUA_TTABLE" 1120 , "LUA_TTABLE"
1121 , "LUA_TFUNCTION" 1121 , "LUA_TFUNCTION"
1122 , "LUA_TUSERDATA" 1122 , "LUA_TUSERDATA"
1123 , "LUA_TTHREAD" 1123 , "LUA_TTHREAD"
1124 , "<LUA_NUMTAGS>" // not really a type 1124 , "<LUA_NUMTAGS>" // not really a type
1125 , "LUA_TJITCDATA" // LuaJIT specific 1125 , "LUA_TJITCDATA" // LuaJIT specific
1126}; 1126};
1127static char const* vt_names[] = 1127static char const* vt_names[] =
1128{ 1128{
1129 "VT_NORMAL" 1129 "VT_NORMAL"
1130 , "VT_KEY" 1130 , "VT_KEY"
1131 , "VT_METATABLE" 1131 , "VT_METATABLE"
1132}; 1132};
1133#endif // USE_DEBUG_SPEW 1133#endif // USE_DEBUG_SPEW
1134 1134
@@ -1149,148 +1149,148 @@ static int buf_writer( lua_State* L, void const* b, size_t size, void* ud)
1149 1149
1150static void copy_func( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, LookupMode mode_, char const* upName_) 1150static void copy_func( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, LookupMode mode_, char const* upName_)
1151{ 1151{
1152 int n, needToPush; 1152 int n, needToPush;
1153 luaL_Buffer B; 1153 luaL_Buffer B;
1154 B.L = NULL; 1154 B.L = NULL;
1155 1155
1156 ASSERT_L( L2_cache_i != 0); // ... {cache} ... p 1156 ASSERT_L( L2_cache_i != 0); // ... {cache} ... p
1157 STACK_GROW( L, 2); 1157 STACK_GROW( L, 2);
1158 STACK_CHECK( L, 0); 1158 STACK_CHECK( L, 0);
1159 1159
1160 1160
1161 // 'lua_dump()' needs the function at top of stack 1161 // 'lua_dump()' needs the function at top of stack
1162 // if already on top of the stack, no need to push again 1162 // if already on top of the stack, no need to push again
1163 needToPush = (i != (uint_t)lua_gettop( L)); 1163 needToPush = (i != (uint_t)lua_gettop( L));
1164 if( needToPush) 1164 if( needToPush)
1165 { 1165 {
1166 lua_pushvalue( L, i); // ... f 1166 lua_pushvalue( L, i); // ... f
1167 } 1167 }
1168 1168
1169 // 1169 //
1170 // "value returned is the error code returned by the last call 1170 // "value returned is the error code returned by the last call
1171 // to the writer" (and we only return 0) 1171 // to the writer" (and we only return 0)
1172 // not sure this could ever fail but for memory shortage reasons 1172 // not sure this could ever fail but for memory shortage reasons
1173 // last parameter is Lua 5.4-specific (no stripping) 1173 // last parameter is Lua 5.4-specific (no stripping)
1174 if( lua504_dump( L, buf_writer, &B, 0) != 0) 1174 if( lua504_dump( L, buf_writer, &B, 0) != 0)
1175 { 1175 {
1176 luaL_error( L, "internal error: function dump failed."); 1176 luaL_error( L, "internal error: function dump failed.");
1177 } 1177 }
1178 1178
1179 // pushes dumped string on 'L' 1179 // pushes dumped string on 'L'
1180 luaL_pushresult( &B); // ... f b 1180 luaL_pushresult( &B); // ... f b
1181 1181
1182 // if not pushed, no need to pop 1182 // if not pushed, no need to pop
1183 if( needToPush) 1183 if( needToPush)
1184 { 1184 {
1185 lua_remove( L, -2); // ... b 1185 lua_remove( L, -2); // ... b
1186 } 1186 }
1187 1187
1188 // transfer the bytecode, then the upvalues, to create a similar closure 1188 // transfer the bytecode, then the upvalues, to create a similar closure
1189 { 1189 {
1190 char const* name = NULL; 1190 char const* name = NULL;
1191 1191
1192 #if LOG_FUNC_INFO 1192 #if LOG_FUNC_INFO
1193 // "To get information about a function you push it onto the 1193 // "To get information about a function you push it onto the
1194 // stack and start the what string with the character '>'." 1194 // stack and start the what string with the character '>'."
1195 // 1195 //
1196 { 1196 {
1197 lua_Debug ar; 1197 lua_Debug ar;
1198 lua_pushvalue( L, i); // ... b f 1198 lua_pushvalue( L, i); // ... b f
1199 // fills 'name' 'namewhat' and 'linedefined', pops function 1199 // fills 'name' 'namewhat' and 'linedefined', pops function
1200 lua_getinfo( L, ">nS", &ar); // ... b 1200 lua_getinfo( L, ">nS", &ar); // ... b
1201 name = ar.namewhat; 1201 name = ar.namewhat;
1202 fprintf( stderr, INDENT_BEGIN "FNAME: %s @ %d\n", i, s_indent, ar.short_src, ar.linedefined); // just gives NULL 1202 fprintf( stderr, INDENT_BEGIN "FNAME: %s @ %d\n", i, s_indent, ar.short_src, ar.linedefined); // just gives NULL
1203 } 1203 }
1204 #endif // LOG_FUNC_INFO 1204 #endif // LOG_FUNC_INFO
1205 { 1205 {
1206 size_t sz; 1206 size_t sz;
1207 char const* s = lua_tolstring( L, -1, &sz); // ... b 1207 char const* s = lua_tolstring( L, -1, &sz); // ... b
1208 ASSERT_L( s && sz); 1208 ASSERT_L( s && sz);
1209 STACK_GROW( L2, 2); 1209 STACK_GROW( L2, 2);
1210 // Note: Line numbers seem to be taken precisely from the 1210 // Note: Line numbers seem to be taken precisely from the
1211 // original function. 'name' is not used since the chunk 1211 // original function. 'name' is not used since the chunk
1212 // is precompiled (it seems...). 1212 // is precompiled (it seems...).
1213 // 1213 //
1214 // TBD: Can we get the function's original name through, as well? 1214 // TBD: Can we get the function's original name through, as well?
1215 // 1215 //
1216 if( luaL_loadbuffer( L2, s, sz, name) != 0) // ... {cache} ... p function 1216 if( luaL_loadbuffer( L2, s, sz, name) != 0) // ... {cache} ... p function
1217 { 1217 {
1218 // chunk is precompiled so only LUA_ERRMEM can happen 1218 // chunk is precompiled so only LUA_ERRMEM can happen
1219 // "Otherwise, it pushes an error message" 1219 // "Otherwise, it pushes an error message"
1220 // 1220 //
1221 STACK_GROW( L, 1); 1221 STACK_GROW( L, 1);
1222 luaL_error( L, "%s: %s", upName_, lua_tostring( L2, -1)); 1222 luaL_error( L, "%s: %s", upName_, lua_tostring( L2, -1));
1223 } 1223 }
1224 // remove the dumped string 1224 // remove the dumped string
1225 lua_pop( L, 1); // ... 1225 lua_pop( L, 1); // ...
1226 // now set the cache as soon as we can. 1226 // now set the cache as soon as we can.
1227 // this is necessary if one of the function's upvalues references it indirectly 1227 // this is necessary if one of the function's upvalues references it indirectly
1228 // we need to find it in the cache even if it isn't fully transfered yet 1228 // we need to find it in the cache even if it isn't fully transfered yet
1229 lua_insert( L2, -2); // ... {cache} ... function p 1229 lua_insert( L2, -2); // ... {cache} ... function p
1230 lua_pushvalue( L2, -2); // ... {cache} ... function p function 1230 lua_pushvalue( L2, -2); // ... {cache} ... function p function
1231 // cache[p] = function 1231 // cache[p] = function
1232 lua_rawset( L2, L2_cache_i); // ... {cache} ... function 1232 lua_rawset( L2, L2_cache_i); // ... {cache} ... function
1233 } 1233 }
1234 STACK_MID( L, 0); 1234 STACK_MID( L, 0);
1235 1235
1236 /* push over any upvalues; references to this function will come from 1236 /* push over any upvalues; references to this function will come from
1237 * cache so we don't end up in eternal loop. 1237 * cache so we don't end up in eternal loop.
1238 * Lua5.2 and Lua5.3: one of the upvalues is _ENV, which we don't want to copy! 1238 * Lua5.2 and Lua5.3: one of the upvalues is _ENV, which we don't want to copy!
1239 * instead, the function shall have LUA_RIDX_GLOBALS taken in the destination state! 1239 * instead, the function shall have LUA_RIDX_GLOBALS taken in the destination state!
1240 */ 1240 */
1241 { 1241 {
1242 char const* upname; 1242 char const* upname;
1243#if LUA_VERSION_NUM >= 502 1243#if LUA_VERSION_NUM >= 502
1244 // Starting with Lua 5.2, each Lua function gets its environment as one of its upvalues (named LUA_ENV, aka "_ENV" by default) 1244 // Starting with Lua 5.2, each Lua function gets its environment as one of its upvalues (named LUA_ENV, aka "_ENV" by default)
1245 // Generally this is LUA_RIDX_GLOBALS, which we don't want to copy from the source to the destination state... 1245 // Generally this is LUA_RIDX_GLOBALS, which we don't want to copy from the source to the destination state...
1246 // -> if we encounter an upvalue equal to the global table in the source, bind it to the destination's global table 1246 // -> if we encounter an upvalue equal to the global table in the source, bind it to the destination's global table
1247 lua_pushglobaltable( L); // ... _G 1247 lua_pushglobaltable( L); // ... _G
1248#endif // LUA_VERSION_NUM 1248#endif // LUA_VERSION_NUM
1249 for( n = 0; (upname = lua_getupvalue( L, i, 1 + n)) != NULL; ++ n) 1249 for( n = 0; (upname = lua_getupvalue( L, i, 1 + n)) != NULL; ++ n)
1250 { // ... _G up[n] 1250 { // ... _G up[n]
1251 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "UPNAME[%d]: %s -> " INDENT_END, n, upname)); 1251 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "UPNAME[%d]: %s -> " INDENT_END, n, upname));
1252#if LUA_VERSION_NUM >= 502 1252#if LUA_VERSION_NUM >= 502
1253 if( lua_rawequal( L, -1, -2)) // is the upvalue equal to the global table? 1253 if( lua_rawequal( L, -1, -2)) // is the upvalue equal to the global table?
1254 { 1254 {
1255 DEBUGSPEW_CODE( fprintf( stderr, "pushing destination global scope\n")); 1255 DEBUGSPEW_CODE( fprintf( stderr, "pushing destination global scope\n"));
1256 lua_pushglobaltable( L2); // ... {cache} ... function <upvalues> 1256 lua_pushglobaltable( L2); // ... {cache} ... function <upvalues>
1257 } 1257 }
1258 else 1258 else
1259#endif // LUA_VERSION_NUM 1259#endif // LUA_VERSION_NUM
1260 { 1260 {
1261 DEBUGSPEW_CODE( fprintf( stderr, "copying value\n")); 1261 DEBUGSPEW_CODE( fprintf( stderr, "copying value\n"));
1262 if( !inter_copy_one( U, L2, L2_cache_i, L, lua_gettop( L), VT_NORMAL, mode_, upname)) // ... {cache} ... function <upvalues> 1262 if( !inter_copy_one( U, L2, L2_cache_i, L, lua_gettop( L), VT_NORMAL, mode_, upname)) // ... {cache} ... function <upvalues>
1263 { 1263 {
1264 luaL_error( L, "Cannot copy upvalue type '%s'", luaL_typename( L, -1)); 1264 luaL_error( L, "Cannot copy upvalue type '%s'", luaL_typename( L, -1));
1265 } 1265 }
1266 } 1266 }
1267 lua_pop( L, 1); // ... _G 1267 lua_pop( L, 1); // ... _G
1268 } 1268 }
1269#if LUA_VERSION_NUM >= 502 1269#if LUA_VERSION_NUM >= 502
1270 lua_pop( L, 1); // ... 1270 lua_pop( L, 1); // ...
1271#endif // LUA_VERSION_NUM 1271#endif // LUA_VERSION_NUM
1272 } 1272 }
1273 // L2: function + 'n' upvalues (>=0) 1273 // L2: function + 'n' upvalues (>=0)
1274 1274
1275 STACK_MID( L, 0); 1275 STACK_MID( L, 0);
1276 1276
1277 // Set upvalues (originally set to 'nil' by 'lua_load') 1277 // Set upvalues (originally set to 'nil' by 'lua_load')
1278 { 1278 {
1279 int func_index = lua_gettop( L2) - n; 1279 int func_index = lua_gettop( L2) - n;
1280 for( ; n > 0; -- n) 1280 for( ; n > 0; -- n)
1281 { 1281 {
1282 char const* rc = lua_setupvalue( L2, func_index, n); // ... {cache} ... function 1282 char const* rc = lua_setupvalue( L2, func_index, n); // ... {cache} ... function
1283 // 1283 //
1284 // "assigns the value at the top of the stack to the upvalue and returns its name. 1284 // "assigns the value at the top of the stack to the upvalue and returns its name.
1285 // It also pops the value from the stack." 1285 // It also pops the value from the stack."
1286 1286
1287 ASSERT_L( rc); // not having enough slots? 1287 ASSERT_L( rc); // not having enough slots?
1288 } 1288 }
1289 // once all upvalues have been set we are left 1289 // once all upvalues have been set we are left
1290 // with the function at the top of the stack // ... {cache} ... function 1290 // with the function at the top of the stack // ... {cache} ... function
1291 } 1291 }
1292 } 1292 }
1293 STACK_END( L, 0); 1293 STACK_END( L, 0);
1294} 1294}
1295 1295
1296/* 1296/*
@@ -1301,168 +1301,168 @@ static void copy_func( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State*
1301 */ 1301 */
1302static void copy_cached_func( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, LookupMode mode_, char const* upName_) 1302static void copy_cached_func( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, LookupMode mode_, char const* upName_)
1303{ 1303{
1304 FuncSubType funcSubType; 1304 FuncSubType funcSubType;
1305 /*lua_CFunction cfunc =*/ luaG_tocfunction( L, i, &funcSubType); // NULL for LuaJIT-fast && bytecode functions 1305 /*lua_CFunction cfunc =*/ luaG_tocfunction( L, i, &funcSubType); // NULL for LuaJIT-fast && bytecode functions
1306 if( funcSubType == FST_Bytecode) 1306 if( funcSubType == FST_Bytecode)
1307 { 1307 {
1308 void* const aspointer = (void*)lua_topointer( L, i); 1308 void* const aspointer = (void*)lua_topointer( L, i);
1309 // TBD: Merge this and same code for tables 1309 // TBD: Merge this and same code for tables
1310 ASSERT_L( L2_cache_i != 0); 1310 ASSERT_L( L2_cache_i != 0);
1311 1311
1312 STACK_GROW( L2, 2); 1312 STACK_GROW( L2, 2);
1313 1313
1314 // L2_cache[id_str]= function 1314 // L2_cache[id_str]= function
1315 // 1315 //
1316 STACK_CHECK( L2, 0); 1316 STACK_CHECK( L2, 0);
1317 1317
1318 // We don't need to use the from state ('L') in ID since the life span 1318 // We don't need to use the from state ('L') in ID since the life span
1319 // is only for the duration of a copy (both states are locked). 1319 // is only for the duration of a copy (both states are locked).
1320 // 1320 //
1321 1321
1322 // push a light userdata uniquely representing the function 1322 // push a light userdata uniquely representing the function
1323 lua_pushlightuserdata( L2, aspointer); // ... {cache} ... p 1323 lua_pushlightuserdata( L2, aspointer); // ... {cache} ... p
1324 1324
1325 //fprintf( stderr, "<< ID: %s >>\n", lua_tostring( L2, -1)); 1325 //fprintf( stderr, "<< ID: %s >>\n", lua_tostring( L2, -1));
1326 1326
1327 lua_pushvalue( L2, -1); // ... {cache} ... p p 1327 lua_pushvalue( L2, -1); // ... {cache} ... p p
1328 lua_rawget( L2, L2_cache_i); // ... {cache} ... p function|nil|true 1328 lua_rawget( L2, L2_cache_i); // ... {cache} ... p function|nil|true
1329 1329
1330 if( lua_isnil( L2, -1)) // function is unknown 1330 if( lua_isnil( L2, -1)) // function is unknown
1331 { 1331 {
1332 lua_pop( L2, 1); // ... {cache} ... p 1332 lua_pop( L2, 1); // ... {cache} ... p
1333 1333
1334 // Set to 'true' for the duration of creation; need to find self-references 1334 // Set to 'true' for the duration of creation; need to find self-references
1335 // via upvalues 1335 // via upvalues
1336 // 1336 //
1337 // pushes a copy of the func, stores a reference in the cache 1337 // pushes a copy of the func, stores a reference in the cache
1338 copy_func( U, L2, L2_cache_i, L, i, mode_, upName_); // ... {cache} ... function 1338 copy_func( U, L2, L2_cache_i, L, i, mode_, upName_); // ... {cache} ... function
1339 } 1339 }
1340 else // found function in the cache 1340 else // found function in the cache
1341 { 1341 {
1342 lua_remove( L2, -2); // ... {cache} ... function 1342 lua_remove( L2, -2); // ... {cache} ... function
1343 } 1343 }
1344 STACK_END( L2, 1); 1344 STACK_END( L2, 1);
1345 ASSERT_L( lua_isfunction( L2, -1)); 1345 ASSERT_L( lua_isfunction( L2, -1));
1346 } 1346 }
1347 else // function is native/LuaJIT: no need to cache 1347 else // function is native/LuaJIT: no need to cache
1348 { 1348 {
1349 lookup_native_func( L2, L, i, mode_, upName_); // ... {cache} ... function 1349 lookup_native_func( L2, L, i, mode_, upName_); // ... {cache} ... function
1350 // if the function was in fact a lookup sentinel, we can either get a function or a table here 1350 // if the function was in fact a lookup sentinel, we can either get a function or a table here
1351 ASSERT_L( lua_isfunction( L2, -1) || lua_istable( L2, -1)); 1351 ASSERT_L( lua_isfunction( L2, -1) || lua_istable( L2, -1));
1352 } 1352 }
1353} 1353}
1354 1354
1355static bool_t push_cached_metatable( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum eLookupMode mode_, char const* upName_) 1355static bool_t push_cached_metatable( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum eLookupMode mode_, char const* upName_)
1356{ 1356{
1357 STACK_CHECK( L, 0); 1357 STACK_CHECK( L, 0);
1358 if( lua_getmetatable( L, i)) // ... mt 1358 if( lua_getmetatable( L, i)) // ... mt
1359 { 1359 {
1360 lua_Integer const mt_id = get_mt_id( U, L, -1); // Unique id for the metatable 1360 lua_Integer const mt_id = get_mt_id( U, L, -1); // Unique id for the metatable
1361 1361
1362 STACK_CHECK( L2, 0); 1362 STACK_CHECK( L2, 0);
1363 STACK_GROW( L2, 4); 1363 STACK_GROW( L2, 4);
1364 // do we already know this metatable? 1364 // do we already know this metatable?
1365 push_registry_subtable( L2, REG_MTID); // _R[REG_MTID] 1365 push_registry_subtable( L2, REG_MTID); // _R[REG_MTID]
1366 lua_pushinteger( L2, mt_id); // _R[REG_MTID] id 1366 lua_pushinteger( L2, mt_id); // _R[REG_MTID] id
1367 lua_rawget( L2, -2); // _R[REG_MTID] mt? 1367 lua_rawget( L2, -2); // _R[REG_MTID] mt?
1368 1368
1369 STACK_MID( L2, 2); 1369 STACK_MID( L2, 2);
1370 1370
1371 if( lua_isnil( L2, -1)) 1371 if( lua_isnil( L2, -1))
1372 { // L2 did not know the metatable 1372 { // L2 did not know the metatable
1373 lua_pop( L2, 1); // _R[REG_MTID] 1373 lua_pop( L2, 1); // _R[REG_MTID]
1374 if( inter_copy_one( U, L2, L2_cache_i, L, lua_gettop( L), VT_METATABLE, mode_, upName_)) // _R[REG_MTID] mt 1374 if( inter_copy_one( U, L2, L2_cache_i, L, lua_gettop( L), VT_METATABLE, mode_, upName_)) // _R[REG_MTID] mt
1375 { 1375 {
1376 STACK_MID( L2, 2); 1376 STACK_MID( L2, 2);
1377 // mt_id -> metatable 1377 // mt_id -> metatable
1378 lua_pushinteger( L2, mt_id); // _R[REG_MTID] mt id 1378 lua_pushinteger( L2, mt_id); // _R[REG_MTID] mt id
1379 lua_pushvalue( L2, -2); // _R[REG_MTID] mt id mt 1379 lua_pushvalue( L2, -2); // _R[REG_MTID] mt id mt
1380 lua_rawset( L2, -4); // _R[REG_MTID] mt 1380 lua_rawset( L2, -4); // _R[REG_MTID] mt
1381 1381
1382 // metatable -> mt_id 1382 // metatable -> mt_id
1383 lua_pushvalue( L2, -1); // _R[REG_MTID] mt mt 1383 lua_pushvalue( L2, -1); // _R[REG_MTID] mt mt
1384 lua_pushinteger( L2, mt_id); // _R[REG_MTID] mt mt id 1384 lua_pushinteger( L2, mt_id); // _R[REG_MTID] mt mt id
1385 lua_rawset( L2, -4); // _R[REG_MTID] mt 1385 lua_rawset( L2, -4); // _R[REG_MTID] mt
1386 } 1386 }
1387 else 1387 else
1388 { 1388 {
1389 (void) luaL_error( L, "Error copying a metatable"); 1389 (void) luaL_error( L, "Error copying a metatable");
1390 } 1390 }
1391 STACK_MID( L2, 2); 1391 STACK_MID( L2, 2);
1392 } 1392 }
1393 lua_remove( L2, -2); // mt 1393 lua_remove( L2, -2); // mt
1394 1394
1395 lua_pop( L, 1); // ... 1395 lua_pop( L, 1); // ...
1396 STACK_END( L2, 1); 1396 STACK_END( L2, 1);
1397 STACK_MID( L, 0); 1397 STACK_MID( L, 0);
1398 return TRUE; 1398 return TRUE;
1399 } 1399 }
1400 STACK_END( L, 0); 1400 STACK_END( L, 0);
1401 return FALSE; 1401 return FALSE;
1402} 1402}
1403 1403
1404static void inter_copy_keyvaluepair( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, enum e_vt vt, LookupMode mode_, char const* upName_) 1404static void inter_copy_keyvaluepair( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, enum e_vt vt, LookupMode mode_, char const* upName_)
1405{ 1405{
1406 uint_t val_i = lua_gettop( L); 1406 uint_t val_i = lua_gettop( L);
1407 uint_t key_i = val_i - 1; 1407 uint_t key_i = val_i - 1;
1408 1408
1409 // Only basic key types are copied over; others ignored 1409 // Only basic key types are copied over; others ignored
1410 if( inter_copy_one( U, L2, 0 /*key*/, L, key_i, VT_KEY, mode_, upName_)) 1410 if( inter_copy_one( U, L2, 0 /*key*/, L, key_i, VT_KEY, mode_, upName_))
1411 { 1411 {
1412 char* valPath = (char*) upName_; 1412 char* valPath = (char*) upName_;
1413 if( U->verboseErrors) 1413 if( U->verboseErrors)
1414 { 1414 {
1415 // for debug purposes, let's try to build a useful name 1415 // for debug purposes, let's try to build a useful name
1416 if( lua_type( L, key_i) == LUA_TSTRING) 1416 if( lua_type( L, key_i) == LUA_TSTRING)
1417 { 1417 {
1418 char const* key = lua_tostring( L, key_i); 1418 char const* key = lua_tostring( L, key_i);
1419 size_t const keyRawLen = lua_rawlen( L, key_i); 1419 size_t const keyRawLen = lua_rawlen( L, key_i);
1420 size_t const bufLen = strlen( upName_) + keyRawLen + 2; 1420 size_t const bufLen = strlen( upName_) + keyRawLen + 2;
1421 valPath = (char*) alloca( bufLen); 1421 valPath = (char*) alloca( bufLen);
1422 sprintf( valPath, "%s.%*s", upName_, (int) keyRawLen, key); 1422 sprintf( valPath, "%s.%*s", upName_, (int) keyRawLen, key);
1423 key = NULL; 1423 key = NULL;
1424 } 1424 }
1425#if defined LUA_LNUM || LUA_VERSION_NUM >= 503 1425#if defined LUA_LNUM || LUA_VERSION_NUM >= 503
1426 else if( lua_isinteger( L, key_i)) 1426 else if( lua_isinteger( L, key_i))
1427 { 1427 {
1428 lua_Integer key = lua_tointeger( L, key_i); 1428 lua_Integer key = lua_tointeger( L, key_i);
1429 valPath = (char*) alloca( strlen( upName_) + 32 + 3); 1429 valPath = (char*) alloca( strlen( upName_) + 32 + 3);
1430 sprintf( valPath, "%s[" LUA_INTEGER_FMT "]", upName_, key); 1430 sprintf( valPath, "%s[" LUA_INTEGER_FMT "]", upName_, key);
1431 } 1431 }
1432#endif // defined LUA_LNUM || LUA_VERSION_NUM >= 503 1432#endif // defined LUA_LNUM || LUA_VERSION_NUM >= 503
1433 else if( lua_type( L, key_i) == LUA_TNUMBER) 1433 else if( lua_type( L, key_i) == LUA_TNUMBER)
1434 { 1434 {
1435 lua_Number key = lua_tonumber( L, key_i); 1435 lua_Number key = lua_tonumber( L, key_i);
1436 valPath = (char*) alloca( strlen( upName_) + 32 + 3); 1436 valPath = (char*) alloca( strlen( upName_) + 32 + 3);
1437 sprintf( valPath, "%s[" LUA_NUMBER_FMT "]", upName_, key); 1437 sprintf( valPath, "%s[" LUA_NUMBER_FMT "]", upName_, key);
1438 } 1438 }
1439 else if( lua_type( L, key_i) == LUA_TLIGHTUSERDATA) 1439 else if( lua_type( L, key_i) == LUA_TLIGHTUSERDATA)
1440 { 1440 {
1441 void* key = lua_touserdata( L, key_i); 1441 void* key = lua_touserdata( L, key_i);
1442 valPath = (char*) alloca( strlen( upName_) + 16 + 5); 1442 valPath = (char*) alloca( strlen( upName_) + 16 + 5);
1443 sprintf( valPath, "%s[U:%p]", upName_, key); 1443 sprintf( valPath, "%s[U:%p]", upName_, key);
1444 } 1444 }
1445 else if( lua_type( L, key_i) == LUA_TBOOLEAN) 1445 else if( lua_type( L, key_i) == LUA_TBOOLEAN)
1446 { 1446 {
1447 int key = lua_toboolean( L, key_i); 1447 int key = lua_toboolean( L, key_i);
1448 valPath = (char*) alloca( strlen( upName_) + 8); 1448 valPath = (char*) alloca( strlen( upName_) + 8);
1449 sprintf( valPath, "%s[%s]", upName_, key ? "true" : "false"); 1449 sprintf( valPath, "%s[%s]", upName_, key ? "true" : "false");
1450 } 1450 }
1451 } 1451 }
1452 /* 1452 /*
1453 * Contents of metatables are copied with cache checking; 1453 * Contents of metatables are copied with cache checking;
1454 * important to detect loops. 1454 * important to detect loops.
1455 */ 1455 */
1456 if( inter_copy_one( U, L2, L2_cache_i, L, val_i, VT_NORMAL, mode_, valPath)) 1456 if( inter_copy_one( U, L2, L2_cache_i, L, val_i, VT_NORMAL, mode_, valPath))
1457 { 1457 {
1458 ASSERT_L( lua_istable( L2, -3)); 1458 ASSERT_L( lua_istable( L2, -3));
1459 lua_rawset( L2, -3); // add to table (pops key & val) 1459 lua_rawset( L2, -3); // add to table (pops key & val)
1460 } 1460 }
1461 else 1461 else
1462 { 1462 {
1463 luaL_error( L, "Unable to copy %s entry '%s' because of value is of type '%s'", (vt == VT_NORMAL) ? "table" : "metatable", valPath, luaL_typename( L, val_i)); 1463 luaL_error( L, "Unable to copy %s entry '%s' because of value is of type '%s'", (vt == VT_NORMAL) ? "table" : "metatable", valPath, luaL_typename( L, val_i));
1464 } 1464 }
1465 } 1465 }
1466} 1466}
1467 1467
1468/* 1468/*
@@ -1473,330 +1473,330 @@ static DECLARE_CONST_UNIQUE_KEY( CLONABLES_CACHE_KEY, 0xD04EE018B3DEE8F5);
1473 1473
1474static bool_t copyclone( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, LookupMode mode_, char const* upName_) 1474static bool_t copyclone( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, LookupMode mode_, char const* upName_)
1475{ 1475{
1476 void* const source = lua_touserdata( L, i); 1476 void* const source = lua_touserdata( L, i);
1477 1477
1478 STACK_CHECK( L, 0); 1478 STACK_CHECK( L, 0);
1479 STACK_CHECK( L2, 0); 1479 STACK_CHECK( L2, 0);
1480 1480
1481 // Check if the source was already cloned during this copy 1481 // Check if the source was already cloned during this copy
1482 lua_pushlightuserdata( L2, source); // ... source 1482 lua_pushlightuserdata( L2, source); // ... source
1483 lua_rawget( L2, L2_cache_i); // ... clone? 1483 lua_rawget( L2, L2_cache_i); // ... clone?
1484 if ( !lua_isnil( L2, -1)) 1484 if ( !lua_isnil( L2, -1))
1485 { 1485 {
1486 STACK_MID( L2, 1); 1486 STACK_MID( L2, 1);
1487 return TRUE; 1487 return TRUE;
1488 } 1488 }
1489 else 1489 else
1490 { 1490 {
1491 lua_pop( L2, 1); // ... 1491 lua_pop( L2, 1); // ...
1492 } 1492 }
1493 STACK_MID( L2, 0); 1493 STACK_MID( L2, 0);
1494 1494
1495 // no metatable? -> not clonable 1495 // no metatable? -> not clonable
1496 if( !lua_getmetatable( L, i)) // ... mt? 1496 if( !lua_getmetatable( L, i)) // ... mt?
1497 { 1497 {
1498 STACK_MID( L, 0); 1498 STACK_MID( L, 0);
1499 return FALSE; 1499 return FALSE;
1500 } 1500 }
1501 1501
1502 // no __lanesclone? -> not clonable 1502 // no __lanesclone? -> not clonable
1503 lua_getfield( L, -1, "__lanesclone"); // ... mt __lanesclone? 1503 lua_getfield( L, -1, "__lanesclone"); // ... mt __lanesclone?
1504 if( lua_isnil( L, -1)) 1504 if( lua_isnil( L, -1))
1505 { 1505 {
1506 lua_pop( L, 2); // ... 1506 lua_pop( L, 2); // ...
1507 STACK_MID( L, 0); 1507 STACK_MID( L, 0);
1508 return FALSE; 1508 return FALSE;
1509 } 1509 }
1510 1510
1511 { 1511 {
1512 int const mt = lua_absindex( L, -2); 1512 int const mt = lua_absindex( L, -2);
1513 size_t userdata_size = 0; 1513 size_t userdata_size = 0;
1514 void* clone = NULL; 1514 void* clone = NULL;
1515 lua_pushvalue( L, -1); // ... mt __lanesclone __lanesclone 1515 lua_pushvalue( L, -1); // ... mt __lanesclone __lanesclone
1516 // call the cloning function with 1 argument, should return the number of bytes to allocate for the clone 1516 // call the cloning function with 1 argument, should return the number of bytes to allocate for the clone
1517 lua_pushlightuserdata( L, source); // ... mt __lanesclone __lanesclone source 1517 lua_pushlightuserdata( L, source); // ... mt __lanesclone __lanesclone source
1518 lua_call( L, 1, 1); // ... mt __lanesclone size 1518 lua_call( L, 1, 1); // ... mt __lanesclone size
1519 STACK_MID( L, 3); 1519 STACK_MID( L, 3);
1520 userdata_size = (size_t) lua_tointeger( L, -1); // ... mt __lanesclone size 1520 userdata_size = (size_t) lua_tointeger( L, -1); // ... mt __lanesclone size
1521 lua_pop( L, 1); // ... mt __lanesclone 1521 lua_pop( L, 1); // ... mt __lanesclone
1522 // we need to copy over the uservalues of the userdata as well 1522 // we need to copy over the uservalues of the userdata as well
1523 { 1523 {
1524 // extract all the uservalues, but don't transfer them yet 1524 // extract all the uservalues, but don't transfer them yet
1525 int uvi = 0; 1525 int uvi = 0;
1526 while( lua_getiuservalue( L, i, uvi + 1) != LUA_TNONE) // ... mt __lanesclone [uv]+ nil 1526 while( lua_getiuservalue( L, i, uvi + 1) != LUA_TNONE) // ... mt __lanesclone [uv]+ nil
1527 { 1527 {
1528 ++ uvi; 1528 ++ uvi;
1529 } 1529 }
1530 // when lua_getiuservalue() returned LUA_TNONE, it pushed a nil. pop it now 1530 // when lua_getiuservalue() returned LUA_TNONE, it pushed a nil. pop it now
1531 lua_pop( L, 1); // ... mt __lanesclone [uv]+ 1531 lua_pop( L, 1); // ... mt __lanesclone [uv]+
1532 // create the clone userdata with the required number of uservalue slots 1532 // create the clone userdata with the required number of uservalue slots
1533 clone = lua_newuserdatauv( L2, userdata_size, uvi); // ... u 1533 clone = lua_newuserdatauv( L2, userdata_size, uvi); // ... u
1534 // copy the metatable in the target state, and give it to the clone we put there 1534 // copy the metatable in the target state, and give it to the clone we put there
1535 if( inter_copy_one( U, L2, L2_cache_i, L, mt, VT_NORMAL, mode_, upName_)) // ... u mt|sentinel 1535 if( inter_copy_one( U, L2, L2_cache_i, L, mt, VT_NORMAL, mode_, upName_)) // ... u mt|sentinel
1536 { 1536 {
1537 if( eLM_ToKeeper == mode_) // ... u sentinel 1537 if( eLM_ToKeeper == mode_) // ... u sentinel
1538 { 1538 {
1539 ASSERT_L( lua_tocfunction( L2, -1) == table_lookup_sentinel); 1539 ASSERT_L( lua_tocfunction( L2, -1) == table_lookup_sentinel);
1540 // we want to create a new closure with a 'clone sentinel' function, where the upvalues are the userdata and the metatable fqn 1540 // we want to create a new closure with a 'clone sentinel' function, where the upvalues are the userdata and the metatable fqn
1541 lua_getupvalue( L2, -1, 1); // ... u sentinel fqn 1541 lua_getupvalue( L2, -1, 1); // ... u sentinel fqn
1542 lua_remove( L2, -2); // ... u fqn 1542 lua_remove( L2, -2); // ... u fqn
1543 lua_insert( L2, -2); // ... fqn u 1543 lua_insert( L2, -2); // ... fqn u
1544 lua_pushcclosure( L2, userdata_clone_sentinel, 2); // ... userdata_clone_sentinel 1544 lua_pushcclosure( L2, userdata_clone_sentinel, 2); // ... userdata_clone_sentinel
1545 } 1545 }
1546 else // from keeper or direct // ... u mt 1546 else // from keeper or direct // ... u mt
1547 { 1547 {
1548 ASSERT_L( lua_istable( L2, -1)); 1548 ASSERT_L( lua_istable( L2, -1));
1549 lua_setmetatable( L2, -2); // ... u 1549 lua_setmetatable( L2, -2); // ... u
1550 } 1550 }
1551 STACK_MID( L2, 1); 1551 STACK_MID( L2, 1);
1552 } 1552 }
1553 else 1553 else
1554 { 1554 {
1555 (void) luaL_error( L, "Error copying a metatable"); 1555 (void) luaL_error( L, "Error copying a metatable");
1556 } 1556 }
1557 // first, add the entry in the cache (at this point it is either the actual userdata or the keeper sentinel 1557 // first, add the entry in the cache (at this point it is either the actual userdata or the keeper sentinel
1558 lua_pushlightuserdata( L2, source); // ... u source 1558 lua_pushlightuserdata( L2, source); // ... u source
1559 lua_pushvalue( L2, -2); // ... u source u 1559 lua_pushvalue( L2, -2); // ... u source u
1560 lua_rawset( L2, L2_cache_i); // ... u 1560 lua_rawset( L2, L2_cache_i); // ... u
1561 // make sure we have the userdata now 1561 // make sure we have the userdata now
1562 if( eLM_ToKeeper == mode_) // ... userdata_clone_sentinel 1562 if( eLM_ToKeeper == mode_) // ... userdata_clone_sentinel
1563 { 1563 {
1564 lua_getupvalue( L2, -1, 2); // ... userdata_clone_sentinel u 1564 lua_getupvalue( L2, -1, 2); // ... userdata_clone_sentinel u
1565 } 1565 }
1566 // assign uservalues 1566 // assign uservalues
1567 while( uvi > 0) 1567 while( uvi > 0)
1568 { 1568 {
1569 inter_copy_one( U, L2, L2_cache_i, L, lua_absindex( L, -1), VT_NORMAL, mode_, upName_); // ... u uv 1569 inter_copy_one( U, L2, L2_cache_i, L, lua_absindex( L, -1), VT_NORMAL, mode_, upName_); // ... u uv
1570 lua_pop( L, 1); // ... mt __lanesclone [uv]* 1570 lua_pop( L, 1); // ... mt __lanesclone [uv]*
1571 // this pops the value from the stack 1571 // this pops the value from the stack
1572 lua_setiuservalue( L2, -2, uvi); // ... u 1572 lua_setiuservalue( L2, -2, uvi); // ... u
1573 -- uvi; 1573 -- uvi;
1574 } 1574 }
1575 // when we are done, all uservalues are popped from the source stack, and we want only the single transferred value in the destination 1575 // when we are done, all uservalues are popped from the source stack, and we want only the single transferred value in the destination
1576 if( eLM_ToKeeper == mode_) // ... userdata_clone_sentinel u 1576 if( eLM_ToKeeper == mode_) // ... userdata_clone_sentinel u
1577 { 1577 {
1578 lua_pop( L2, 1); // ... userdata_clone_sentinel 1578 lua_pop( L2, 1); // ... userdata_clone_sentinel
1579 } 1579 }
1580 STACK_MID( L2, 1); 1580 STACK_MID( L2, 1);
1581 STACK_MID( L, 2); 1581 STACK_MID( L, 2);
1582 // call cloning function in source state to perform the actual memory cloning 1582 // call cloning function in source state to perform the actual memory cloning
1583 lua_pushlightuserdata( L, clone); // ... mt __lanesclone clone 1583 lua_pushlightuserdata( L, clone); // ... mt __lanesclone clone
1584 lua_pushlightuserdata( L, source); // ... mt __lanesclone clone source 1584 lua_pushlightuserdata( L, source); // ... mt __lanesclone clone source
1585 lua_call( L, 2, 0); // ... mt 1585 lua_call( L, 2, 0); // ... mt
1586 STACK_MID( L, 1); 1586 STACK_MID( L, 1);
1587 } 1587 }
1588 } 1588 }
1589 1589
1590 STACK_END( L2, 1); 1590 STACK_END( L2, 1);
1591 lua_pop( L, 1); // ... 1591 lua_pop( L, 1); // ...
1592 STACK_END( L, 0); 1592 STACK_END( L, 0);
1593 return TRUE; 1593 return TRUE;
1594} 1594}
1595 1595
1596static bool_t inter_copy_userdata( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum e_vt vt, LookupMode mode_, char const* upName_) 1596static bool_t inter_copy_userdata( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum e_vt vt, LookupMode mode_, char const* upName_)
1597{ 1597{
1598 STACK_CHECK( L, 0); 1598 STACK_CHECK( L, 0);
1599 STACK_CHECK( L2, 0); 1599 STACK_CHECK( L2, 0);
1600 if( vt == VT_KEY) 1600 if( vt == VT_KEY)
1601 { 1601 {
1602 return FALSE; 1602 return FALSE;
1603 } 1603 }
1604 1604
1605 // try clonable userdata first 1605 // try clonable userdata first
1606 if( copyclone( U, L2, L2_cache_i, L, i, mode_, upName_)) 1606 if( copyclone( U, L2, L2_cache_i, L, i, mode_, upName_))
1607 { 1607 {
1608 STACK_MID( L, 0); 1608 STACK_MID( L, 0);
1609 STACK_MID( L2, 1); 1609 STACK_MID( L2, 1);
1610 return TRUE; 1610 return TRUE;
1611 } 1611 }
1612 1612
1613 STACK_MID( L, 0); 1613 STACK_MID( L, 0);
1614 STACK_MID( L2, 0); 1614 STACK_MID( L2, 0);
1615 1615
1616 // Allow only deep userdata entities to be copied across 1616 // Allow only deep userdata entities to be copied across
1617 DEBUGSPEW_CODE( fprintf( stderr, "USERDATA\n")); 1617 DEBUGSPEW_CODE( fprintf( stderr, "USERDATA\n"));
1618 if( copydeep( U, L2, L2_cache_i, L, i, mode_, upName_)) 1618 if( copydeep( U, L2, L2_cache_i, L, i, mode_, upName_))
1619 { 1619 {
1620 STACK_MID( L, 0); 1620 STACK_MID( L, 0);
1621 STACK_MID( L2, 1); 1621 STACK_MID( L2, 1);
1622 return TRUE; 1622 return TRUE;
1623 } 1623 }
1624 1624
1625 STACK_MID( L, 0); 1625 STACK_MID( L, 0);
1626 STACK_MID( L2, 0); 1626 STACK_MID( L2, 0);
1627 1627
1628 // Not a deep or clonable full userdata 1628 // Not a deep or clonable full userdata
1629 if( U->demoteFullUserdata) // attempt demotion to light userdata 1629 if( U->demoteFullUserdata) // attempt demotion to light userdata
1630 { 1630 {
1631 void* lud = lua_touserdata( L, i); 1631 void* lud = lua_touserdata( L, i);
1632 lua_pushlightuserdata( L2, lud); 1632 lua_pushlightuserdata( L2, lud);
1633 } 1633 }
1634 else // raise an error 1634 else // raise an error
1635 { 1635 {
1636 (void) luaL_error( L, "can't copy non-deep full userdata across lanes"); 1636 (void) luaL_error( L, "can't copy non-deep full userdata across lanes");
1637 } 1637 }
1638 1638
1639 STACK_END( L2, 1); 1639 STACK_END( L2, 1);
1640 STACK_END( L, 0); 1640 STACK_END( L, 0);
1641 return TRUE; 1641 return TRUE;
1642} 1642}
1643 1643
1644static bool_t inter_copy_function( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum e_vt vt, LookupMode mode_, char const* upName_) 1644static bool_t inter_copy_function( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum e_vt vt, LookupMode mode_, char const* upName_)
1645{ 1645{
1646 if( vt == VT_KEY) 1646 if( vt == VT_KEY)
1647 { 1647 {
1648 return FALSE; 1648 return FALSE;
1649 } 1649 }
1650 1650
1651 STACK_CHECK( L, 0); 1651 STACK_CHECK( L, 0);
1652 STACK_CHECK( L2, 0); 1652 STACK_CHECK( L2, 0);
1653 DEBUGSPEW_CODE( fprintf( stderr, "FUNCTION %s\n", upName_)); 1653 DEBUGSPEW_CODE( fprintf( stderr, "FUNCTION %s\n", upName_));
1654 1654
1655 if( lua_tocfunction( L, i) == userdata_clone_sentinel) // we are actually copying a clonable full userdata from a keeper 1655 if( lua_tocfunction( L, i) == userdata_clone_sentinel) // we are actually copying a clonable full userdata from a keeper
1656 { 1656 {
1657 // clone the full userdata again 1657 // clone the full userdata again
1658 size_t userdata_size = 0; 1658 size_t userdata_size = 0;
1659 void* source; 1659 void* source;
1660 void* clone; 1660 void* clone;
1661 1661
1662 // let's see if we already restored this userdata 1662 // let's see if we already restored this userdata
1663 lua_getupvalue( L, i, 2); // ... u 1663 lua_getupvalue( L, i, 2); // ... u
1664 source = lua_touserdata( L, -1); 1664 source = lua_touserdata( L, -1);
1665 lua_pushlightuserdata( L2, source); // ... source 1665 lua_pushlightuserdata( L2, source); // ... source
1666 lua_rawget( L2, L2_cache_i); // ... u? 1666 lua_rawget( L2, L2_cache_i); // ... u?
1667 if( !lua_isnil( L2, -1)) 1667 if( !lua_isnil( L2, -1))
1668 { 1668 {
1669 lua_pop( L, 1); // ... 1669 lua_pop( L, 1); // ...
1670 STACK_MID( L, 0); 1670 STACK_MID( L, 0);
1671 STACK_MID( L2, 1); 1671 STACK_MID( L2, 1);
1672 return TRUE; 1672 return TRUE;
1673 } 1673 }
1674 lua_pop( L2, 1); // ... 1674 lua_pop( L2, 1); // ...
1675 1675
1676 // this function has 2 upvalues: the fqn of its metatable, and the userdata itself 1676 // this function has 2 upvalues: the fqn of its metatable, and the userdata itself
1677 lookup_table( L2, L, i, mode_, upName_); // ... mt 1677 lookup_table( L2, L, i, mode_, upName_); // ... mt
1678 // __lanesclone should always exist because we wouldn't be restoring data from a userdata_clone_sentinel closure to begin with 1678 // __lanesclone should always exist because we wouldn't be restoring data from a userdata_clone_sentinel closure to begin with
1679 lua_getfield( L2, -1, "__lanesclone"); // ... mt __lanesclone 1679 lua_getfield( L2, -1, "__lanesclone"); // ... mt __lanesclone
1680 lua_pushvalue( L2, -1); // ... mt __lanesclone __lanesclone 1680 lua_pushvalue( L2, -1); // ... mt __lanesclone __lanesclone
1681 // 'i' slot is the closure, but from now on it is the actual userdata 1681 // 'i' slot is the closure, but from now on it is the actual userdata
1682 i = lua_gettop( L); 1682 i = lua_gettop( L);
1683 source = lua_touserdata( L, -1); 1683 source = lua_touserdata( L, -1);
1684 // call the cloning function with 1 argument, should return the number of bytes to allocate for the clone 1684 // call the cloning function with 1 argument, should return the number of bytes to allocate for the clone
1685 lua_pushlightuserdata( L2, source); // ... mt __lanesclone __lanesclone source 1685 lua_pushlightuserdata( L2, source); // ... mt __lanesclone __lanesclone source
1686 lua_call( L2, 1, 1); // ... mt __lanesclone size 1686 lua_call( L2, 1, 1); // ... mt __lanesclone size
1687 userdata_size = (size_t) lua_tointeger( L2, -1); // ... mt __lanesclone size 1687 userdata_size = (size_t) lua_tointeger( L2, -1); // ... mt __lanesclone size
1688 lua_pop( L2, 1); // ... mt __lanesclone 1688 lua_pop( L2, 1); // ... mt __lanesclone
1689 { 1689 {
1690 // extract uservalues (don't transfer them yet) 1690 // extract uservalues (don't transfer them yet)
1691 int uvi = 0; 1691 int uvi = 0;
1692 while( lua_getiuservalue( L, i, uvi + 1) != LUA_TNONE) // ... u uv 1692 while( lua_getiuservalue( L, i, uvi + 1) != LUA_TNONE) // ... u uv
1693 { 1693 {
1694 ++ uvi; 1694 ++ uvi;
1695 } 1695 }
1696 // when lua_getiuservalue() returned LUA_TNONE, it pushed a nil. pop it now 1696 // when lua_getiuservalue() returned LUA_TNONE, it pushed a nil. pop it now
1697 lua_pop( L, 1); // ... u [uv]* 1697 lua_pop( L, 1); // ... u [uv]*
1698 STACK_MID( L, uvi + 1); 1698 STACK_MID( L, uvi + 1);
1699 // create the clone userdata with the required number of uservalue slots 1699 // create the clone userdata with the required number of uservalue slots
1700 clone = lua_newuserdatauv( L2, userdata_size, uvi); // ... mt __lanesclone u 1700 clone = lua_newuserdatauv( L2, userdata_size, uvi); // ... mt __lanesclone u
1701 // add it in the cache 1701 // add it in the cache
1702 lua_pushlightuserdata( L2, source); // ... mt __lanesclone u source 1702 lua_pushlightuserdata( L2, source); // ... mt __lanesclone u source
1703 lua_pushvalue( L2, -2); // ... mt __lanesclone u source u 1703 lua_pushvalue( L2, -2); // ... mt __lanesclone u source u
1704 lua_rawset( L2, L2_cache_i); // ... mt __lanesclone u 1704 lua_rawset( L2, L2_cache_i); // ... mt __lanesclone u
1705 // set metatable 1705 // set metatable
1706 lua_pushvalue( L2, -3); // ... mt __lanesclone u mt 1706 lua_pushvalue( L2, -3); // ... mt __lanesclone u mt
1707 lua_setmetatable( L2, -2); // ... mt __lanesclone u 1707 lua_setmetatable( L2, -2); // ... mt __lanesclone u
1708 // transfer and assign uservalues 1708 // transfer and assign uservalues
1709 while( uvi > 0) 1709 while( uvi > 0)
1710 { 1710 {
1711 inter_copy_one( U, L2, L2_cache_i, L, lua_absindex( L, -1), vt, mode_, upName_); // ... mt __lanesclone u uv 1711 inter_copy_one( U, L2, L2_cache_i, L, lua_absindex( L, -1), vt, mode_, upName_); // ... mt __lanesclone u uv
1712 lua_pop( L, 1); // ... u [uv]* 1712 lua_pop( L, 1); // ... u [uv]*
1713 // this pops the value from the stack 1713 // this pops the value from the stack
1714 lua_setiuservalue( L2, -2, uvi); // ... mt __lanesclone u 1714 lua_setiuservalue( L2, -2, uvi); // ... mt __lanesclone u
1715 -- uvi; 1715 -- uvi;
1716 } 1716 }
1717 // when we are done, all uservalues are popped from the stack 1717 // when we are done, all uservalues are popped from the stack
1718 lua_pop( L, 1); // ... 1718 lua_pop( L, 1); // ...
1719 STACK_MID( L, 0); 1719 STACK_MID( L, 0);
1720 STACK_MID( L2, 3); // ... mt __lanesclone u 1720 STACK_MID( L2, 3); // ... mt __lanesclone u
1721 } 1721 }
1722 // perform the custom cloning part 1722 // perform the custom cloning part
1723 lua_replace( L2, -3); // ... u __lanesclone 1723 lua_replace( L2, -3); // ... u __lanesclone
1724 lua_pushlightuserdata( L2, clone); // ... u __lanesclone clone 1724 lua_pushlightuserdata( L2, clone); // ... u __lanesclone clone
1725 lua_pushlightuserdata( L2, source); // ... u __lanesclone clone source 1725 lua_pushlightuserdata( L2, source); // ... u __lanesclone clone source
1726 lua_call( L2, 2, 0); // ... u 1726 lua_call( L2, 2, 0); // ... u
1727 } 1727 }
1728 else 1728 else
1729 { 1729 {
1730 DEBUGSPEW_CODE( fprintf( stderr, "FUNCTION %s\n", upName_)); 1730 DEBUGSPEW_CODE( fprintf( stderr, "FUNCTION %s\n", upName_));
1731 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); 1731 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth);
1732 STACK_CHECK( L2, 0); 1732 STACK_CHECK( L2, 0);
1733 copy_cached_func( U, L2, L2_cache_i, L, i, mode_, upName_); 1733 copy_cached_func( U, L2, L2_cache_i, L, i, mode_, upName_);
1734 STACK_END( L2, 1); 1734 STACK_END( L2, 1);
1735 DEBUGSPEW_CODE( -- U->debugspew_indent_depth); 1735 DEBUGSPEW_CODE( -- U->debugspew_indent_depth);
1736 } 1736 }
1737 STACK_END( L2, 1); 1737 STACK_END( L2, 1);
1738 STACK_END( L, 0); 1738 STACK_END( L, 0);
1739 return TRUE; 1739 return TRUE;
1740} 1740}
1741 1741
1742static bool_t inter_copy_table( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum e_vt vt, LookupMode mode_, char const* upName_) 1742static bool_t inter_copy_table( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum e_vt vt, LookupMode mode_, char const* upName_)
1743{ 1743{
1744 if( vt == VT_KEY) 1744 if( vt == VT_KEY)
1745 { 1745 {
1746 return FALSE; 1746 return FALSE;
1747 } 1747 }
1748 1748
1749 STACK_CHECK( L, 0); 1749 STACK_CHECK( L, 0);
1750 STACK_CHECK( L2, 0); 1750 STACK_CHECK( L2, 0);
1751 DEBUGSPEW_CODE( fprintf( stderr, "TABLE %s\n", upName_)); 1751 DEBUGSPEW_CODE( fprintf( stderr, "TABLE %s\n", upName_));
1752 1752
1753 /* 1753 /*
1754 * First, let's try to see if this table is special (aka is it some table that we registered in our lookup databases during module registration?) 1754 * First, let's try to see if this table is special (aka is it some table that we registered in our lookup databases during module registration?)
1755 * Note that this table CAN be a module table, but we just didn't register it, in which case we'll send it through the table cloning mechanism 1755 * Note that this table CAN be a module table, but we just didn't register it, in which case we'll send it through the table cloning mechanism
1756 */ 1756 */
1757 if( lookup_table( L2, L, i, mode_, upName_)) 1757 if( lookup_table( L2, L, i, mode_, upName_))
1758 { 1758 {
1759 ASSERT_L( lua_istable( L2, -1) || (lua_tocfunction( L2, -1) == table_lookup_sentinel)); // from lookup datables // can also be table_lookup_sentinel if this is a table we know 1759 ASSERT_L( lua_istable( L2, -1) || (lua_tocfunction( L2, -1) == table_lookup_sentinel)); // from lookup datables // can also be table_lookup_sentinel if this is a table we know
1760 return TRUE; 1760 return TRUE;
1761 } 1761 }
1762 1762
1763 /* Check if we've already copied the same table from 'L' (during this transmission), and 1763 /* Check if we've already copied the same table from 'L' (during this transmission), and
1764 * reuse the old copy. This allows table upvalues shared by multiple 1764 * reuse the old copy. This allows table upvalues shared by multiple
1765 * local functions to point to the same table, also in the target. 1765 * local functions to point to the same table, also in the target.
1766 * Also, this takes care of cyclic tables and multiple references 1766 * Also, this takes care of cyclic tables and multiple references
1767 * to the same subtable. 1767 * to the same subtable.
1768 * 1768 *
1769 * Note: Even metatables need to go through this test; to detect 1769 * Note: Even metatables need to go through this test; to detect
1770 * loops such as those in required module tables (getmetatable(lanes).lanes == lanes) 1770 * loops such as those in required module tables (getmetatable(lanes).lanes == lanes)
1771 */ 1771 */
1772 if( push_cached_table( L2, L2_cache_i, L, i)) 1772 if( push_cached_table( L2, L2_cache_i, L, i))
1773 { 1773 {
1774 ASSERT_L( lua_istable( L2, -1)); // from cache 1774 ASSERT_L( lua_istable( L2, -1)); // from cache
1775 return TRUE; 1775 return TRUE;
1776 } 1776 }
1777 ASSERT_L( lua_istable( L2, -1)); 1777 ASSERT_L( lua_istable( L2, -1));
1778 1778
1779 STACK_GROW( L, 2); 1779 STACK_GROW( L, 2);
1780 STACK_GROW( L2, 2); 1780 STACK_GROW( L2, 2);
1781 1781
1782 lua_pushnil( L); // start iteration 1782 lua_pushnil( L); // start iteration
1783 while( lua_next( L, i)) 1783 while( lua_next( L, i))
1784 { 1784 {
1785 // need a function to prevent overflowing the stack with verboseErrors-induced alloca() 1785 // need a function to prevent overflowing the stack with verboseErrors-induced alloca()
1786 inter_copy_keyvaluepair( U, L2, L2_cache_i, L, vt, mode_, upName_); 1786 inter_copy_keyvaluepair( U, L2, L2_cache_i, L, vt, mode_, upName_);
1787 lua_pop( L, 1); // pop value (next round) 1787 lua_pop( L, 1); // pop value (next round)
1788 } 1788 }
1789 STACK_MID( L, 0); 1789 STACK_MID( L, 0);
1790 STACK_MID( L2, 1); 1790 STACK_MID( L2, 1);
1791 1791
1792 // Metatables are expected to be immutable, and copied only once. 1792 // Metatables are expected to be immutable, and copied only once.
1793 if( push_cached_metatable( U, L2, L2_cache_i, L, i, mode_, upName_)) // ... t mt? 1793 if( push_cached_metatable( U, L2, L2_cache_i, L, i, mode_, upName_)) // ... t mt?
1794 { 1794 {
1795 lua_setmetatable( L2, -2); // ... t 1795 lua_setmetatable( L2, -2); // ... t
1796 } 1796 }
1797 STACK_END( L2, 1); 1797 STACK_END( L2, 1);
1798 STACK_END( L, 0); 1798 STACK_END( L, 0);
1799 return TRUE; 1799 return TRUE;
1800} 1800}
1801 1801
1802/* 1802/*
@@ -1811,118 +1811,118 @@ static bool_t inter_copy_table( Universe* U, lua_State* L2, uint_t L2_cache_i, l
1811*/ 1811*/
1812bool_t inter_copy_one( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum e_vt vt, LookupMode mode_, char const* upName_) 1812bool_t inter_copy_one( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum e_vt vt, LookupMode mode_, char const* upName_)
1813{ 1813{
1814 bool_t ret = TRUE; 1814 bool_t ret = TRUE;
1815 int val_type = lua_type( L, i); 1815 int val_type = lua_type( L, i);
1816 static int const pod_mask = (1 << LUA_TNIL) | (1 << LUA_TBOOLEAN) | (1 << LUA_TLIGHTUSERDATA) | (1 << LUA_TNUMBER) | (1 << LUA_TSTRING); 1816 static int const pod_mask = (1 << LUA_TNIL) | (1 << LUA_TBOOLEAN) | (1 << LUA_TLIGHTUSERDATA) | (1 << LUA_TNUMBER) | (1 << LUA_TSTRING);
1817 STACK_GROW( L2, 1); 1817 STACK_GROW( L2, 1);
1818 STACK_CHECK( L, 0); // L // L2 1818 STACK_CHECK( L, 0); // L // L2
1819 STACK_CHECK( L2, 0); // L // L2 1819 STACK_CHECK( L2, 0); // L // L2
1820 1820
1821 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "inter_copy_one()\n" INDENT_END)); 1821 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "inter_copy_one()\n" INDENT_END));
1822 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); 1822 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth);
1823 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%s %s: " INDENT_END, lua_type_names[val_type], vt_names[vt])); 1823 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%s %s: " INDENT_END, lua_type_names[val_type], vt_names[vt]));
1824 1824
1825 // Non-POD can be skipped if its metatable contains { __lanesignore = true } 1825 // Non-POD can be skipped if its metatable contains { __lanesignore = true }
1826 if( ((1 << val_type) & pod_mask) == 0) 1826 if( ((1 << val_type) & pod_mask) == 0)
1827 { 1827 {
1828 if( lua_getmetatable( L, i)) // ... mt 1828 if( lua_getmetatable( L, i)) // ... mt
1829 { 1829 {
1830 lua_getfield( L, -1, "__lanesignore"); // ... mt ignore? 1830 lua_getfield( L, -1, "__lanesignore"); // ... mt ignore?
1831 if( lua_isboolean( L, -1) && lua_toboolean( L, -1)) 1831 if( lua_isboolean( L, -1) && lua_toboolean( L, -1))
1832 { 1832 {
1833 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "__lanesignore -> LUA_TNIL\n" INDENT_END)); 1833 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "__lanesignore -> LUA_TNIL\n" INDENT_END));
1834 val_type = LUA_TNIL; 1834 val_type = LUA_TNIL;
1835 } 1835 }
1836 lua_pop( L, 2); // ... 1836 lua_pop( L, 2); // ...
1837 } 1837 }
1838 } 1838 }
1839 STACK_MID( L, 0); 1839 STACK_MID( L, 0);
1840 1840
1841 /* Lets push nil to L2 if the object should be ignored */ 1841 /* Lets push nil to L2 if the object should be ignored */
1842 switch( val_type) 1842 switch( val_type)
1843 { 1843 {
1844 /* Basic types allowed both as values, and as table keys */ 1844 /* Basic types allowed both as values, and as table keys */
1845 1845
1846 case LUA_TBOOLEAN: 1846 case LUA_TBOOLEAN:
1847 { 1847 {
1848 bool_t v = lua_toboolean( L, i); 1848 bool_t v = lua_toboolean( L, i);
1849 DEBUGSPEW_CODE( fprintf( stderr, "%s\n", v ? "true" : "false")); 1849 DEBUGSPEW_CODE( fprintf( stderr, "%s\n", v ? "true" : "false"));
1850 lua_pushboolean( L2, v); 1850 lua_pushboolean( L2, v);
1851 } 1851 }
1852 break; 1852 break;
1853 1853
1854 case LUA_TNUMBER: 1854 case LUA_TNUMBER:
1855 /* LNUM patch support (keeping integer accuracy) */ 1855 /* LNUM patch support (keeping integer accuracy) */
1856#if defined LUA_LNUM || LUA_VERSION_NUM >= 503 1856#if defined LUA_LNUM || LUA_VERSION_NUM >= 503
1857 if( lua_isinteger( L, i)) 1857 if( lua_isinteger( L, i))
1858 { 1858 {
1859 lua_Integer v = lua_tointeger( L, i); 1859 lua_Integer v = lua_tointeger( L, i);
1860 DEBUGSPEW_CODE( fprintf( stderr, LUA_INTEGER_FMT "\n", v)); 1860 DEBUGSPEW_CODE( fprintf( stderr, LUA_INTEGER_FMT "\n", v));
1861 lua_pushinteger( L2, v); 1861 lua_pushinteger( L2, v);
1862 break; 1862 break;
1863 } 1863 }
1864 else 1864 else
1865#endif // defined LUA_LNUM || LUA_VERSION_NUM >= 503 1865#endif // defined LUA_LNUM || LUA_VERSION_NUM >= 503
1866 { 1866 {
1867 lua_Number v = lua_tonumber( L, i); 1867 lua_Number v = lua_tonumber( L, i);
1868 DEBUGSPEW_CODE( fprintf( stderr, LUA_NUMBER_FMT "\n", v)); 1868 DEBUGSPEW_CODE( fprintf( stderr, LUA_NUMBER_FMT "\n", v));
1869 lua_pushnumber( L2, v); 1869 lua_pushnumber( L2, v);
1870 } 1870 }
1871 break; 1871 break;
1872 1872
1873 case LUA_TSTRING: 1873 case LUA_TSTRING:
1874 { 1874 {
1875 size_t len; 1875 size_t len;
1876 char const* s = lua_tolstring( L, i, &len); 1876 char const* s = lua_tolstring( L, i, &len);
1877 DEBUGSPEW_CODE( fprintf( stderr, "'%s'\n", s)); 1877 DEBUGSPEW_CODE( fprintf( stderr, "'%s'\n", s));
1878 lua_pushlstring( L2, s, len); 1878 lua_pushlstring( L2, s, len);
1879 } 1879 }
1880 break; 1880 break;
1881 1881
1882 case LUA_TLIGHTUSERDATA: 1882 case LUA_TLIGHTUSERDATA:
1883 { 1883 {
1884 void* p = lua_touserdata( L, i); 1884 void* p = lua_touserdata( L, i);
1885 DEBUGSPEW_CODE( fprintf( stderr, "%p\n", p)); 1885 DEBUGSPEW_CODE( fprintf( stderr, "%p\n", p));
1886 lua_pushlightuserdata( L2, p); 1886 lua_pushlightuserdata( L2, p);
1887 } 1887 }
1888 break; 1888 break;
1889 1889
1890 /* The following types are not allowed as table keys */ 1890 /* The following types are not allowed as table keys */
1891 1891
1892 case LUA_TUSERDATA: 1892 case LUA_TUSERDATA:
1893 ret = inter_copy_userdata( U, L2, L2_cache_i, L, i, vt, mode_, upName_); 1893 ret = inter_copy_userdata( U, L2, L2_cache_i, L, i, vt, mode_, upName_);
1894 break; 1894 break;
1895 1895
1896 case LUA_TNIL: 1896 case LUA_TNIL:
1897 if( vt == VT_KEY) 1897 if( vt == VT_KEY)
1898 { 1898 {
1899 ret = FALSE; 1899 ret = FALSE;
1900 break; 1900 break;
1901 } 1901 }
1902 lua_pushnil( L2); 1902 lua_pushnil( L2);
1903 break; 1903 break;
1904 1904
1905 case LUA_TFUNCTION: 1905 case LUA_TFUNCTION:
1906 ret = inter_copy_function( U, L2, L2_cache_i, L, i, vt, mode_, upName_); 1906 ret = inter_copy_function( U, L2, L2_cache_i, L, i, vt, mode_, upName_);
1907 break; 1907 break;
1908 1908
1909 case LUA_TTABLE: 1909 case LUA_TTABLE:
1910 ret = inter_copy_table( U, L2, L2_cache_i, L, i, vt, mode_, upName_); 1910 ret = inter_copy_table( U, L2, L2_cache_i, L, i, vt, mode_, upName_);
1911 break; 1911 break;
1912 1912
1913 /* The following types cannot be copied */ 1913 /* The following types cannot be copied */
1914 1914
1915 case 10: // LuaJIT CDATA 1915 case 10: // LuaJIT CDATA
1916 case LUA_TTHREAD: 1916 case LUA_TTHREAD:
1917 ret = FALSE; 1917 ret = FALSE;
1918 break; 1918 break;
1919 } 1919 }
1920 1920
1921 DEBUGSPEW_CODE( -- U->debugspew_indent_depth); 1921 DEBUGSPEW_CODE( -- U->debugspew_indent_depth);
1922 1922
1923 STACK_END( L2, ret ? 1 : 0); 1923 STACK_END( L2, ret ? 1 : 0);
1924 STACK_END( L, 0); 1924 STACK_END( L, 0);
1925 return ret; 1925 return ret;
1926} 1926}
1927 1927
1928/* 1928/*
@@ -1934,122 +1934,122 @@ bool_t inter_copy_one( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State*
1934*/ 1934*/
1935int luaG_inter_copy( Universe* U, lua_State* L, lua_State* L2, uint_t n, LookupMode mode_) 1935int luaG_inter_copy( Universe* U, lua_State* L, lua_State* L2, uint_t n, LookupMode mode_)
1936{ 1936{
1937 uint_t top_L = lua_gettop( L); // ... {}n 1937 uint_t top_L = lua_gettop( L); // ... {}n
1938 uint_t top_L2 = lua_gettop( L2); // ... 1938 uint_t top_L2 = lua_gettop( L2); // ...
1939 uint_t i, j; 1939 uint_t i, j;
1940 char tmpBuf[16]; 1940 char tmpBuf[16];
1941 char const* pBuf = U->verboseErrors ? tmpBuf : "?"; 1941 char const* pBuf = U->verboseErrors ? tmpBuf : "?";
1942 bool_t copyok = TRUE; 1942 bool_t copyok = TRUE;
1943 1943
1944 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_inter_copy()\n" INDENT_END)); 1944 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_inter_copy()\n" INDENT_END));
1945 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); 1945 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth);
1946 1946
1947 if( n > top_L) 1947 if( n > top_L)
1948 { 1948 {
1949 // requesting to copy more than is available? 1949 // requesting to copy more than is available?
1950 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "nothing to copy()\n" INDENT_END)); 1950 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "nothing to copy()\n" INDENT_END));
1951 DEBUGSPEW_CODE( -- U->debugspew_indent_depth); 1951 DEBUGSPEW_CODE( -- U->debugspew_indent_depth);
1952 return -1; 1952 return -1;
1953 } 1953 }
1954 1954
1955 STACK_CHECK( L2, 0); 1955 STACK_CHECK( L2, 0);
1956 STACK_GROW( L2, n + 1); 1956 STACK_GROW( L2, n + 1);
1957 1957
1958 /* 1958 /*
1959 * Make a cache table for the duration of this copy. Collects tables and 1959 * Make a cache table for the duration of this copy. Collects tables and
1960 * function entries, avoiding the same entries to be passed on as multiple 1960 * function entries, avoiding the same entries to be passed on as multiple
1961 * copies. ESSENTIAL i.e. for handling upvalue tables in the right manner! 1961 * copies. ESSENTIAL i.e. for handling upvalue tables in the right manner!
1962 */ 1962 */
1963 lua_newtable( L2); // ... cache 1963 lua_newtable( L2); // ... cache
1964 1964
1965 STACK_CHECK( L, 0); 1965 STACK_CHECK( L, 0);
1966 for( i = top_L - n + 1, j = 1; i <= top_L; ++ i, ++ j) 1966 for( i = top_L - n + 1, j = 1; i <= top_L; ++ i, ++ j)
1967 { 1967 {
1968 if( U->verboseErrors) 1968 if( U->verboseErrors)
1969 { 1969 {
1970 sprintf( tmpBuf, "arg_%d", j); 1970 sprintf( tmpBuf, "arg_%d", j);
1971 } 1971 }
1972 copyok = inter_copy_one( U, L2, top_L2 + 1, L, i, VT_NORMAL, mode_, pBuf); // ... cache {}n 1972 copyok = inter_copy_one( U, L2, top_L2 + 1, L, i, VT_NORMAL, mode_, pBuf); // ... cache {}n
1973 if( !copyok) 1973 if( !copyok)
1974 { 1974 {
1975 break; 1975 break;
1976 } 1976 }
1977 } 1977 }
1978 STACK_END( L, 0); 1978 STACK_END( L, 0);
1979 1979
1980 DEBUGSPEW_CODE( -- U->debugspew_indent_depth); 1980 DEBUGSPEW_CODE( -- U->debugspew_indent_depth);
1981 1981
1982 if( copyok) 1982 if( copyok)
1983 { 1983 {
1984 STACK_MID( L2, n + 1); 1984 STACK_MID( L2, n + 1);
1985 // Remove the cache table. Persistent caching would cause i.e. multiple 1985 // Remove the cache table. Persistent caching would cause i.e. multiple
1986 // messages passed in the same table to use the same table also in receiving end. 1986 // messages passed in the same table to use the same table also in receiving end.
1987 lua_remove( L2, top_L2 + 1); 1987 lua_remove( L2, top_L2 + 1);
1988 return 0; 1988 return 0;
1989 } 1989 }
1990 1990
1991 // error -> pop everything from the target state stack 1991 // error -> pop everything from the target state stack
1992 lua_settop( L2, top_L2); 1992 lua_settop( L2, top_L2);
1993 STACK_END( L2, 0); 1993 STACK_END( L2, 0);
1994 return -2; 1994 return -2;
1995} 1995}
1996 1996
1997 1997
1998int luaG_inter_move( Universe* U, lua_State* L, lua_State* L2, uint_t n, LookupMode mode_) 1998int luaG_inter_move( Universe* U, lua_State* L, lua_State* L2, uint_t n, LookupMode mode_)
1999{ 1999{
2000 int ret = luaG_inter_copy( U, L, L2, n, mode_); 2000 int ret = luaG_inter_copy( U, L, L2, n, mode_);
2001 lua_pop( L, (int) n); 2001 lua_pop( L, (int) n);
2002 return ret; 2002 return ret;
2003} 2003}
2004 2004
2005int luaG_inter_copy_package( Universe* U, lua_State* L, lua_State* L2, int package_idx_, LookupMode mode_) 2005int luaG_inter_copy_package( Universe* U, lua_State* L, lua_State* L2, int package_idx_, LookupMode mode_)
2006{ 2006{
2007 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_inter_copy_package()\n" INDENT_END)); 2007 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_inter_copy_package()\n" INDENT_END));
2008 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); 2008 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth);
2009 // package 2009 // package
2010 STACK_CHECK( L, 0); 2010 STACK_CHECK( L, 0);
2011 STACK_CHECK( L2, 0); 2011 STACK_CHECK( L2, 0);
2012 package_idx_ = lua_absindex( L, package_idx_); 2012 package_idx_ = lua_absindex( L, package_idx_);
2013 if( lua_type( L, package_idx_) != LUA_TTABLE) 2013 if( lua_type( L, package_idx_) != LUA_TTABLE)
2014 { 2014 {
2015 lua_pushfstring( L, "expected package as table, got %s", luaL_typename( L, package_idx_)); 2015 lua_pushfstring( L, "expected package as table, got %s", luaL_typename( L, package_idx_));
2016 STACK_MID( L, 1); 2016 STACK_MID( L, 1);
2017 // raise the error when copying from lane to lane, else just leave it on the stack to be raised later 2017 // raise the error when copying from lane to lane, else just leave it on the stack to be raised later
2018 return ( mode_ == eLM_LaneBody) ? lua_error( L) : 1; 2018 return ( mode_ == eLM_LaneBody) ? lua_error( L) : 1;
2019 } 2019 }
2020 lua_getglobal( L2, "package"); 2020 lua_getglobal( L2, "package");
2021 if( !lua_isnil( L2, -1)) // package library not loaded: do nothing 2021 if( !lua_isnil( L2, -1)) // package library not loaded: do nothing
2022 { 2022 {
2023 int i; 2023 int i;
2024 // package.loaders is renamed package.searchers in Lua 5.2 2024 // package.loaders is renamed package.searchers in Lua 5.2
2025 // but don't copy it anyway, as the function names change depending on the slot index! 2025 // but don't copy it anyway, as the function names change depending on the slot index!
2026 // users should provide an on_state_create function to setup custom loaders instead 2026 // users should provide an on_state_create function to setup custom loaders instead
2027 // don't copy package.preload in keeper states (they don't know how to translate functions) 2027 // don't copy package.preload in keeper states (they don't know how to translate functions)
2028 char const* entries[] = { "path", "cpath", (mode_ == eLM_LaneBody) ? "preload" : NULL/*, (LUA_VERSION_NUM == 501) ? "loaders" : "searchers"*/, NULL}; 2028 char const* entries[] = { "path", "cpath", (mode_ == eLM_LaneBody) ? "preload" : NULL/*, (LUA_VERSION_NUM == 501) ? "loaders" : "searchers"*/, NULL};
2029 for( i = 0; entries[i]; ++ i) 2029 for( i = 0; entries[i]; ++ i)
2030 { 2030 {
2031 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "package.%s\n" INDENT_END, entries[i])); 2031 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "package.%s\n" INDENT_END, entries[i]));
2032 lua_getfield( L, package_idx_, entries[i]); 2032 lua_getfield( L, package_idx_, entries[i]);
2033 if( lua_isnil( L, -1)) 2033 if( lua_isnil( L, -1))
2034 { 2034 {
2035 lua_pop( L, 1); 2035 lua_pop( L, 1);
2036 } 2036 }
2037 else 2037 else
2038 { 2038 {
2039 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); 2039 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth);
2040 luaG_inter_move( U, L, L2, 1, mode_); // moves the entry to L2 2040 luaG_inter_move( U, L, L2, 1, mode_); // moves the entry to L2
2041 DEBUGSPEW_CODE( -- U->debugspew_indent_depth); 2041 DEBUGSPEW_CODE( -- U->debugspew_indent_depth);
2042 lua_setfield( L2, -2, entries[i]); // set package[entries[i]] 2042 lua_setfield( L2, -2, entries[i]); // set package[entries[i]]
2043 } 2043 }
2044 } 2044 }
2045 } 2045 }
2046 else 2046 else
2047 { 2047 {
2048 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "'package' not loaded, nothing to do\n" INDENT_END)); 2048 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "'package' not loaded, nothing to do\n" INDENT_END));
2049 } 2049 }
2050 lua_pop( L2, 1); 2050 lua_pop( L2, 1);
2051 STACK_END( L2, 0); 2051 STACK_END( L2, 0);
2052 STACK_END( L, 0); 2052 STACK_END( L, 0);
2053 DEBUGSPEW_CODE( -- U->debugspew_indent_depth); 2053 DEBUGSPEW_CODE( -- U->debugspew_indent_depth);
2054 return 0; 2054 return 0;
2055} 2055}