summaryrefslogtreecommitdiff
path: root/src/tools.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools.c')
-rw-r--r--src/tools.c121
1 files changed, 79 insertions, 42 deletions
diff --git a/src/tools.c b/src/tools.c
index 41163c4..29959a8 100644
--- a/src/tools.c
+++ b/src/tools.c
@@ -395,65 +395,102 @@ void luaG_push_proxy( lua_State *L, luaG_IdFunction idfunc, DEEP_PRELUDE *prelud
395 395
396 if (lua_isnil(L,-1)) 396 if (lua_isnil(L,-1))
397 { 397 {
398 int oldtop;
399 // No metatable yet. We have two things to do: 398 // No metatable yet. We have two things to do:
400
401 // 1 - make one and register it 399 // 1 - make one and register it
402 lua_pop(L,1); 400 {
401 int oldtop;
403 402
404 // tbl= idfunc( "metatable" ) 403 lua_pop( L, 1);
405 //
406 oldtop = lua_gettop( L);
407 idfunc( L, "metatable");
408 //
409 // [-2]: proxy
410 // [-1]: metatable (returned by 'idfunc')
411 404
412 if (lua_gettop( L) - oldtop != 1 || !lua_istable(L, -1)) 405 // tbl= idfunc( "metatable" )
413 { 406 //
414 luaL_error( L, "Bad idfunc on \"metatable\": did not return one" ); 407 oldtop = lua_gettop( L);
415 } 408 idfunc( L, "metatable");
409 //
410 // [-2]: proxy
411 // [-1]: metatable (returned by 'idfunc')
416 412
417 // Add '__gc' method 413 if (lua_gettop( L) - oldtop != 1 || !lua_istable(L, -1))
418 // 414 {
419 lua_pushcfunction( L, deep_userdata_gc ); 415 luaL_error( L, "Bad idfunc on \"metatable\": did not return one" );
420 lua_setfield( L, -2, "__gc" ); 416 }
421 417
422 // Memorize for later rounds 418 // Add '__gc' method
423 // 419 //
424 lua_pushvalue( L,-1 ); 420 lua_pushcfunction( L, deep_userdata_gc );
425 lua_pushlightuserdata( L, idfunc ); 421 lua_setfield( L, -2, "__gc" );
426 // 422
427 // [-4]: proxy 423 // Memorize for later rounds
428 // [-3]: metatable (2nd ref) 424 //
429 // [-2]: metatable 425 lua_pushvalue( L,-1 );
430 // [-1]: idfunc 426 lua_pushlightuserdata( L, idfunc );
427 //
428 // [-4]: proxy
429 // [-3]: metatable (2nd ref)
430 // [-2]: metatable
431 // [-1]: idfunc
431 432
432 set_deep_lookup(L); 433 set_deep_lookup(L);
434 }
433 435
434 // 2 - cause the target state to require the module that exported the idfunc 436 // 2 - cause the target state to require the module that exported the idfunc
435 // this is needed because we must make sure the shared library is still loaded as long as we hold a pointer on the idfunc 437 // this is needed because we must make sure the shared library is still loaded as long as we hold a pointer on the idfunc
436 lua_getglobal( L, "require"); 438 STACK_CHECK(L)
437 if( lua_isfunction( L, -1)) // just in case...
438 { 439 {
440 char const * modname;
439 // make sure the function pushed a single value on the stack! 441 // make sure the function pushed a single value on the stack!
440 int oldtop = lua_gettop( L);
441 idfunc( L, "module");
442 if( lua_gettop( L) - oldtop != 1 || !lua_isstring( L, -1))
443 { 442 {
444 luaL_error( L, "Bad idfunc on \"module\": should return a string"); 443 int oldtop = lua_gettop( L);
444 idfunc( L, "module"); // ... "module"/nil
445 if( lua_gettop( L) - oldtop != 1)
446 {
447 luaL_error( L, "Bad idfunc on \"module\": should return a single value");
448 }
445 } 449 }
446 // if we are inside a call to require, this will raise a "reentrency" error that we absorb silently (we don't care, this probably means the module is already being required, which is what we need) 450 modname = luaL_optstring( L, -1, NULL); // raises an error if not a string or nil
447 if( lua_pcall( L, 1, 0, 0) != 0) 451 if( modname) // we actually got a module name
448 { 452 {
449 //char const * const errMsg = lua_tostring( L, -1); // just to see it in the debugger 453 // somehow, L.registry._LOADED can exist without having registered the 'package' library.
450 lua_pop( L, 1); 454 lua_getglobal( L, "require"); // ... "module" require()
455 // check that the module is already loaded (or being loaded, we are happy either way)
456 if( lua_isfunction( L, -1))
457 {
458 lua_insert( L, -2); // ... require() "module"
459 lua_getfield( L, LUA_REGISTRYINDEX, "_LOADED"); // ... require() "module" L.registry._LOADED
460 if( lua_istable( L, -1))
461 {
462 bool_t alreadyloaded;
463 lua_pushvalue( L, -2); // ... require() "module" L.registry._LOADED "module"
464 lua_rawget( L, -2); // ... require() "module" L.registry._LOADED module
465 alreadyloaded = lua_toboolean( L, -1);
466 if( !alreadyloaded) // not loaded
467 {
468 lua_pop( L, 2); // ... require() "module"
469 lua_call( L, 1, 0); // call require "modname" // ...
470 }
471 else // already loaded, we are happy
472 {
473 lua_pop( L, 4); // ...
474 }
475 }
476 else // no L.registry._LOADED; can this ever happen?
477 {
478 luaL_error( L, "unexpected error while requiring a module");
479 lua_pop( L, 3); // ...
480 }
481 }
482 else // a module name, but no require() function :-(
483 {
484 luaL_error( L, "lanes receiving deep userdata should register the 'package' library");
485 lua_pop( L, 2); // ...
486 }
487 }
488 else // no module name
489 {
490 lua_pop( L, 1); // ...
451 } 491 }
452 } 492 }
453 else 493 STACK_END(L,0)
454 {
455 lua_pop( L, 1);
456 }
457 } 494 }
458 STACK_MID(L,2) 495 STACK_MID(L,2)
459 ASSERT_L( lua_isuserdata(L,-2) ); 496 ASSERT_L( lua_isuserdata(L,-2) );