diff options
-rw-r--r-- | CHANGES | 4 | ||||
-rw-r--r-- | src/keeper.c | 43 | ||||
-rw-r--r-- | src/lanes.c | 151 | ||||
-rw-r--r-- | src/lanes.lua | 2 | ||||
-rw-r--r-- | src/tools.c | 577 | ||||
-rw-r--r-- | src/tools.h | 17 |
6 files changed, 456 insertions, 338 deletions
@@ -1,5 +1,9 @@ | |||
1 | CHANGES: | 1 | CHANGES: |
2 | 2 | ||
3 | CHANGE 57: BGe 28-Jan-13 | ||
4 | * More detailed DEBUG_SPEW logs | ||
5 | * A bit of code cosmetics | ||
6 | |||
3 | CHANGE 56: BGe 25-Jan-13 | 7 | CHANGE 56: BGe 25-Jan-13 |
4 | * version 3.4.4 | 8 | * version 3.4.4 |
5 | * bugfix: take into account the fact that "coroutine" is no longer part of base library in Lua 5.2 | 9 | * bugfix: take into account the fact that "coroutine" is no longer part of base library in Lua 5.2 |
diff --git a/src/keeper.c b/src/keeper.c index 516fe85..7485110 100644 --- a/src/keeper.c +++ b/src/keeper.c | |||
@@ -163,7 +163,7 @@ static void* const fifos_key = (void*) prepare_fifo_access; | |||
163 | static void push_table( lua_State* L, int idx) | 163 | static void push_table( lua_State* L, int idx) |
164 | { | 164 | { |
165 | STACK_GROW( L, 4); | 165 | STACK_GROW( L, 4); |
166 | STACK_CHECK( L) | 166 | STACK_CHECK( L); |
167 | idx = lua_absindex( L, idx); | 167 | idx = lua_absindex( L, idx); |
168 | lua_pushlightuserdata( L, fifos_key); // ud fifos_key | 168 | lua_pushlightuserdata( L, fifos_key); // ud fifos_key |
169 | lua_rawget( L, LUA_REGISTRYINDEX); // ud fifos | 169 | lua_rawget( L, LUA_REGISTRYINDEX); // ud fifos |
@@ -187,7 +187,7 @@ int keeper_push_linda_storage( lua_State* L, void* ptr) | |||
187 | { | 187 | { |
188 | struct s_Keeper* K = keeper_acquire( ptr); | 188 | struct s_Keeper* K = keeper_acquire( ptr); |
189 | lua_State* KL = K->L; | 189 | lua_State* KL = K->L; |
190 | STACK_CHECK( KL) | 190 | STACK_CHECK( KL); |
191 | lua_pushlightuserdata( KL, fifos_key); // fifos_key | 191 | lua_pushlightuserdata( KL, fifos_key); // fifos_key |
192 | lua_rawget( KL, LUA_REGISTRYINDEX); // fifos | 192 | lua_rawget( KL, LUA_REGISTRYINDEX); // fifos |
193 | lua_pushlightuserdata( KL, ptr); // fifos ud | 193 | lua_pushlightuserdata( KL, ptr); // fifos ud |
@@ -206,7 +206,7 @@ int keeper_push_linda_storage( lua_State* L, void* ptr) | |||
206 | keeper_fifo* fifo = prepare_fifo_access( KL, -1); // storage key fifo | 206 | keeper_fifo* fifo = prepare_fifo_access( KL, -1); // storage key fifo |
207 | lua_pushvalue( KL, -2); // storage key fifo key | 207 | lua_pushvalue( KL, -2); // storage key fifo key |
208 | luaG_inter_move( KL, L, 1); // storage key fifo // out key | 208 | luaG_inter_move( KL, L, 1); // storage key fifo // out key |
209 | STACK_CHECK( L) | 209 | STACK_CHECK( L); |
210 | lua_newtable( L); // out key keyout | 210 | lua_newtable( L); // out key keyout |
211 | luaG_inter_move( KL, L, 1); // storage key // out key keyout fifo | 211 | luaG_inter_move( KL, L, 1); // storage key // out key keyout fifo |
212 | lua_pushinteger( L, fifo->first); // out key keyout fifo first | 212 | lua_pushinteger( L, fifo->first); // out key keyout fifo first |
@@ -217,10 +217,10 @@ int keeper_push_linda_storage( lua_State* L, void* ptr) | |||
217 | lua_setfield( L, -3, "limit"); // out key keyout fifo | 217 | lua_setfield( L, -3, "limit"); // out key keyout fifo |
218 | lua_setfield( L, -2, "fifo"); // out key keyout | 218 | lua_setfield( L, -2, "fifo"); // out key keyout |
219 | lua_rawset( L, -3); // out | 219 | lua_rawset( L, -3); // out |
220 | STACK_END( L, 0) | 220 | STACK_END( L, 0); |
221 | } | 221 | } |
222 | lua_pop( KL, 1); // | 222 | lua_pop( KL, 1); // |
223 | STACK_END( KL, 0) | 223 | STACK_END( KL, 0); |
224 | keeper_release( K); | 224 | keeper_release( K); |
225 | return 1; | 225 | return 1; |
226 | } | 226 | } |
@@ -565,26 +565,31 @@ char const* init_keepers( lua_State* L, int const _nbKeepers, lua_CFunction _on_ | |||
565 | GKeepers = malloc( _nbKeepers * sizeof( struct s_Keeper)); | 565 | GKeepers = malloc( _nbKeepers * sizeof( struct s_Keeper)); |
566 | for( i = 0; i < _nbKeepers; ++ i) | 566 | for( i = 0; i < _nbKeepers; ++ i) |
567 | { | 567 | { |
568 | lua_State* K; | ||
569 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "### init_keepers %d BEGIN\n" INDENT_END, i)); | ||
570 | DEBUGSPEW_CODE( ++ debugspew_indent_depth); | ||
568 | // We need to load all base libraries in the keeper states so that the transfer databases are populated properly | 571 | // We need to load all base libraries in the keeper states so that the transfer databases are populated properly |
569 | // | 572 | // |
570 | // 'io' for debugging messages, 'package' because we need to require modules exporting idfuncs | 573 | // 'io' for debugging messages, 'package' because we need to require modules exporting idfuncs |
571 | // the others because they export functions that we may store in a keeper for transfer between lanes | 574 | // the others because they export functions that we may store in a keeper for transfer between lanes |
572 | lua_State* K = luaG_newstate( L, "*", _on_state_create); | 575 | K = luaG_newstate( L, "*", _on_state_create); |
573 | 576 | ||
574 | DEBUGSPEW_CODE( fprintf( stderr, "init_keepers %d\n", i)); | 577 | STACK_CHECK( K); |
578 | |||
579 | // replace default 'package' contents with stuff gotten from the master state | ||
580 | lua_getglobal( L, "package"); | ||
581 | luaG_inter_copy_package( L, K, -1); | ||
582 | lua_pop( L, 1); | ||
583 | |||
584 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "### init_keepers %d END\n" INDENT_END, i)); | ||
585 | DEBUGSPEW_CODE( -- debugspew_indent_depth); | ||
575 | 586 | ||
576 | STACK_CHECK( K) | ||
577 | // to see VM name in Decoda debugger | 587 | // to see VM name in Decoda debugger |
578 | lua_pushliteral( K, "Keeper #"); | 588 | lua_pushliteral( K, "Keeper #"); |
579 | lua_pushinteger( K, i + 1); | 589 | lua_pushinteger( K, i + 1); |
580 | lua_concat( K, 2); | 590 | lua_concat( K, 2); |
581 | lua_setglobal( K, "decoda_name"); | 591 | lua_setglobal( K, "decoda_name"); |
582 | 592 | ||
583 | // replace default 'package' contents with stuff gotten from the master state | ||
584 | lua_getglobal( L, "package"); | ||
585 | luaG_inter_copy_package( L, K, -1); | ||
586 | lua_pop( L, 1); | ||
587 | |||
588 | #if KEEPER_MODEL == KEEPER_MODEL_C | 593 | #if KEEPER_MODEL == KEEPER_MODEL_C |
589 | // create the fifos table in the keeper state | 594 | // create the fifos table in the keeper state |
590 | lua_pushlightuserdata( K, fifos_key); | 595 | lua_pushlightuserdata( K, fifos_key); |
@@ -611,7 +616,7 @@ char const* init_keepers( lua_State* L, int const _nbKeepers, lua_CFunction _on_ | |||
611 | STACK_MID( K, 2); | 616 | STACK_MID( K, 2); |
612 | lua_pop( K, 2); | 617 | lua_pop( K, 2); |
613 | #endif // KEEPER_MODEL == KEEPER_MODEL_LUA | 618 | #endif // KEEPER_MODEL == KEEPER_MODEL_LUA |
614 | STACK_END( K, 0) | 619 | STACK_END( K, 0); |
615 | MUTEX_INIT( &GKeepers[i].lock_); | 620 | MUTEX_INIT( &GKeepers[i].lock_); |
616 | GKeepers[i].L = K; | 621 | GKeepers[i].L = K; |
617 | //GKeepers[i].count = 0; | 622 | //GKeepers[i].count = 0; |
@@ -630,7 +635,7 @@ void populate_keepers( lua_State* L) | |||
630 | char const* name = luaL_checklstring( L, -1, &name_len); | 635 | char const* name = luaL_checklstring( L, -1, &name_len); |
631 | int i; | 636 | int i; |
632 | 637 | ||
633 | STACK_CHECK( L) | 638 | STACK_CHECK( L); |
634 | STACK_GROW( L, 3); | 639 | STACK_GROW( L, 3); |
635 | 640 | ||
636 | for( i = 0; i < GNbKeepers; ++ i) | 641 | for( i = 0; i < GNbKeepers; ++ i) |
@@ -638,20 +643,20 @@ void populate_keepers( lua_State* L) | |||
638 | lua_State* K = GKeepers[i].L; | 643 | lua_State* K = GKeepers[i].L; |
639 | int res; | 644 | int res; |
640 | MUTEX_LOCK( &GKeepers[i].lock_); | 645 | MUTEX_LOCK( &GKeepers[i].lock_); |
641 | STACK_CHECK( K) | 646 | STACK_CHECK( K); |
642 | STACK_GROW( K, 2); | 647 | STACK_GROW( K, 2); |
643 | lua_getglobal( K, "require"); | 648 | lua_getglobal( K, "require"); |
644 | lua_pushlstring( K, name, name_len); | 649 | lua_pushlstring( K, name, name_len); |
645 | res = lua_pcall( K, 1, 0, 0); | 650 | res = lua_pcall( K, 1, 0, 0); |
646 | if( res != 0) | 651 | if( res != LUA_OK) |
647 | { | 652 | { |
648 | char const* err = luaL_checkstring( K, -1); | 653 | char const* err = luaL_checkstring( K, -1); |
649 | luaL_error( L, "error requiring '%s' in keeper state: %s", name, err); | 654 | luaL_error( L, "error requiring '%s' in keeper state: %s", name, err); |
650 | } | 655 | } |
651 | STACK_END( K, 0) | 656 | STACK_END( K, 0); |
652 | MUTEX_UNLOCK( &GKeepers[i].lock_); | 657 | MUTEX_UNLOCK( &GKeepers[i].lock_); |
653 | } | 658 | } |
654 | STACK_END( L, 0) | 659 | STACK_END( L, 0); |
655 | } | 660 | } |
656 | 661 | ||
657 | struct s_Keeper* keeper_acquire( void const* ptr) | 662 | struct s_Keeper* keeper_acquire( void const* ptr) |
diff --git a/src/lanes.c b/src/lanes.c index 62d56c1..80f5b15 100644 --- a/src/lanes.c +++ b/src/lanes.c | |||
@@ -403,11 +403,11 @@ LUAG_FUNC( linda_send) | |||
403 | STACK_GROW(L, 1); | 403 | STACK_GROW(L, 1); |
404 | { | 404 | { |
405 | struct s_Keeper *K = keeper_acquire( linda); | 405 | struct s_Keeper *K = keeper_acquire( linda); |
406 | lua_State*KL = K->L; // need to do this for 'STACK_CHECK' | 406 | lua_State *KL = K->L; // need to do this for 'STACK_CHECK' |
407 | STACK_CHECK( KL) | 407 | STACK_CHECK( KL); |
408 | for( ;;) | 408 | for( ;;) |
409 | { | 409 | { |
410 | STACK_MID(KL, 0) | 410 | STACK_MID( KL, 0); |
411 | pushed = keeper_call( KL, KEEPER_API( send), L, linda, key_i); | 411 | pushed = keeper_call( KL, KEEPER_API( send), L, linda, key_i); |
412 | if( pushed < 0) | 412 | if( pushed < 0) |
413 | { | 413 | { |
@@ -444,12 +444,12 @@ LUAG_FUNC( linda_send) | |||
444 | enum e_status prev_status = ERROR_ST; // prevent 'might be used uninitialized' warnings | 444 | enum e_status prev_status = ERROR_ST; // prevent 'might be used uninitialized' warnings |
445 | STACK_GROW(L, 1); | 445 | STACK_GROW(L, 1); |
446 | 446 | ||
447 | STACK_CHECK(L) | 447 | STACK_CHECK( L); |
448 | lua_pushlightuserdata( L, CANCEL_TEST_KEY); | 448 | lua_pushlightuserdata( L, CANCEL_TEST_KEY); |
449 | lua_rawget( L, LUA_REGISTRYINDEX); | 449 | lua_rawget( L, LUA_REGISTRYINDEX); |
450 | s = lua_touserdata( L, -1); // lightuserdata (true 's_lane' pointer) or nil if in the main Lua state | 450 | s = lua_touserdata( L, -1); // lightuserdata (true 's_lane' pointer) or nil if in the main Lua state |
451 | lua_pop(L, 1); | 451 | lua_pop(L, 1); |
452 | STACK_END(L,0) | 452 | STACK_END( L, 0); |
453 | if( s) | 453 | if( s) |
454 | { | 454 | { |
455 | prev_status = s->status; // RUNNING, most likely | 455 | prev_status = s->status; // RUNNING, most likely |
@@ -475,7 +475,7 @@ LUAG_FUNC( linda_send) | |||
475 | } | 475 | } |
476 | } | 476 | } |
477 | } | 477 | } |
478 | STACK_END( KL, 0) | 478 | STACK_END( KL, 0); |
479 | keeper_release( K); | 479 | keeper_release( K); |
480 | } | 480 | } |
481 | 481 | ||
@@ -602,12 +602,12 @@ LUAG_FUNC( linda_receive) | |||
602 | enum e_status prev_status = ERROR_ST; // prevent 'might be used uninitialized' warnings | 602 | enum e_status prev_status = ERROR_ST; // prevent 'might be used uninitialized' warnings |
603 | STACK_GROW(L,1); | 603 | STACK_GROW(L,1); |
604 | 604 | ||
605 | STACK_CHECK(L) | 605 | STACK_CHECK( L); |
606 | lua_pushlightuserdata( L, CANCEL_TEST_KEY); | 606 | lua_pushlightuserdata( L, CANCEL_TEST_KEY); |
607 | lua_rawget( L, LUA_REGISTRYINDEX); | 607 | lua_rawget( L, LUA_REGISTRYINDEX); |
608 | s = lua_touserdata( L, -1); // lightuserdata (true 's_lane' pointer) or nil if in the main Lua state | 608 | s = lua_touserdata( L, -1); // lightuserdata (true 's_lane' pointer) or nil if in the main Lua state |
609 | lua_pop(L, 1); | 609 | lua_pop( L, 1); |
610 | STACK_END(L, 0) | 610 | STACK_END( L, 0); |
611 | if( s) | 611 | if( s) |
612 | { | 612 | { |
613 | prev_status = s->status; // RUNNING, most likely | 613 | prev_status = s->status; // RUNNING, most likely |
@@ -959,7 +959,7 @@ static void linda_id( lua_State*L, char const * const which) | |||
959 | else if (strcmp( which, "metatable" )==0) | 959 | else if (strcmp( which, "metatable" )==0) |
960 | { | 960 | { |
961 | 961 | ||
962 | STACK_CHECK(L) | 962 | STACK_CHECK( L); |
963 | lua_newtable(L); | 963 | lua_newtable(L); |
964 | // metatable is its own index | 964 | // metatable is its own index |
965 | lua_pushvalue( L, -1); | 965 | lua_pushvalue( L, -1); |
@@ -1008,7 +1008,7 @@ static void linda_id( lua_State*L, char const * const which) | |||
1008 | lua_pushliteral( L, BATCH_SENTINEL); | 1008 | lua_pushliteral( L, BATCH_SENTINEL); |
1009 | lua_setfield(L, -2, "batched"); | 1009 | lua_setfield(L, -2, "batched"); |
1010 | 1010 | ||
1011 | STACK_END(L,1) | 1011 | STACK_END( L, 1); |
1012 | } | 1012 | } |
1013 | else if( strcmp( which, "module") == 0) | 1013 | else if( strcmp( which, "module") == 0) |
1014 | { | 1014 | { |
@@ -1441,12 +1441,12 @@ static bool_t cancel_test( lua_State*L ) { | |||
1441 | 1441 | ||
1442 | STACK_GROW(L,1); | 1442 | STACK_GROW(L,1); |
1443 | 1443 | ||
1444 | STACK_CHECK(L) | 1444 | STACK_CHECK( L); |
1445 | lua_pushlightuserdata( L, CANCEL_TEST_KEY ); | 1445 | lua_pushlightuserdata( L, CANCEL_TEST_KEY ); |
1446 | lua_rawget( L, LUA_REGISTRYINDEX ); | 1446 | lua_rawget( L, LUA_REGISTRYINDEX ); |
1447 | s= lua_touserdata( L, -1 ); // lightuserdata (true 's_lane' pointer) / nil | 1447 | s= lua_touserdata( L, -1 ); // lightuserdata (true 's_lane' pointer) / nil |
1448 | lua_pop(L,1); | 1448 | lua_pop(L,1); |
1449 | STACK_END(L,0) | 1449 | STACK_END( L, 0); |
1450 | 1450 | ||
1451 | // 's' is NULL for the original main state (no-one can cancel that) | 1451 | // 's' is NULL for the original main state (no-one can cancel that) |
1452 | // | 1452 | // |
@@ -1773,12 +1773,12 @@ static THREAD_RETURN_T THREAD_CALLCONV lane_main( void *vs) | |||
1773 | // LUA_ERRMEM(4): memory allocation error | 1773 | // LUA_ERRMEM(4): memory allocation error |
1774 | #endif | 1774 | #endif |
1775 | 1775 | ||
1776 | DEBUGSPEW_CODE( fprintf( stderr, "Lane %p body: %s\n", L, get_errcode_name( rc))); | 1776 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "Lane %p body: %s\n" INDENT_END, L, get_errcode_name( rc))); |
1777 | //STACK_DUMP(L); | 1777 | //STACK_DUMP(L); |
1778 | // Call finalizers, if the script has set them up. | 1778 | // Call finalizers, if the script has set them up. |
1779 | // | 1779 | // |
1780 | rc2 = run_finalizers( L, rc); | 1780 | rc2 = run_finalizers( L, rc); |
1781 | DEBUGSPEW_CODE( fprintf( stderr, "Lane %p finalizer: %s\n", L, get_errcode_name( rc2))); | 1781 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "Lane %p finalizer: %s\n" INDENT_END, L, get_errcode_name( rc2))); |
1782 | if( rc2 != LUA_OK) | 1782 | if( rc2 != LUA_OK) |
1783 | { | 1783 | { |
1784 | // Error within a finalizer! | 1784 | // Error within a finalizer! |
@@ -1857,7 +1857,9 @@ static void require_one_module( lua_State* L, lua_State* L2, bool_t _fatal) | |||
1857 | { | 1857 | { |
1858 | lua_pop( L2, 1); | 1858 | lua_pop( L2, 1); |
1859 | if( _fatal) | 1859 | if( _fatal) |
1860 | { | ||
1860 | luaL_error( L, "cannot pre-require modules without loading 'package' library first"); | 1861 | luaL_error( L, "cannot pre-require modules without loading 'package' library first"); |
1862 | } | ||
1861 | } | 1863 | } |
1862 | else | 1864 | else |
1863 | { | 1865 | { |
@@ -1868,11 +1870,11 @@ static void require_one_module( lua_State* L, lua_State* L2, bool_t _fatal) | |||
1868 | } | 1870 | } |
1869 | } | 1871 | } |
1870 | 1872 | ||
1871 | LUAG_FUNC( thread_new ) | 1873 | LUAG_FUNC( thread_new) |
1872 | { | 1874 | { |
1873 | lua_State*L2; | 1875 | lua_State* L2; |
1874 | struct s_lane *s; | 1876 | struct s_lane* s; |
1875 | struct s_lane **ud; | 1877 | struct s_lane** ud; |
1876 | 1878 | ||
1877 | char const* libs = lua_tostring( L, 2); | 1879 | char const* libs = lua_tostring( L, 2); |
1878 | lua_CFunction on_state_create = lua_iscfunction( L, 3) ? lua_tocfunction( L, 3) : NULL; | 1880 | lua_CFunction on_state_create = lua_iscfunction( L, 3) ? lua_tocfunction( L, 3) : NULL; |
@@ -1891,6 +1893,8 @@ LUAG_FUNC( thread_new ) | |||
1891 | } | 1893 | } |
1892 | 1894 | ||
1893 | /* --- Create and prepare the sub state --- */ | 1895 | /* --- Create and prepare the sub state --- */ |
1896 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "thread_new: setup\n" INDENT_END)); | ||
1897 | DEBUGSPEW_CODE( ++ debugspew_indent_depth); | ||
1894 | 1898 | ||
1895 | // populate with selected libraries at the same time | 1899 | // populate with selected libraries at the same time |
1896 | // | 1900 | // |
@@ -1905,6 +1909,7 @@ LUAG_FUNC( thread_new ) | |||
1905 | 1909 | ||
1906 | ASSERT_L( lua_gettop(L2) == 0); | 1910 | ASSERT_L( lua_gettop(L2) == 0); |
1907 | 1911 | ||
1912 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "thread_new: update 'package'\n" INDENT_END)); | ||
1908 | // package | 1913 | // package |
1909 | if( package) | 1914 | if( package) |
1910 | { | 1915 | { |
@@ -1913,21 +1918,24 @@ LUAG_FUNC( thread_new ) | |||
1913 | 1918 | ||
1914 | // modules to require in the target lane *before* the function is transfered! | 1919 | // modules to require in the target lane *before* the function is transfered! |
1915 | 1920 | ||
1921 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "thread_new: require 'lanes.core'\n" INDENT_END)); | ||
1916 | //start by requiring lanes.core, since it is a bit special | 1922 | //start by requiring lanes.core, since it is a bit special |
1917 | // it is not fatal if 'require' isn't loaded, just ignore (may cause function transfer errors later on if the lane pulls the lanes module itself) | 1923 | // it is not fatal if 'require' isn't loaded, just ignore (may cause function transfer errors later on if the lane pulls the lanes module itself) |
1918 | STACK_CHECK(L) | 1924 | STACK_CHECK( L); |
1919 | STACK_CHECK(L2) | 1925 | STACK_CHECK( L2); |
1920 | lua_pushliteral( L, "lanes.core"); | 1926 | lua_pushliteral( L, "lanes.core"); |
1921 | require_one_module( L, L2, FALSE); | 1927 | require_one_module( L, L2, FALSE); |
1922 | lua_pop( L, 1); | 1928 | lua_pop( L, 1); |
1923 | STACK_END(L2,0) | 1929 | STACK_END( L2, 0); |
1924 | STACK_END(L,0) | 1930 | STACK_END (L, 0); |
1925 | 1931 | ||
1926 | STACK_CHECK(L) | 1932 | STACK_CHECK( L); |
1927 | STACK_CHECK(L2) | 1933 | STACK_CHECK( L2); |
1928 | if( required) | 1934 | if( required) |
1929 | { | 1935 | { |
1930 | int nbRequired = 1; | 1936 | int nbRequired = 1; |
1937 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "thread_new: require 'required' list\n" INDENT_END)); | ||
1938 | DEBUGSPEW_CODE( ++ debugspew_indent_depth); | ||
1931 | // should not happen, was checked in lanes.lua before calling thread_new() | 1939 | // should not happen, was checked in lanes.lua before calling thread_new() |
1932 | if( lua_type( L, required) != LUA_TTABLE) | 1940 | if( lua_type( L, required) != LUA_TTABLE) |
1933 | { | 1941 | { |
@@ -1947,22 +1955,25 @@ LUAG_FUNC( thread_new ) | |||
1947 | lua_pop( L, 1); | 1955 | lua_pop( L, 1); |
1948 | ++ nbRequired; | 1956 | ++ nbRequired; |
1949 | } | 1957 | } |
1958 | DEBUGSPEW_CODE( -- debugspew_indent_depth); | ||
1950 | } | 1959 | } |
1951 | STACK_END(L2,0) | 1960 | STACK_END( L2, 0); |
1952 | STACK_END(L,0) | 1961 | STACK_END( L, 0); |
1953 | 1962 | ||
1954 | // Appending the specified globals to the global environment | 1963 | // Appending the specified globals to the global environment |
1955 | // *after* stdlibs have been loaded and modules required, in case we transfer references to native functions they exposed... | 1964 | // *after* stdlibs have been loaded and modules required, in case we transfer references to native functions they exposed... |
1956 | // | 1965 | // |
1957 | if( glob != 0) | 1966 | if( glob != 0) |
1958 | { | 1967 | { |
1959 | STACK_CHECK(L) | 1968 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "thread_new: transfer globals\n" INDENT_END)); |
1960 | STACK_CHECK(L2) | 1969 | STACK_CHECK( L); |
1970 | STACK_CHECK( L2); | ||
1961 | if( !lua_istable( L, glob)) | 1971 | if( !lua_istable( L, glob)) |
1962 | { | 1972 | { |
1963 | return luaL_error( L, "Expected table, got %s", luaL_typename( L, glob)); | 1973 | return luaL_error( L, "Expected table, got %s", luaL_typename( L, glob)); |
1964 | } | 1974 | } |
1965 | 1975 | ||
1976 | DEBUGSPEW_CODE( ++ debugspew_indent_depth); | ||
1966 | lua_pushnil( L); | 1977 | lua_pushnil( L); |
1967 | lua_pushglobaltable( L2); // Lua 5.2 wants us to push the globals table on the stack | 1978 | lua_pushglobaltable( L2); // Lua 5.2 wants us to push the globals table on the stack |
1968 | while( lua_next( L, glob)) | 1979 | while( lua_next( L, glob)) |
@@ -1974,23 +1985,29 @@ LUAG_FUNC( thread_new ) | |||
1974 | } | 1985 | } |
1975 | lua_pop( L2, 1); | 1986 | lua_pop( L2, 1); |
1976 | 1987 | ||
1977 | STACK_END(L2, 0) | 1988 | STACK_END( L2, 0); |
1978 | STACK_END(L, 0) | 1989 | STACK_END( L, 0); |
1990 | DEBUGSPEW_CODE( -- debugspew_indent_depth); | ||
1979 | } | 1991 | } |
1980 | 1992 | ||
1981 | ASSERT_L( lua_gettop(L2) == 0); | 1993 | ASSERT_L( lua_gettop( L2) == 0); |
1982 | 1994 | ||
1983 | // Lane main function | 1995 | // Lane main function |
1984 | // | 1996 | // |
1985 | STACK_CHECK(L) | 1997 | STACK_CHECK( L); |
1986 | if( lua_type( L, 1) == LUA_TFUNCTION) | 1998 | if( lua_type( L, 1) == LUA_TFUNCTION) |
1987 | { | 1999 | { |
2000 | int res; | ||
2001 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "thread_new: transfer lane body\n" INDENT_END)); | ||
2002 | DEBUGSPEW_CODE( ++ debugspew_indent_depth); | ||
1988 | lua_pushvalue( L, 1); | 2003 | lua_pushvalue( L, 1); |
1989 | if( luaG_inter_move( L, L2, 1) != 0) // L->L2 | 2004 | res = luaG_inter_move( L, L2, 1); // L->L2 |
2005 | DEBUGSPEW_CODE( -- debugspew_indent_depth); | ||
2006 | if( res != 0) | ||
1990 | { | 2007 | { |
1991 | return luaL_error( L, "tried to copy unsupported types"); | 2008 | return luaL_error( L, "tried to copy unsupported types"); |
1992 | } | 2009 | } |
1993 | STACK_MID(L,0) | 2010 | STACK_MID( L, 0); |
1994 | } | 2011 | } |
1995 | else if( lua_type( L, 1) == LUA_TSTRING) | 2012 | else if( lua_type( L, 1) == LUA_TSTRING) |
1996 | { | 2013 | { |
@@ -2001,28 +2018,34 @@ LUAG_FUNC( thread_new ) | |||
2001 | } | 2018 | } |
2002 | } | 2019 | } |
2003 | 2020 | ||
2004 | ASSERT_L( lua_gettop(L2) == 1); | 2021 | ASSERT_L( lua_gettop( L2) == 1); |
2005 | ASSERT_L( lua_isfunction(L2,1)); | 2022 | ASSERT_L( lua_isfunction( L2, 1)); |
2006 | 2023 | ||
2007 | // revive arguments | 2024 | // revive arguments |
2008 | // | 2025 | // |
2009 | if( (args > 0) && (luaG_inter_copy( L, L2, args) != 0)) // L->L2 | 2026 | if( args > 0) |
2010 | { | 2027 | { |
2011 | return luaL_error( L, "tried to copy unsupported types"); | 2028 | int res; |
2029 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "thread_new: transfer lane arguments\n" INDENT_END)); | ||
2030 | DEBUGSPEW_CODE( ++ debugspew_indent_depth); | ||
2031 | res = luaG_inter_copy( L, L2, args); // L->L2 | ||
2032 | DEBUGSPEW_CODE( -- debugspew_indent_depth); | ||
2033 | if( res != 0) | ||
2034 | return luaL_error( L, "tried to copy unsupported types"); | ||
2012 | } | 2035 | } |
2013 | STACK_MID(L,0) | 2036 | STACK_MID( L, 0); |
2014 | 2037 | ||
2015 | ASSERT_L( (uint_t)lua_gettop(L2) == 1+args ); | 2038 | ASSERT_L( (uint_t)lua_gettop( L2) == 1+args); |
2016 | ASSERT_L( lua_isfunction(L2,1) ); | 2039 | ASSERT_L( lua_isfunction( L2, 1)); |
2017 | 2040 | ||
2018 | // 's' is allocated from heap, not Lua, since its life span may surpass | 2041 | // 's' is allocated from heap, not Lua, since its life span may surpass |
2019 | // the handle's (if free running thread) | 2042 | // the handle's (if free running thread) |
2020 | // | 2043 | // |
2021 | ud= lua_newuserdata( L, sizeof(struct s_lane*) ); | 2044 | ud = lua_newuserdata( L, sizeof( struct s_lane*)); |
2022 | ASSERT_L(ud); | 2045 | ASSERT_L( ud); |
2023 | 2046 | ||
2024 | s= *ud= malloc( sizeof(struct s_lane) ); | 2047 | s = *ud = malloc( sizeof( struct s_lane)); |
2025 | ASSERT_L(s); | 2048 | ASSERT_L( s); |
2026 | 2049 | ||
2027 | //memset( s, 0, sizeof(struct s_lane) ); | 2050 | //memset( s, 0, sizeof(struct s_lane) ); |
2028 | s->L= L2; | 2051 | s->L= L2; |
@@ -2045,7 +2068,7 @@ LUAG_FUNC( thread_new ) | |||
2045 | // | 2068 | // |
2046 | lua_pushvalue( L, lua_upvalueindex(1) ); | 2069 | lua_pushvalue( L, lua_upvalueindex(1) ); |
2047 | lua_setmetatable( L, -2 ); | 2070 | lua_setmetatable( L, -2 ); |
2048 | STACK_MID(L,1) | 2071 | STACK_MID( L, 1); |
2049 | 2072 | ||
2050 | // Clear environment for the userdata | 2073 | // Clear environment for the userdata |
2051 | // | 2074 | // |
@@ -2064,8 +2087,11 @@ LUAG_FUNC( thread_new ) | |||
2064 | lua_sethook( L2, cancel_hook, LUA_MASKCOUNT, cs ); | 2087 | lua_sethook( L2, cancel_hook, LUA_MASKCOUNT, cs ); |
2065 | } | 2088 | } |
2066 | 2089 | ||
2090 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "thread_new: launching thread\n" INDENT_END)); | ||
2067 | THREAD_CREATE( &s->thread, lane_main, s, prio ); | 2091 | THREAD_CREATE( &s->thread, lane_main, s, prio ); |
2068 | STACK_END(L,1) | 2092 | STACK_END( L, 1); |
2093 | |||
2094 | DEBUGSPEW_CODE( -- debugspew_indent_depth); | ||
2069 | 2095 | ||
2070 | return 1; | 2096 | return 1; |
2071 | } | 2097 | } |
@@ -2503,7 +2529,7 @@ LUAG_FUNC( wakeup_conv ) | |||
2503 | // .yday (day of the year) | 2529 | // .yday (day of the year) |
2504 | // .isdst (daylight saving on/off) | 2530 | // .isdst (daylight saving on/off) |
2505 | 2531 | ||
2506 | STACK_CHECK(L) | 2532 | STACK_CHECK( L); |
2507 | lua_getfield( L, 1, "year" ); year= (int)lua_tointeger(L,-1); lua_pop(L,1); | 2533 | lua_getfield( L, 1, "year" ); year= (int)lua_tointeger(L,-1); lua_pop(L,1); |
2508 | lua_getfield( L, 1, "month" ); month= (int)lua_tointeger(L,-1); lua_pop(L,1); | 2534 | lua_getfield( L, 1, "month" ); month= (int)lua_tointeger(L,-1); lua_pop(L,1); |
2509 | lua_getfield( L, 1, "day" ); day= (int)lua_tointeger(L,-1); lua_pop(L,1); | 2535 | lua_getfield( L, 1, "day" ); day= (int)lua_tointeger(L,-1); lua_pop(L,1); |
@@ -2517,7 +2543,7 @@ LUAG_FUNC( wakeup_conv ) | |||
2517 | lua_getfield( L, 1, "isdst" ); | 2543 | lua_getfield( L, 1, "isdst" ); |
2518 | isdst= lua_isboolean(L,-1) ? lua_toboolean(L,-1) : -1; | 2544 | isdst= lua_isboolean(L,-1) ? lua_toboolean(L,-1) : -1; |
2519 | lua_pop(L,1); | 2545 | lua_pop(L,1); |
2520 | STACK_END(L,0) | 2546 | STACK_END( L, 0); |
2521 | 2547 | ||
2522 | t.tm_year= year-1900; | 2548 | t.tm_year= year-1900; |
2523 | t.tm_mon= month-1; // 0..11 | 2549 | t.tm_mon= month-1; // 0..11 |
@@ -2619,13 +2645,13 @@ static void init_once_LOCKED( lua_State* L, int const nbKeepers, lua_CFunction _ | |||
2619 | // | 2645 | // |
2620 | ASSERT_L( timer_deep == NULL); | 2646 | ASSERT_L( timer_deep == NULL); |
2621 | 2647 | ||
2622 | STACK_CHECK(L) | 2648 | STACK_CHECK( L); |
2623 | { | 2649 | { |
2624 | // proxy_ud= deep_userdata( idfunc ) | 2650 | // proxy_ud= deep_userdata( idfunc ) |
2625 | // | 2651 | // |
2626 | lua_pushliteral( L, "lanes-timer"); // push a name for debug purposes | 2652 | lua_pushliteral( L, "lanes-timer"); // push a name for debug purposes |
2627 | luaG_deep_userdata( L, linda_id); | 2653 | luaG_deep_userdata( L, linda_id); |
2628 | STACK_MID( L, 2) | 2654 | STACK_MID( L, 2); |
2629 | lua_remove( L, -2); // remove the name as we no longer need it | 2655 | lua_remove( L, -2); // remove the name as we no longer need it |
2630 | 2656 | ||
2631 | ASSERT_L( lua_isuserdata(L,-1) ); | 2657 | ASSERT_L( lua_isuserdata(L,-1) ); |
@@ -2653,7 +2679,7 @@ static void init_once_LOCKED( lua_State* L, int const nbKeepers, lua_CFunction _ | |||
2653 | lua_rawset( L, LUA_REGISTRYINDEX); | 2679 | lua_rawset( L, LUA_REGISTRYINDEX); |
2654 | 2680 | ||
2655 | } | 2681 | } |
2656 | STACK_END(L,0) | 2682 | STACK_END( L, 0); |
2657 | } | 2683 | } |
2658 | 2684 | ||
2659 | static volatile long s_initCount = 0; | 2685 | static volatile long s_initCount = 0; |
@@ -2669,7 +2695,10 @@ LUAG_FUNC( configure) | |||
2669 | lua_Number shutdown_timeout = lua_tonumber( L, 3); | 2695 | lua_Number shutdown_timeout = lua_tonumber( L, 3); |
2670 | bool_t track_lanes = lua_toboolean( L, 4); | 2696 | bool_t track_lanes = lua_toboolean( L, 4); |
2671 | 2697 | ||
2672 | STACK_CHECK( L) | 2698 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: lanes.configure() BEGIN\n" INDENT_END, L)); |
2699 | DEBUGSPEW_CODE( ++ debugspew_indent_depth); | ||
2700 | STACK_CHECK( L); | ||
2701 | |||
2673 | // Create main module interface table | 2702 | // Create main module interface table |
2674 | lua_pushvalue( L, lua_upvalueindex( 2)); // ... M | 2703 | lua_pushvalue( L, lua_upvalueindex( 2)); // ... M |
2675 | // remove configure() (this function) from the module interface | 2704 | // remove configure() (this function) from the module interface |
@@ -2677,7 +2706,7 @@ LUAG_FUNC( configure) | |||
2677 | lua_setfield( L, -2, "configure"); // ... M | 2706 | lua_setfield( L, -2, "configure"); // ... M |
2678 | // add functions to the module's table | 2707 | // add functions to the module's table |
2679 | luaG_registerlibfuncs( L, lanes_functions); | 2708 | luaG_registerlibfuncs( L, lanes_functions); |
2680 | STACK_MID( L, 1) | 2709 | STACK_MID( L, 1); |
2681 | 2710 | ||
2682 | // metatable for threads | 2711 | // metatable for threads |
2683 | // contains keys: { __gc, __index, cached_error, cached_tostring, cancel, join } | 2712 | // contains keys: { __gc, __index, cached_error, cached_tostring, cancel, join } |
@@ -2723,7 +2752,7 @@ LUAG_FUNC( configure) | |||
2723 | populate_func_lookup_table( L, -1, NULL); | 2752 | populate_func_lookup_table( L, -1, NULL); |
2724 | lua_pop( L, 1); // ... M | 2753 | lua_pop( L, 1); // ... M |
2725 | 2754 | ||
2726 | STACK_MID( L, 1) | 2755 | STACK_MID( L, 1); |
2727 | /* | 2756 | /* |
2728 | * Making one-time initializations. | 2757 | * Making one-time initializations. |
2729 | * | 2758 | * |
@@ -2765,14 +2794,16 @@ LUAG_FUNC( configure) | |||
2765 | } | 2794 | } |
2766 | #endif // THREADAPI == THREADAPI_PTHREAD | 2795 | #endif // THREADAPI == THREADAPI_PTHREAD |
2767 | assert( timer_deep != NULL); | 2796 | assert( timer_deep != NULL); |
2768 | STACK_MID( L, 1) | 2797 | STACK_MID( L, 1); |
2769 | 2798 | ||
2770 | // init_once_LOCKED initializes timer_deep, so we must do this after, of course | 2799 | // init_once_LOCKED initializes timer_deep, so we must do this after, of course |
2771 | luaG_push_proxy( L, linda_id, (DEEP_PRELUDE*) timer_deep); // ... M timer_deep | 2800 | luaG_push_proxy( L, linda_id, (DEEP_PRELUDE*) timer_deep); // ... M timer_deep |
2772 | lua_setfield( L, -2, "timer_gateway"); // ... M | 2801 | lua_setfield( L, -2, "timer_gateway"); // ... M |
2773 | 2802 | ||
2774 | lua_pop( L, 1); // ... | 2803 | lua_pop( L, 1); // ... |
2775 | STACK_END( L, 0) | 2804 | STACK_END( L, 0); |
2805 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: lanes.configure() END\n" INDENT_END, L)); | ||
2806 | DEBUGSPEW_CODE( -- debugspew_indent_depth); | ||
2776 | // Return nothing | 2807 | // Return nothing |
2777 | return 0; | 2808 | return 0; |
2778 | } | 2809 | } |
@@ -2810,7 +2841,7 @@ luaopen_lanes_core( lua_State* L) | |||
2810 | EnableCrashingOnCrashes(); | 2841 | EnableCrashingOnCrashes(); |
2811 | 2842 | ||
2812 | STACK_GROW( L, 3); | 2843 | STACK_GROW( L, 3); |
2813 | STACK_CHECK( L) | 2844 | STACK_CHECK( L); |
2814 | 2845 | ||
2815 | // sanity check: let's see if _"VERSION" matches what we we built against | 2846 | // sanity check: let's see if _"VERSION" matches what we we built against |
2816 | lua_getglobal( L, "_VERSION"); | 2847 | lua_getglobal( L, "_VERSION"); |
@@ -2838,6 +2869,6 @@ luaopen_lanes_core( lua_State* L) | |||
2838 | lua_call( L, 2, 0); | 2869 | lua_call( L, 2, 0); |
2839 | } | 2870 | } |
2840 | 2871 | ||
2841 | STACK_END( L, 1) | 2872 | STACK_END( L, 1); |
2842 | return 1; | 2873 | return 1; |
2843 | } | 2874 | } |
diff --git a/src/lanes.lua b/src/lanes.lua index 6bd9e44..1d50f97 100644 --- a/src/lanes.lua +++ b/src/lanes.lua | |||
@@ -281,7 +281,7 @@ local function gen( ... ) | |||
281 | elseif k=="package" then | 281 | elseif k=="package" then |
282 | package_tbl = (type( v) == "table") and v or error( "Bad package: " .. tostring( v), lev) | 282 | package_tbl = (type( v) == "table") and v or error( "Bad package: " .. tostring( v), lev) |
283 | elseif k=="required" then | 283 | elseif k=="required" then |
284 | required= (type( v) == "table") and v or error( "Bad required: " .. tostring( v), lev) | 284 | required= (type( v) == "table") and v or error( "Bad 'required' option: expecting table, got " .. type( v), lev) |
285 | --.. | 285 | --.. |
286 | elseif k==1 then error( "unkeyed option: ".. tostring(v), lev ) | 286 | elseif k==1 then error( "unkeyed option: ".. tostring(v), lev ) |
287 | else error( "Bad option: ".. tostring(k), lev ) | 287 | else error( "Bad option: ".. tostring(k), lev ) |
diff --git a/src/tools.c b/src/tools.c index ade8cb8..552e61e 100644 --- a/src/tools.c +++ b/src/tools.c | |||
@@ -43,6 +43,8 @@ THE SOFTWARE. | |||
43 | #include <stdlib.h> | 43 | #include <stdlib.h> |
44 | 44 | ||
45 | DEBUGSPEW_CODE( char const* debugspew_indent = "----+----!----+----!----+----!----+----!----+----!----+----!----+----!----+"); | 45 | DEBUGSPEW_CODE( char const* debugspew_indent = "----+----!----+----!----+----!----+----!----+----!----+----!----+----!----+"); |
46 | DEBUGSPEW_CODE( int debugspew_indent_depth = 0); | ||
47 | |||
46 | 48 | ||
47 | MUTEX_T deep_lock; | 49 | MUTEX_T deep_lock; |
48 | MUTEX_T mtid_lock; | 50 | MUTEX_T mtid_lock; |
@@ -69,7 +71,7 @@ void luaG_dump( lua_State* L ) { | |||
69 | // Note: this requires 'tostring()' to be defined. If it is NOT, | 71 | // Note: this requires 'tostring()' to be defined. If it is NOT, |
70 | // enable it for more debugging. | 72 | // enable it for more debugging. |
71 | // | 73 | // |
72 | STACK_CHECK(L) | 74 | STACK_CHECK( L); |
73 | STACK_GROW( L, 2); | 75 | STACK_GROW( L, 2); |
74 | 76 | ||
75 | lua_getglobal( L, "tostring" ); | 77 | lua_getglobal( L, "tostring" ); |
@@ -87,7 +89,7 @@ void luaG_dump( lua_State* L ) { | |||
87 | fprintf( stderr, "%s", lua_tostring(L,-1) ); | 89 | fprintf( stderr, "%s", lua_tostring(L,-1) ); |
88 | } | 90 | } |
89 | lua_pop(L,1); | 91 | lua_pop(L,1); |
90 | STACK_END(L,0) | 92 | STACK_END( L, 0); |
91 | fprintf( stderr, "\n" ); | 93 | fprintf( stderr, "\n" ); |
92 | } | 94 | } |
93 | fprintf( stderr, "\n" ); | 95 | fprintf( stderr, "\n" ); |
@@ -125,8 +127,8 @@ static void open1lib( lua_State* L, char const* name, size_t len) | |||
125 | { | 127 | { |
126 | if( libs[i].func) | 128 | if( libs[i].func) |
127 | { | 129 | { |
128 | DEBUGSPEW_CODE( fprintf( stderr, "opening %.*s library\n", len, name)); | 130 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening %.*s library\n" INDENT_END, len, name)); |
129 | STACK_CHECK( L) | 131 | STACK_CHECK( L); |
130 | #if LUA_VERSION_NUM >= 502 | 132 | #if LUA_VERSION_NUM >= 502 |
131 | // open the library as if through require(), and create a global as well (the library table is left on the stack) | 133 | // open the library as if through require(), and create a global as well (the library table is left on the stack) |
132 | luaL_requiref( L, libs[i].name, libs[i].func, 1); | 134 | luaL_requiref( L, libs[i].name, libs[i].func, 1); |
@@ -137,7 +139,7 @@ static void open1lib( lua_State* L, char const* name, size_t len) | |||
137 | // pushes the module table on the stack | 139 | // pushes the module table on the stack |
138 | lua_call( L, 0, 0); | 140 | lua_call( L, 0, 0); |
139 | #endif // LUA_VERSION_NUM | 141 | #endif // LUA_VERSION_NUM |
140 | STACK_END( L, 0) | 142 | STACK_END( L, 0); |
141 | } | 143 | } |
142 | break; | 144 | break; |
143 | } | 145 | } |
@@ -216,7 +218,7 @@ static char const* luaG_pushFQN(lua_State *L, int t, int last) | |||
216 | { | 218 | { |
217 | int i = 1; | 219 | int i = 1; |
218 | luaL_Buffer b; | 220 | luaL_Buffer b; |
219 | STACK_CHECK( L) | 221 | STACK_CHECK( L); |
220 | luaL_buffinit(L, &b); | 222 | luaL_buffinit(L, &b); |
221 | for( ; i < last; ++ i) | 223 | for( ; i < last; ++ i) |
222 | { | 224 | { |
@@ -230,7 +232,7 @@ static char const* luaG_pushFQN(lua_State *L, int t, int last) | |||
230 | luaL_addvalue( &b); | 232 | luaL_addvalue( &b); |
231 | } | 233 | } |
232 | luaL_pushresult( &b); | 234 | luaL_pushresult( &b); |
233 | STACK_END( L, 1) | 235 | STACK_END( L, 1); |
234 | return lua_tostring( L, -1); | 236 | return lua_tostring( L, -1); |
235 | } | 237 | } |
236 | 238 | ||
@@ -249,14 +251,14 @@ static void populate_func_lookup_table_recur( lua_State* L, int _ctx_base, int _ | |||
249 | 251 | ||
250 | STACK_GROW( L, 6); | 252 | STACK_GROW( L, 6); |
251 | // slot _i contains a table where we search for functions | 253 | // slot _i contains a table where we search for functions |
252 | STACK_CHECK( L) // ... {_i} | 254 | STACK_CHECK( L); // ... {_i} |
253 | 255 | ||
254 | // if table is already visited, we are done | 256 | // if table is already visited, we are done |
255 | lua_pushvalue( L, _i); // ... {_i} {} | 257 | lua_pushvalue( L, _i); // ... {_i} {} |
256 | lua_rawget( L, cache); // ... {_i} nil|n | 258 | lua_rawget( L, cache); // ... {_i} nil|n |
257 | visit_count = lua_tointeger( L, -1); // 0 if nil, else n | 259 | visit_count = lua_tointeger( L, -1); // 0 if nil, else n |
258 | lua_pop( L, 1); // ... {_i} | 260 | lua_pop( L, 1); // ... {_i} |
259 | STACK_MID( L, 0) | 261 | STACK_MID( L, 0); |
260 | if( visit_count > 0) | 262 | if( visit_count > 0) |
261 | { | 263 | { |
262 | return; | 264 | return; |
@@ -266,7 +268,7 @@ static void populate_func_lookup_table_recur( lua_State* L, int _ctx_base, int _ | |||
266 | lua_pushvalue( L, _i); // ... {_i} {} | 268 | lua_pushvalue( L, _i); // ... {_i} {} |
267 | lua_pushinteger( L, visit_count + 1); // ... {_i} {} 1 | 269 | lua_pushinteger( L, visit_count + 1); // ... {_i} {} 1 |
268 | lua_rawset( L, cache); // ... {_i} | 270 | lua_rawset( L, cache); // ... {_i} |
269 | STACK_MID( L, 0) | 271 | STACK_MID( L, 0); |
270 | 272 | ||
271 | // this table is at breadth_first_cache index | 273 | // this table is at breadth_first_cache index |
272 | lua_newtable( L); // ... {_i} {bfc} | 274 | lua_newtable( L); // ... {_i} {bfc} |
@@ -276,7 +278,7 @@ static void populate_func_lookup_table_recur( lua_State* L, int _ctx_base, int _ | |||
276 | while( lua_next( L, _i) != 0) // ... {_i} {bfc} k v | 278 | while( lua_next( L, _i) != 0) // ... {_i} {bfc} k v |
277 | { | 279 | { |
278 | // just for debug, not actually needed | 280 | // just for debug, not actually needed |
279 | //char const * key = (lua_type( L, -2) == LUA_TSTRING) ? lua_tostring( L, -2) : "not a string"; | 281 | //char const* key = (lua_type( L, -2) == LUA_TSTRING) ? lua_tostring( L, -2) : "not a string"; |
280 | // subtable: process it recursively | 282 | // subtable: process it recursively |
281 | if( lua_istable( L, -1)) // ... {_i} {bfc} k {} | 283 | if( lua_istable( L, -1)) // ... {_i} {bfc} k {} |
282 | { | 284 | { |
@@ -332,20 +334,23 @@ static void populate_func_lookup_table_recur( lua_State* L, int _ctx_base, int _ | |||
332 | // remove table name from fqn stack | 334 | // remove table name from fqn stack |
333 | lua_pushnil( L); // ... {_i} {bfc} k nil | 335 | lua_pushnil( L); // ... {_i} {bfc} k nil |
334 | lua_rawseti( L, fqn, _depth); // ... {_i} {bfc} k | 336 | lua_rawseti( L, fqn, _depth); // ... {_i} {bfc} k |
335 | DEBUGSPEW_CODE( fprintf( stderr, "%.*spopulating: %s\n", _i, debugspew_indent, newName)); | 337 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "function '%s'\n" INDENT_END, newName)); |
336 | -- _depth; | 338 | -- _depth; |
337 | } | 339 | } |
338 | else | 340 | else |
339 | { | 341 | { |
340 | lua_pop( L, 1); // ... {_i} {bfc} k | 342 | lua_pop( L, 1); // ... {_i} {bfc} k |
341 | } | 343 | } |
342 | STACK_MID( L, 2) | 344 | STACK_MID( L, 2); |
343 | } | 345 | } |
344 | // now process the tables we encountered at that depth | 346 | // now process the tables we encountered at that depth |
345 | ++ _depth; | 347 | ++ _depth; |
346 | lua_pushnil( L); // ... {_i} {bfc} nil | 348 | lua_pushnil( L); // ... {_i} {bfc} nil |
347 | while( lua_next( L, breadth_first_cache) != 0) // ... {_i} {bfc} k {} | 349 | while( lua_next( L, breadth_first_cache) != 0) // ... {_i} {bfc} k {} |
348 | { | 350 | { |
351 | DEBUGSPEW_CODE( char const* key = (lua_type( L, -2) == LUA_TSTRING) ? lua_tostring( L, -2) : "not a string"); | ||
352 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "table '%s'\n" INDENT_END, key)); | ||
353 | DEBUGSPEW_CODE( ++ debugspew_indent_depth); | ||
349 | // un-visit this table in case we do need to process it | 354 | // un-visit this table in case we do need to process it |
350 | lua_pushvalue( L, -1); // ... {_i} {bfc} k {} {} | 355 | lua_pushvalue( L, -1); // ... {_i} {bfc} k {} {} |
351 | lua_rawget( L, cache); // ... {_i} {bfc} k {} n | 356 | lua_rawget( L, cache); // ... {_i} {bfc} k {} n |
@@ -367,7 +372,8 @@ static void populate_func_lookup_table_recur( lua_State* L, int _ctx_base, int _ | |||
367 | lua_rawseti( L, fqn, _depth); // ... {_i} {bfc} k {} | 372 | lua_rawseti( L, fqn, _depth); // ... {_i} {bfc} k {} |
368 | populate_func_lookup_table_recur( L, _ctx_base, lua_gettop( L), _depth); // ... {_i} {bfc} k {} | 373 | populate_func_lookup_table_recur( L, _ctx_base, lua_gettop( L), _depth); // ... {_i} {bfc} k {} |
369 | lua_pop( L, 1); // ... {_i} {bfc} k | 374 | lua_pop( L, 1); // ... {_i} {bfc} k |
370 | STACK_MID( L, 2) | 375 | STACK_MID( L, 2); |
376 | DEBUGSPEW_CODE( -- debugspew_indent_depth); | ||
371 | } | 377 | } |
372 | // remove table name from fqn stack | 378 | // remove table name from fqn stack |
373 | lua_pushnil( L); // ... {_i} {bfc} nil | 379 | lua_pushnil( L); // ... {_i} {bfc} nil |
@@ -375,7 +381,7 @@ static void populate_func_lookup_table_recur( lua_State* L, int _ctx_base, int _ | |||
375 | -- _depth; | 381 | -- _depth; |
376 | // we are done with our cache | 382 | // we are done with our cache |
377 | lua_pop( L, 1); // ... {_i} | 383 | lua_pop( L, 1); // ... {_i} |
378 | STACK_END( L, 0) | 384 | STACK_END( L, 0); |
379 | // we are done // ... {_i} {bfc} | 385 | // we are done // ... {_i} {bfc} |
380 | } | 386 | } |
381 | 387 | ||
@@ -387,9 +393,10 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* _name) | |||
387 | int const ctx_base = lua_gettop( L) + 1; | 393 | int const ctx_base = lua_gettop( L) + 1; |
388 | int const in_base = lua_absindex( L, _i); | 394 | int const in_base = lua_absindex( L, _i); |
389 | int const start_depth = _name ? 1 : 0; | 395 | int const start_depth = _name ? 1 : 0; |
390 | DEBUGSPEW_CODE( fprintf( stderr, "%p: populate_func_lookup_table('%s')\n", L, _name ? _name : "NULL")); | 396 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: populate_func_lookup_table('%s')\n" INDENT_END, L, _name ? _name : "NULL")); |
397 | DEBUGSPEW_CODE( ++ debugspew_indent_depth); | ||
391 | STACK_GROW( L, 3); | 398 | STACK_GROW( L, 3); |
392 | STACK_CHECK( L) | 399 | STACK_CHECK( L); |
393 | lua_getfield( L, LUA_REGISTRYINDEX, LOOKUP_KEY); // {}? | 400 | lua_getfield( L, LUA_REGISTRYINDEX, LOOKUP_KEY); // {}? |
394 | if( lua_isnil( L, -1)) // nil | 401 | if( lua_isnil( L, -1)) // nil |
395 | { | 402 | { |
@@ -414,7 +421,8 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* _name) | |||
414 | } | 421 | } |
415 | populate_func_lookup_table_recur( L, ctx_base, in_base, start_depth); // {...} {fqn} {cache} | 422 | populate_func_lookup_table_recur( L, ctx_base, in_base, start_depth); // {...} {fqn} {cache} |
416 | lua_pop( L, 3); | 423 | lua_pop( L, 3); |
417 | STACK_END( L, 0) | 424 | STACK_END( L, 0); |
425 | DEBUGSPEW_CODE( -- debugspew_indent_depth); | ||
418 | } | 426 | } |
419 | 427 | ||
420 | /* | 428 | /* |
@@ -447,11 +455,14 @@ lua_State* luaG_newstate( lua_State* _from, char const* libs, lua_CFunction _on_ | |||
447 | return L; | 455 | return L; |
448 | } | 456 | } |
449 | 457 | ||
458 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_newstate()\n" INDENT_END)); | ||
459 | DEBUGSPEW_CODE( ++ debugspew_indent_depth); | ||
460 | |||
450 | STACK_GROW( L, 2); | 461 | STACK_GROW( L, 2); |
451 | STACK_CHECK( L) | 462 | STACK_CHECK( L); |
452 | if( _on_state_create) | 463 | if( _on_state_create) |
453 | { | 464 | { |
454 | DEBUGSPEW_CODE( fprintf( stderr, "calling on_state_create()\n")); | 465 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "calling on_state_create()\n" INDENT_END)); |
455 | lua_pushcfunction( L, _on_state_create); | 466 | lua_pushcfunction( L, _on_state_create); |
456 | lua_call( L, 0, 0); | 467 | lua_call( L, 0, 0); |
457 | } | 468 | } |
@@ -466,13 +477,13 @@ lua_State* luaG_newstate( lua_State* _from, char const* libs, lua_CFunction _on_ | |||
466 | { | 477 | { |
467 | if( libs[0] == '*' && libs[1] == 0) // special "*" case (mainly to help with LuaJIT compatibility) | 478 | if( libs[0] == '*' && libs[1] == 0) // special "*" case (mainly to help with LuaJIT compatibility) |
468 | { | 479 | { |
469 | DEBUGSPEW_CODE( fprintf( stderr, "opening ALL standard libraries\n")); | 480 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening ALL standard libraries\n" INDENT_END)); |
470 | luaL_openlibs( L); | 481 | luaL_openlibs( L); |
471 | libs = NULL; // done with libs | 482 | libs = NULL; // done with libs |
472 | } | 483 | } |
473 | else | 484 | else |
474 | { | 485 | { |
475 | DEBUGSPEW_CODE( fprintf( stderr, "opening base library\n")); | 486 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening base library\n" INDENT_END)); |
476 | #if LUA_VERSION_NUM >= 502 | 487 | #if LUA_VERSION_NUM >= 502 |
477 | // open base library the same way as in luaL_openlibs() | 488 | // open base library the same way as in luaL_openlibs() |
478 | luaL_requiref( L, "_G", luaopen_base, 1); | 489 | luaL_requiref( L, "_G", luaopen_base, 1); |
@@ -484,7 +495,7 @@ lua_State* luaG_newstate( lua_State* _from, char const* libs, lua_CFunction _on_ | |||
484 | #endif // LUA_VERSION_NUM | 495 | #endif // LUA_VERSION_NUM |
485 | } | 496 | } |
486 | } | 497 | } |
487 | STACK_END( L, 0) | 498 | STACK_END( L, 0); |
488 | 499 | ||
489 | // scan all libraries, open them one by one | 500 | // scan all libraries, open them one by one |
490 | if( libs) | 501 | if( libs) |
@@ -508,12 +519,13 @@ lua_State* luaG_newstate( lua_State* _from, char const* libs, lua_CFunction _on_ | |||
508 | 519 | ||
509 | lua_gc( L, LUA_GCRESTART, 0); | 520 | lua_gc( L, LUA_GCRESTART, 0); |
510 | 521 | ||
511 | STACK_CHECK( L) | 522 | STACK_CHECK( L); |
512 | // after opening base, register the functions it exported in our name<->function database | 523 | // after opening base, register the functions it exported in our name<->function database |
513 | lua_pushglobaltable( L); // Lua 5.2 no longer has LUA_GLOBALSINDEX: we must push globals table on the stack | 524 | lua_pushglobaltable( L); // Lua 5.2 no longer has LUA_GLOBALSINDEX: we must push globals table on the stack |
514 | populate_func_lookup_table( L, -1, NULL); | 525 | populate_func_lookup_table( L, -1, NULL); |
515 | lua_pop( L, 1); | 526 | lua_pop( L, 1); |
516 | STACK_END( L, 0) | 527 | STACK_END( L, 0); |
528 | DEBUGSPEW_CODE( -- debugspew_indent_depth); | ||
517 | return L; | 529 | return L; |
518 | } | 530 | } |
519 | 531 | ||
@@ -554,7 +566,7 @@ void set_deep_lookup( lua_State *L ) { | |||
554 | 566 | ||
555 | STACK_GROW(L,3); | 567 | STACK_GROW(L,3); |
556 | 568 | ||
557 | STACK_CHECK(L) | 569 | STACK_CHECK( L); |
558 | #if 1 | 570 | #if 1 |
559 | push_registry_subtable( L, DEEP_LOOKUP_KEY ); | 571 | push_registry_subtable( L, DEEP_LOOKUP_KEY ); |
560 | #else | 572 | #else |
@@ -580,7 +592,7 @@ void set_deep_lookup( lua_State *L ) { | |||
580 | // [-1]: lookup table (empty) | 592 | // [-1]: lookup table (empty) |
581 | } | 593 | } |
582 | #endif | 594 | #endif |
583 | STACK_MID(L,1) | 595 | STACK_MID( L, 1); |
584 | 596 | ||
585 | lua_insert(L,-3); | 597 | lua_insert(L,-3); |
586 | 598 | ||
@@ -594,7 +606,7 @@ void set_deep_lookup( lua_State *L ) { | |||
594 | lua_rawset( L, -3 ); // A->B | 606 | lua_rawset( L, -3 ); // A->B |
595 | lua_pop( L,1 ); | 607 | lua_pop( L,1 ); |
596 | 608 | ||
597 | STACK_END(L,-2) | 609 | STACK_END( L, -2); |
598 | } | 610 | } |
599 | 611 | ||
600 | /* | 612 | /* |
@@ -605,7 +617,7 @@ void get_deep_lookup( lua_State *L ) { | |||
605 | 617 | ||
606 | STACK_GROW(L,1); | 618 | STACK_GROW(L,1); |
607 | 619 | ||
608 | STACK_CHECK(L) | 620 | STACK_CHECK( L); |
609 | lua_pushlightuserdata( L, DEEP_LOOKUP_KEY ); | 621 | lua_pushlightuserdata( L, DEEP_LOOKUP_KEY ); |
610 | lua_rawget( L, LUA_REGISTRYINDEX ); | 622 | lua_rawget( L, LUA_REGISTRYINDEX ); |
611 | 623 | ||
@@ -621,7 +633,7 @@ void get_deep_lookup( lua_State *L ) { | |||
621 | } | 633 | } |
622 | lua_remove(L,-2); | 634 | lua_remove(L,-2); |
623 | // remove lookup, or unused key | 635 | // remove lookup, or unused key |
624 | STACK_END(L,0) | 636 | STACK_END( L, 0); |
625 | } | 637 | } |
626 | 638 | ||
627 | /* | 639 | /* |
@@ -637,7 +649,7 @@ luaG_IdFunction get_idfunc( lua_State *L, int index ) | |||
637 | 649 | ||
638 | STACK_GROW(L,1); | 650 | STACK_GROW(L,1); |
639 | 651 | ||
640 | STACK_CHECK(L) | 652 | STACK_CHECK( L); |
641 | if (!lua_getmetatable( L, index )) | 653 | if (!lua_getmetatable( L, index )) |
642 | return NULL; // no metatable | 654 | return NULL; // no metatable |
643 | 655 | ||
@@ -649,7 +661,7 @@ luaG_IdFunction get_idfunc( lua_State *L, int index ) | |||
649 | 661 | ||
650 | ret= (luaG_IdFunction)lua_touserdata(L,-1); | 662 | ret= (luaG_IdFunction)lua_touserdata(L,-1); |
651 | lua_pop(L,1); | 663 | lua_pop(L,1); |
652 | STACK_END(L,0) | 664 | STACK_END( L, 0); |
653 | return ret; | 665 | return ret; |
654 | } | 666 | } |
655 | 667 | ||
@@ -728,7 +740,7 @@ void luaG_push_proxy( lua_State *L, luaG_IdFunction idfunc, DEEP_PRELUDE *prelud | |||
728 | 740 | ||
729 | STACK_GROW(L,4); | 741 | STACK_GROW(L,4); |
730 | 742 | ||
731 | STACK_CHECK(L) | 743 | STACK_CHECK( L); |
732 | 744 | ||
733 | proxy= lua_newuserdata( L, sizeof( DEEP_PRELUDE* ) ); | 745 | proxy= lua_newuserdata( L, sizeof( DEEP_PRELUDE* ) ); |
734 | ASSERT_L(proxy); | 746 | ASSERT_L(proxy); |
@@ -784,7 +796,7 @@ void luaG_push_proxy( lua_State *L, luaG_IdFunction idfunc, DEEP_PRELUDE *prelud | |||
784 | 796 | ||
785 | // 2 - cause the target state to require the module that exported the idfunc | 797 | // 2 - cause the target state to require the module that exported the idfunc |
786 | // this is needed because we must make sure the shared library is still loaded as long as we hold a pointer on the idfunc | 798 | // this is needed because we must make sure the shared library is still loaded as long as we hold a pointer on the idfunc |
787 | STACK_CHECK(L) | 799 | STACK_CHECK( L); |
788 | { | 800 | { |
789 | char const * modname; | 801 | char const * modname; |
790 | // make sure the function pushed a single value on the stack! | 802 | // make sure the function pushed a single value on the stack! |
@@ -839,9 +851,9 @@ void luaG_push_proxy( lua_State *L, luaG_IdFunction idfunc, DEEP_PRELUDE *prelud | |||
839 | lua_pop( L, 1); // ... | 851 | lua_pop( L, 1); // ... |
840 | } | 852 | } |
841 | } | 853 | } |
842 | STACK_END(L,0) | 854 | STACK_END( L, 0); |
843 | } | 855 | } |
844 | STACK_MID(L,2) | 856 | STACK_MID( L, 2); |
845 | ASSERT_L( lua_isuserdata(L,-2) ); | 857 | ASSERT_L( lua_isuserdata(L,-2) ); |
846 | ASSERT_L( lua_istable(L,-1) ); | 858 | ASSERT_L( lua_istable(L,-1) ); |
847 | 859 | ||
@@ -857,7 +869,7 @@ void luaG_push_proxy( lua_State *L, luaG_IdFunction idfunc, DEEP_PRELUDE *prelud | |||
857 | lua_rawset(L, -3); | 869 | lua_rawset(L, -3); |
858 | lua_pop(L, 1); // Remove the cache proxy table | 870 | lua_pop(L, 1); // Remove the cache proxy table |
859 | 871 | ||
860 | STACK_END(L,1) | 872 | STACK_END( L, 1); |
861 | // [-1]: proxy userdata | 873 | // [-1]: proxy userdata |
862 | } | 874 | } |
863 | 875 | ||
@@ -894,7 +906,7 @@ int luaG_deep_userdata( lua_State *L, luaG_IdFunction idfunc) | |||
894 | prelude->refcount= 0; // 'luaG_push_proxy' will lift it to 1 | 906 | prelude->refcount= 0; // 'luaG_push_proxy' will lift it to 1 |
895 | 907 | ||
896 | STACK_GROW(L,1); | 908 | STACK_GROW(L,1); |
897 | STACK_CHECK(L) | 909 | STACK_CHECK( L); |
898 | 910 | ||
899 | // lightuserdata= idfunc( "new" [, ...] ) | 911 | // lightuserdata= idfunc( "new" [, ...] ) |
900 | // | 912 | // |
@@ -915,7 +927,7 @@ int luaG_deep_userdata( lua_State *L, luaG_IdFunction idfunc) | |||
915 | // | 927 | // |
916 | // [-1]: proxy userdata | 928 | // [-1]: proxy userdata |
917 | 929 | ||
918 | STACK_END(L,1) | 930 | STACK_END( L, 1); |
919 | return 1; | 931 | return 1; |
920 | } | 932 | } |
921 | 933 | ||
@@ -930,12 +942,12 @@ void *luaG_todeep( lua_State *L, luaG_IdFunction idfunc, int index ) | |||
930 | { | 942 | { |
931 | DEEP_PRELUDE **proxy; | 943 | DEEP_PRELUDE **proxy; |
932 | 944 | ||
933 | STACK_CHECK(L) | 945 | STACK_CHECK( L); |
934 | if( get_idfunc(L,index) != idfunc) | 946 | if( get_idfunc(L,index) != idfunc) |
935 | return NULL; // no metatable, or wrong kind | 947 | return NULL; // no metatable, or wrong kind |
936 | 948 | ||
937 | proxy= (DEEP_PRELUDE**)lua_touserdata( L, index ); | 949 | proxy= (DEEP_PRELUDE**)lua_touserdata( L, index ); |
938 | STACK_END(L,0) | 950 | STACK_END( L, 0); |
939 | 951 | ||
940 | return (*proxy)->deep; | 952 | return (*proxy)->deep; |
941 | } | 953 | } |
@@ -993,7 +1005,7 @@ void push_registry_subtable_mode( lua_State *L, void *token, const char* mode ) | |||
993 | 1005 | ||
994 | STACK_GROW(L,3); | 1006 | STACK_GROW(L,3); |
995 | 1007 | ||
996 | STACK_CHECK(L) | 1008 | STACK_CHECK( L); |
997 | 1009 | ||
998 | lua_pushlightuserdata( L, token ); | 1010 | lua_pushlightuserdata( L, token ); |
999 | lua_rawget( L, LUA_REGISTRYINDEX ); | 1011 | lua_rawget( L, LUA_REGISTRYINDEX ); |
@@ -1021,7 +1033,7 @@ void push_registry_subtable_mode( lua_State *L, void *token, const char* mode ) | |||
1021 | lua_setmetatable(L, -2); | 1033 | lua_setmetatable(L, -2); |
1022 | } | 1034 | } |
1023 | } | 1035 | } |
1024 | STACK_END(L,1) | 1036 | STACK_END( L, 1); |
1025 | 1037 | ||
1026 | ASSERT_L( lua_istable(L,-1) ); | 1038 | ASSERT_L( lua_istable(L,-1) ); |
1027 | } | 1039 | } |
@@ -1049,7 +1061,7 @@ uint_t get_mt_id( lua_State *L, int i ) { | |||
1049 | 1061 | ||
1050 | STACK_GROW(L,3); | 1062 | STACK_GROW(L,3); |
1051 | 1063 | ||
1052 | STACK_CHECK(L) | 1064 | STACK_CHECK( L); |
1053 | push_registry_subtable( L, REG_MTID ); | 1065 | push_registry_subtable( L, REG_MTID ); |
1054 | lua_pushvalue(L, i); | 1066 | lua_pushvalue(L, i); |
1055 | lua_rawget( L, -2 ); | 1067 | lua_rawget( L, -2 ); |
@@ -1059,7 +1071,7 @@ uint_t get_mt_id( lua_State *L, int i ) { | |||
1059 | 1071 | ||
1060 | id= (uint_t)lua_tointeger(L,-1); // 0 for nil | 1072 | id= (uint_t)lua_tointeger(L,-1); // 0 for nil |
1061 | lua_pop(L,1); | 1073 | lua_pop(L,1); |
1062 | STACK_MID(L,1) | 1074 | STACK_MID( L, 1); |
1063 | 1075 | ||
1064 | if (id==0) { | 1076 | if (id==0) { |
1065 | MUTEX_LOCK( &mtid_lock ); | 1077 | MUTEX_LOCK( &mtid_lock ); |
@@ -1078,7 +1090,7 @@ uint_t get_mt_id( lua_State *L, int i ) { | |||
1078 | } | 1090 | } |
1079 | lua_pop(L,1); // remove 'reg[REG_MTID]' reference | 1091 | lua_pop(L,1); // remove 'reg[REG_MTID]' reference |
1080 | 1092 | ||
1081 | STACK_END(L,0) | 1093 | STACK_END( L, 0); |
1082 | 1094 | ||
1083 | return id; | 1095 | return id; |
1084 | } | 1096 | } |
@@ -1111,7 +1123,7 @@ static bool_t push_cached_table( lua_State *L2, uint_t L2_cache_i, lua_State *L, | |||
1111 | 1123 | ||
1112 | // L2_cache[id_str]= [{...}] | 1124 | // L2_cache[id_str]= [{...}] |
1113 | // | 1125 | // |
1114 | STACK_CHECK(L2) | 1126 | STACK_CHECK( L2); |
1115 | 1127 | ||
1116 | // We don't need to use the from state ('L') in ID since the life span | 1128 | // We don't need to use the from state ('L') in ID since the life span |
1117 | // is only for the duration of a copy (both states are locked). | 1129 | // is only for the duration of a copy (both states are locked). |
@@ -1149,7 +1161,7 @@ static bool_t push_cached_table( lua_State *L2, uint_t L2_cache_i, lua_State *L, | |||
1149 | lua_remove(L2,-2); | 1161 | lua_remove(L2,-2); |
1150 | ret= TRUE; // from cache | 1162 | ret= TRUE; // from cache |
1151 | } | 1163 | } |
1152 | STACK_END(L2,1) | 1164 | STACK_END( L2, 1); |
1153 | // | 1165 | // |
1154 | // L2 [-1]: table to use as destination | 1166 | // L2 [-1]: table to use as destination |
1155 | 1167 | ||
@@ -1176,7 +1188,7 @@ static void push_cached_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, ui | |||
1176 | 1188 | ||
1177 | // L2_cache[id_str]= function | 1189 | // L2_cache[id_str]= function |
1178 | // | 1190 | // |
1179 | STACK_CHECK( L2) | 1191 | STACK_CHECK( L2); |
1180 | 1192 | ||
1181 | // We don't need to use the from state ('L') in ID since the life span | 1193 | // We don't need to use the from state ('L') in ID since the life span |
1182 | // is only for the duration of a copy (both states are locked). | 1194 | // is only for the duration of a copy (both states are locked). |
@@ -1204,7 +1216,7 @@ static void push_cached_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, ui | |||
1204 | { | 1216 | { |
1205 | lua_remove( L2, -2); // ... {cache} ... function | 1217 | lua_remove( L2, -2); // ... {cache} ... function |
1206 | } | 1218 | } |
1207 | STACK_END( L2, 1) | 1219 | STACK_END( L2, 1); |
1208 | // | 1220 | // |
1209 | // L2 [-1]: function | 1221 | // L2 [-1]: function |
1210 | 1222 | ||
@@ -1226,7 +1238,7 @@ int discover_object_name_recur( lua_State* L, int _shortest, int _length) | |||
1226 | return _shortest; | 1238 | return _shortest; |
1227 | } | 1239 | } |
1228 | STACK_GROW( L, 3); | 1240 | STACK_GROW( L, 3); |
1229 | STACK_CHECK(L) | 1241 | STACK_CHECK( L); |
1230 | // stack top contains the table to search in | 1242 | // stack top contains the table to search in |
1231 | lua_pushvalue( L, -1); // o "r" {c} {fqn} ... {?} {?} | 1243 | lua_pushvalue( L, -1); // o "r" {c} {fqn} ... {?} {?} |
1232 | lua_rawget( L, cache); // o "r" {c} {fqn} ... {?} nil/1 | 1244 | lua_rawget( L, cache); // o "r" {c} {fqn} ... {?} nil/1 |
@@ -1299,7 +1311,7 @@ int discover_object_name_recur( lua_State* L, int _shortest, int _length) | |||
1299 | lua_pushvalue( L, -1); // o "r" {c} {fqn} ... {?} {?} | 1311 | lua_pushvalue( L, -1); // o "r" {c} {fqn} ... {?} {?} |
1300 | lua_pushnil( L); // o "r" {c} {fqn} ... {?} {?} nil | 1312 | lua_pushnil( L); // o "r" {c} {fqn} ... {?} {?} nil |
1301 | lua_rawset( L, cache); // o "r" {c} {fqn} ... {?} | 1313 | lua_rawset( L, cache); // o "r" {c} {fqn} ... {?} |
1302 | STACK_END( L, 0) | 1314 | STACK_END( L, 0); |
1303 | return _shortest; | 1315 | return _shortest; |
1304 | } | 1316 | } |
1305 | 1317 | ||
@@ -1345,13 +1357,14 @@ static void lookup_native_func( lua_State* L2, lua_State* L, uint_t i) | |||
1345 | char const* fqn; // L // L2 | 1357 | char const* fqn; // L // L2 |
1346 | size_t len; | 1358 | size_t len; |
1347 | _ASSERT_L( L, lua_isfunction( L, i)); // ... f ... | 1359 | _ASSERT_L( L, lua_isfunction( L, i)); // ... f ... |
1348 | STACK_CHECK( L) | 1360 | STACK_CHECK( L); |
1349 | // fetch the name from the source state's lookup table | 1361 | // fetch the name from the source state's lookup table |
1350 | lua_getfield( L, LUA_REGISTRYINDEX, LOOKUP_KEY); // ... f ... {} | 1362 | lua_getfield( L, LUA_REGISTRYINDEX, LOOKUP_KEY); // ... f ... {} |
1351 | _ASSERT_L( L, lua_istable( L, -1)); | 1363 | _ASSERT_L( L, lua_istable( L, -1)); |
1352 | lua_pushvalue( L, i); // ... f ... {} f | 1364 | lua_pushvalue( L, i); // ... f ... {} f |
1353 | lua_rawget( L, -2); // ... f ... {} "f.q.n" | 1365 | lua_rawget( L, -2); // ... f ... {} "f.q.n" |
1354 | fqn = lua_tolstring( L, -1, &len); | 1366 | fqn = lua_tolstring( L, -1, &len); |
1367 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "function [C] %s \n" INDENT_END, fqn)); | ||
1355 | // popping doesn't invalidate the pointer since this is an interned string gotten from the lookup database | 1368 | // popping doesn't invalidate the pointer since this is an interned string gotten from the lookup database |
1356 | lua_pop( L, 2); // ... f ... | 1369 | lua_pop( L, 2); // ... f ... |
1357 | if( !fqn) | 1370 | if( !fqn) |
@@ -1366,9 +1379,9 @@ static void lookup_native_func( lua_State* L2, lua_State* L, uint_t i) | |||
1366 | (void) luaL_error( L, "%s '%s' not found in %s origin transfer database.", lua_tostring( L, -3), lua_tostring( L, -2), from ? from : "main"); | 1379 | (void) luaL_error( L, "%s '%s' not found in %s origin transfer database.", lua_tostring( L, -3), lua_tostring( L, -2), from ? from : "main"); |
1367 | return; | 1380 | return; |
1368 | } | 1381 | } |
1369 | STACK_END( L, 0) | 1382 | STACK_END( L, 0); |
1370 | // push the equivalent function in the destination's stack, retrieved from the lookup table | 1383 | // push the equivalent function in the destination's stack, retrieved from the lookup table |
1371 | STACK_CHECK( L2) | 1384 | STACK_CHECK( L2); |
1372 | lua_getfield( L2, LUA_REGISTRYINDEX, LOOKUP_KEY); // {} | 1385 | lua_getfield( L2, LUA_REGISTRYINDEX, LOOKUP_KEY); // {} |
1373 | _ASSERT_L( L2, lua_istable( L2, -1)); | 1386 | _ASSERT_L( L2, lua_istable( L2, -1)); |
1374 | lua_pushlstring( L2, fqn, len); // {} "f.q.n" | 1387 | lua_pushlstring( L2, fqn, len); // {} "f.q.n" |
@@ -1384,7 +1397,7 @@ static void lookup_native_func( lua_State* L2, lua_State* L, uint_t i) | |||
1384 | return; | 1397 | return; |
1385 | } | 1398 | } |
1386 | lua_remove( L2, -2); // f | 1399 | lua_remove( L2, -2); // f |
1387 | STACK_END( L2, 1) | 1400 | STACK_END( L2, 1); |
1388 | } | 1401 | } |
1389 | 1402 | ||
1390 | /* | 1403 | /* |
@@ -1403,7 +1416,7 @@ static void inter_copy_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, uin | |||
1403 | 1416 | ||
1404 | ASSERT_L( L2_cache_i != 0); // ... {cache} ... p | 1417 | ASSERT_L( L2_cache_i != 0); // ... {cache} ... p |
1405 | STACK_GROW(L,2); | 1418 | STACK_GROW(L,2); |
1406 | STACK_CHECK(L) | 1419 | STACK_CHECK( L); |
1407 | 1420 | ||
1408 | if( funcSubType == FST_Bytecode) | 1421 | if( funcSubType == FST_Bytecode) |
1409 | { | 1422 | { |
@@ -1448,7 +1461,7 @@ static void inter_copy_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, uin | |||
1448 | // fills 'name' 'namewhat' and 'linedefined', pops function | 1461 | // fills 'name' 'namewhat' and 'linedefined', pops function |
1449 | lua_getinfo(L, ">nS", &ar); // ... b | 1462 | lua_getinfo(L, ">nS", &ar); // ... b |
1450 | name = ar.namewhat; | 1463 | name = ar.namewhat; |
1451 | fprintf( stderr, "%.*sFNAME: %s @ %d\n", i, s_indent, ar.short_src, ar.linedefined); // just gives NULL | 1464 | fprintf( stderr, INDENT_BEGIN "FNAME: %s @ %d\n", i, s_indent, ar.short_src, ar.linedefined); // just gives NULL |
1452 | } | 1465 | } |
1453 | #endif // LOG_FUNC_INFO | 1466 | #endif // LOG_FUNC_INFO |
1454 | { | 1467 | { |
@@ -1480,7 +1493,7 @@ static void inter_copy_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, uin | |||
1480 | // cache[p] = function | 1493 | // cache[p] = function |
1481 | lua_rawset( L2, L2_cache_i); // ... {cache} ... function | 1494 | lua_rawset( L2, L2_cache_i); // ... {cache} ... function |
1482 | } | 1495 | } |
1483 | STACK_MID( L, 0) | 1496 | STACK_MID( L, 0); |
1484 | 1497 | ||
1485 | /* push over any upvalues; references to this function will come from | 1498 | /* push over any upvalues; references to this function will come from |
1486 | * cache so we don't end up in eternal loop. | 1499 | * cache so we don't end up in eternal loop. |
@@ -1497,7 +1510,7 @@ static void inter_copy_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, uin | |||
1497 | #endif // LUA_VERSION_NUM | 1510 | #endif // LUA_VERSION_NUM |
1498 | for( n = 0; (DEBUGSPEW_CODE( upname =) lua_getupvalue( L, i, 1 + n)) != NULL; ++ n) | 1511 | for( n = 0; (DEBUGSPEW_CODE( upname =) lua_getupvalue( L, i, 1 + n)) != NULL; ++ n) |
1499 | { // ... _G up[n] | 1512 | { // ... _G up[n] |
1500 | DEBUGSPEW_CODE( fprintf( stderr, "%.*sUPNAME[%d]: %s\n", i, debugspew_indent, n, upname)); | 1513 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "UPNAME[%d]: %s\n" INDENT_END, n, upname)); |
1501 | #if LUA_VERSION_NUM == 502 | 1514 | #if LUA_VERSION_NUM == 502 |
1502 | if( lua_rawequal( L, -1, -2)) // is the upvalue equal to the global table? | 1515 | if( lua_rawequal( L, -1, -2)) // is the upvalue equal to the global table? |
1503 | { | 1516 | { |
@@ -1517,7 +1530,7 @@ static void inter_copy_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, uin | |||
1517 | } | 1530 | } |
1518 | // L2: function + 'n' upvalues (>=0) | 1531 | // L2: function + 'n' upvalues (>=0) |
1519 | 1532 | ||
1520 | STACK_MID( L, 0) | 1533 | STACK_MID( L, 0); |
1521 | 1534 | ||
1522 | // Set upvalues (originally set to 'nil' by 'lua_load') | 1535 | // Set upvalues (originally set to 'nil' by 'lua_load') |
1523 | { | 1536 | { |
@@ -1539,11 +1552,10 @@ static void inter_copy_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, uin | |||
1539 | else // C function OR LuaJIT fast function!!! | 1552 | else // C function OR LuaJIT fast function!!! |
1540 | { | 1553 | { |
1541 | lua_pop( L2, 1); // ... {cache} ... | 1554 | lua_pop( L2, 1); // ... {cache} ... |
1542 | DEBUGSPEW_CODE( fprintf( stderr, "%.*sFNAME: [C] function %p \n", i, debugspew_indent, cfunc)); | ||
1543 | // No need to transfer upvalues for C/JIT functions since they weren't actually copied, only looked up | 1555 | // No need to transfer upvalues for C/JIT functions since they weren't actually copied, only looked up |
1544 | lookup_native_func( L2, L, i); // ... {cache} ... function | 1556 | lookup_native_func( L2, L, i); // ... {cache} ... function |
1545 | } | 1557 | } |
1546 | STACK_END( L, 0) | 1558 | STACK_END( L, 0); |
1547 | } | 1559 | } |
1548 | 1560 | ||
1549 | /* | 1561 | /* |
@@ -1558,206 +1570,253 @@ static void inter_copy_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, uin | |||
1558 | */ | 1570 | */ |
1559 | static bool_t inter_copy_one_( lua_State *L2, uint_t L2_cache_i, lua_State *L, uint_t i, enum e_vt vt ) | 1571 | static bool_t inter_copy_one_( lua_State *L2, uint_t L2_cache_i, lua_State *L, uint_t i, enum e_vt vt ) |
1560 | { | 1572 | { |
1561 | bool_t ret= TRUE; | 1573 | bool_t ret= TRUE; |
1562 | 1574 | ||
1563 | STACK_GROW( L2, 1 ); | 1575 | STACK_GROW( L2, 1 ); |
1564 | 1576 | ||
1565 | STACK_CHECK(L2) | 1577 | STACK_CHECK( L2); |
1566 | 1578 | ||
1567 | switch ( lua_type(L,i) ) { | 1579 | switch ( lua_type( L, i)) |
1568 | /* Basic types allowed both as values, and as table keys */ | 1580 | { |
1581 | /* Basic types allowed both as values, and as table keys */ | ||
1569 | 1582 | ||
1570 | case LUA_TBOOLEAN: | 1583 | case LUA_TBOOLEAN: |
1571 | lua_pushboolean( L2, lua_toboolean(L, i) ); | 1584 | lua_pushboolean( L2, lua_toboolean( L, i)); |
1572 | break; | 1585 | break; |
1573 | 1586 | ||
1574 | case LUA_TNUMBER: | 1587 | case LUA_TNUMBER: |
1575 | /* LNUM patch support (keeping integer accuracy) */ | 1588 | /* LNUM patch support (keeping integer accuracy) */ |
1576 | #ifdef LUA_LNUM | 1589 | #ifdef LUA_LNUM |
1577 | if (lua_isinteger(L,i)) { | 1590 | if( lua_isinteger(L,i)) |
1578 | lua_pushinteger( L2, lua_tointeger(L, i) ); | 1591 | { |
1579 | break; | 1592 | lua_Integer v = lua_tointeger( L, i); |
1580 | } | 1593 | DEBUGSPEW_CODE( if( vt == VT_KEY) fprintf( stderr, INDENT_BEGIN "KEY: %d\n" INDENT_END, v)); |
1594 | lua_pushinteger( L2, v); | ||
1595 | break; | ||
1596 | } | ||
1597 | else | ||
1581 | #endif | 1598 | #endif |
1582 | lua_pushnumber( L2, lua_tonumber(L, i) ); | 1599 | { |
1583 | break; | 1600 | lua_Number v = lua_tonumber( L, i); |
1584 | 1601 | DEBUGSPEW_CODE( if( vt == VT_KEY) fprintf( stderr, INDENT_BEGIN "KEY: " LUA_NUMBER_FMT "\n" INDENT_END, v)); | |
1585 | case LUA_TSTRING: { | 1602 | lua_pushnumber( L2, v); |
1586 | size_t len; const char* s = lua_tolstring( L, i, &len); | 1603 | } |
1587 | DEBUGSPEW_CODE( if( vt == VT_KEY) fprintf( stderr, "%.*sKEY: %s\n", i, debugspew_indent, s)); | 1604 | break; |
1588 | lua_pushlstring( L2, s, len ); | 1605 | |
1589 | } break; | 1606 | case LUA_TSTRING: |
1590 | 1607 | { | |
1591 | case LUA_TLIGHTUSERDATA: | 1608 | size_t len; |
1592 | lua_pushlightuserdata( L2, lua_touserdata(L, i) ); | 1609 | char const* s = lua_tolstring( L, i, &len); |
1593 | break; | 1610 | DEBUGSPEW_CODE( if( vt == VT_KEY) fprintf( stderr, INDENT_BEGIN "KEY: %s\n" INDENT_END, s)); |
1594 | 1611 | lua_pushlstring( L2, s, len); | |
1595 | /* The following types are not allowed as table keys */ | 1612 | } |
1596 | 1613 | break; | |
1597 | case LUA_TUSERDATA: if (vt==VT_KEY) { ret=FALSE; break; } | 1614 | |
1598 | /* Allow only deep userdata entities to be copied across | 1615 | case LUA_TLIGHTUSERDATA: |
1599 | */ | 1616 | lua_pushlightuserdata( L2, lua_touserdata(L, i)); |
1600 | if (!luaG_copydeep( L, L2, i )) { | 1617 | break; |
1601 | // Cannot copy it full; copy as light userdata | 1618 | |
1602 | // | 1619 | /* The following types are not allowed as table keys */ |
1603 | lua_pushlightuserdata( L2, lua_touserdata(L, i) ); | 1620 | |
1604 | } break; | 1621 | case LUA_TUSERDATA: |
1605 | 1622 | if( vt == VT_KEY) | |
1606 | case LUA_TNIL: if (vt==VT_KEY) { ret=FALSE; break; } | 1623 | { |
1607 | lua_pushnil(L2); | 1624 | ret = FALSE; |
1608 | break; | 1625 | break; |
1609 | 1626 | } | |
1610 | case LUA_TFUNCTION: if (vt==VT_KEY) { ret=FALSE; break; } { | 1627 | /* Allow only deep userdata entities to be copied across |
1611 | /* | 1628 | */ |
1612 | * Passing C functions is risky; if they refer to LUA_ENVIRONINDEX | 1629 | if( !luaG_copydeep( L, L2, i)) |
1613 | * and/or LUA_REGISTRYINDEX they might work unintended (not work) | 1630 | { |
1614 | * at the target. | 1631 | // Cannot copy it full; copy as light userdata |
1615 | * | 1632 | // |
1616 | * On the other hand, NOT copying them causes many self tests not | 1633 | lua_pushlightuserdata( L2, lua_touserdata( L, i)); |
1617 | * to work (timer, hangtest, ...) | 1634 | } |
1618 | * | 1635 | break; |
1619 | * The trouble is, we cannot KNOW if the function at hand is safe | 1636 | |
1620 | * or not. We cannot study it's behaviour. We could trust the user, | 1637 | case LUA_TNIL: |
1621 | * but they might not even know they're sending lua_CFunction over | 1638 | if( vt == VT_KEY) |
1622 | * (as upvalues etc.). | 1639 | { |
1623 | */ | 1640 | ret = FALSE; |
1641 | break; | ||
1642 | } | ||
1643 | lua_pushnil( L2); | ||
1644 | break; | ||
1645 | |||
1646 | case LUA_TFUNCTION: | ||
1647 | if( vt == VT_KEY) | ||
1648 | { | ||
1649 | ret = FALSE; | ||
1650 | break; | ||
1651 | } | ||
1652 | { | ||
1653 | /* | ||
1654 | * Passing C functions is risky; if they refer to LUA_ENVIRONINDEX | ||
1655 | * and/or LUA_REGISTRYINDEX they might work unintended (not work) | ||
1656 | * at the target. | ||
1657 | * | ||
1658 | * On the other hand, NOT copying them causes many self tests not | ||
1659 | * to work (timer, hangtest, ...) | ||
1660 | * | ||
1661 | * The trouble is, we cannot KNOW if the function at hand is safe | ||
1662 | * or not. We cannot study it's behaviour. We could trust the user, | ||
1663 | * but they might not even know they're sending lua_CFunction over | ||
1664 | * (as upvalues etc.). | ||
1665 | */ | ||
1624 | #if 0 | 1666 | #if 0 |
1625 | if (lua_iscfunction(L,i)) | 1667 | if( lua_iscfunction( L, i)) |
1626 | luaL_error( L, "Copying lua_CFunction between Lua states is risky, and currently disabled." ); | 1668 | luaL_error( L, "Copying lua_CFunction between Lua states is risky, and currently disabled." ); |
1627 | #endif | 1669 | #endif |
1628 | STACK_CHECK(L2) | 1670 | STACK_CHECK( L2); |
1629 | push_cached_func( L2, L2_cache_i, L, i ); | 1671 | push_cached_func( L2, L2_cache_i, L, i); |
1630 | ASSERT_L( lua_isfunction(L2,-1) ); | 1672 | ASSERT_L( lua_isfunction( L2, -1)); |
1631 | STACK_END(L2,1) | 1673 | STACK_END( L2, 1); |
1632 | } break; | 1674 | } |
1675 | break; | ||
1633 | 1676 | ||
1634 | case LUA_TTABLE: if (vt==VT_KEY) { ret=FALSE; break; } { | 1677 | case LUA_TTABLE: |
1635 | 1678 | if( vt == VT_KEY) | |
1636 | STACK_CHECK(L) | 1679 | { |
1637 | STACK_CHECK(L2) | 1680 | ret = FALSE; |
1638 | 1681 | break; | |
1639 | /* Check if we've already copied the same table from 'L' (during this transmission), and | 1682 | } |
1640 | * reuse the old copy. This allows table upvalues shared by multiple | 1683 | { |
1641 | * local functions to point to the same table, also in the target. | 1684 | STACK_CHECK( L); |
1642 | * Also, this takes care of cyclic tables and multiple references | 1685 | STACK_CHECK( L2); |
1643 | * to the same subtable. | 1686 | |
1644 | * | 1687 | /* Check if we've already copied the same table from 'L' (during this transmission), and |
1645 | * Note: Even metatables need to go through this test; to detect | 1688 | * reuse the old copy. This allows table upvalues shared by multiple |
1646 | * loops s.a. those in required module tables (getmetatable(lanes).lanes == lanes) | 1689 | * local functions to point to the same table, also in the target. |
1647 | */ | 1690 | * Also, this takes care of cyclic tables and multiple references |
1648 | if (push_cached_table( L2, L2_cache_i, L, i )) { | 1691 | * to the same subtable. |
1649 | ASSERT_L( lua_istable(L2, -1) ); // from cache | 1692 | * |
1650 | break; | 1693 | * Note: Even metatables need to go through this test; to detect |
1651 | } | 1694 | * loops s.a. those in required module tables (getmetatable(lanes).lanes == lanes) |
1652 | ASSERT_L( lua_istable(L2,-1) ); | 1695 | */ |
1653 | 1696 | if( push_cached_table( L2, L2_cache_i, L, i)) | |
1654 | STACK_GROW( L, 2 ); | 1697 | { |
1655 | STACK_GROW( L2, 2 ); | 1698 | ASSERT_L( lua_istable( L2, -1)); // from cache |
1656 | 1699 | break; | |
1657 | lua_pushnil(L); // start iteration | 1700 | } |
1658 | while( lua_next( L, i ) ) { | 1701 | ASSERT_L( lua_istable( L2,-1)); |
1659 | uint_t val_i= lua_gettop(L); | ||
1660 | uint_t key_i= val_i-1; | ||
1661 | |||
1662 | /* Only basic key types are copied over; others ignored | ||
1663 | */ | ||
1664 | if (inter_copy_one_( L2, 0 /*key*/, L, key_i, VT_KEY )) { | ||
1665 | /* | ||
1666 | * Contents of metatables are copied with cache checking; | ||
1667 | * important to detect loops. | ||
1668 | */ | ||
1669 | if (inter_copy_one_( L2, L2_cache_i, L, val_i, VT_NORMAL )) { | ||
1670 | ASSERT_L( lua_istable(L2,-3) ); | ||
1671 | lua_rawset( L2, -3 ); // add to table (pops key & val) | ||
1672 | } else { | ||
1673 | luaL_error( L, "Unable to copy over type '%s' (in %s)", | ||
1674 | luaL_typename(L,val_i), | ||
1675 | vt==VT_NORMAL ? "table":"metatable" ); | ||
1676 | } | ||
1677 | } | ||
1678 | lua_pop( L, 1 ); // pop value (next round) | ||
1679 | } | ||
1680 | STACK_MID(L,0) | ||
1681 | STACK_MID(L2,1) | ||
1682 | |||
1683 | /* Metatables are expected to be immutable, and copied only once. | ||
1684 | */ | ||
1685 | if (lua_getmetatable( L, i )) { | ||
1686 | // | ||
1687 | // L [-1]: metatable | ||
1688 | |||
1689 | uint_t mt_id= get_mt_id( L, -1 ); // Unique id for the metatable | ||
1690 | |||
1691 | STACK_GROW(L2,4); | ||
1692 | |||
1693 | push_registry_subtable( L2, REG_MTID ); | ||
1694 | STACK_MID(L2,2); | ||
1695 | lua_pushinteger( L2, mt_id ); | ||
1696 | lua_rawget( L2, -2 ); | ||
1697 | // | ||
1698 | // L2 ([-3]: copied table) | ||
1699 | // [-2]: reg[REG_MTID] | ||
1700 | // [-1]: nil/metatable pre-known in L2 | ||
1701 | |||
1702 | STACK_MID(L2,3); | ||
1703 | |||
1704 | if (lua_isnil(L2,-1)) { /* L2 did not know the metatable */ | ||
1705 | lua_pop(L2,1); | ||
1706 | STACK_MID(L2,2); | ||
1707 | ASSERT_L( lua_istable(L,-1) ); | ||
1708 | if (inter_copy_one_( L2, L2_cache_i /*for function cacheing*/, L, lua_gettop(L) /*[-1]*/, VT_METATABLE )) { | ||
1709 | // | ||
1710 | // L2 ([-3]: copied table) | ||
1711 | // [-2]: reg[REG_MTID] | ||
1712 | // [-1]: metatable (copied from L) | ||
1713 | |||
1714 | STACK_MID(L2,3); | ||
1715 | // mt_id -> metatable | ||
1716 | // | ||
1717 | lua_pushinteger(L2,mt_id); | ||
1718 | lua_pushvalue(L2,-2); | ||
1719 | lua_rawset(L2,-4); | ||
1720 | |||
1721 | // metatable -> mt_id | ||
1722 | // | ||
1723 | lua_pushvalue(L2,-1); | ||
1724 | lua_pushinteger(L2,mt_id); | ||
1725 | lua_rawset(L2,-4); | ||
1726 | |||
1727 | STACK_MID(L2,3); | ||
1728 | } else { | ||
1729 | luaL_error( L, "Error copying a metatable" ); | ||
1730 | } | ||
1731 | STACK_MID(L2,3); | ||
1732 | } | ||
1733 | // L2 ([-3]: copied table) | ||
1734 | // [-2]: reg[REG_MTID] | ||
1735 | // [-1]: metatable (pre-known or copied from L) | ||
1736 | 1702 | ||
1737 | lua_remove(L2,-2); // take away 'reg[REG_MTID]' | 1703 | STACK_GROW( L, 2); |
1738 | // | 1704 | STACK_GROW( L2, 2); |
1739 | // L2: ([-2]: copied table) | ||
1740 | // [-1]: metatable for that table | ||
1741 | 1705 | ||
1742 | lua_setmetatable( L2, -2 ); | 1706 | lua_pushnil( L); // start iteration |
1743 | 1707 | while( lua_next( L, i)) | |
1744 | // L2: [-1]: copied table (with metatable set if source had it) | 1708 | { |
1709 | uint_t val_i = lua_gettop(L); | ||
1710 | uint_t key_i = val_i - 1; | ||
1745 | 1711 | ||
1746 | lua_pop(L,1); // remove source metatable (L, not L2!) | 1712 | /* Only basic key types are copied over; others ignored |
1747 | } | 1713 | */ |
1748 | STACK_END(L2,1) | 1714 | if( inter_copy_one_( L2, 0 /*key*/, L, key_i, VT_KEY)) |
1749 | STACK_END(L,0) | 1715 | { |
1750 | } break; | 1716 | /* |
1717 | * Contents of metatables are copied with cache checking; | ||
1718 | * important to detect loops. | ||
1719 | */ | ||
1720 | if( inter_copy_one_( L2, L2_cache_i, L, val_i, VT_NORMAL)) | ||
1721 | { | ||
1722 | ASSERT_L( lua_istable(L2,-3)); | ||
1723 | lua_rawset( L2, -3); // add to table (pops key & val) | ||
1724 | } | ||
1725 | else | ||
1726 | { | ||
1727 | luaL_error( L, "Unable to copy over type '%s' (in %s)", luaL_typename( L, val_i), (vt == VT_NORMAL) ? "table" : "metatable"); | ||
1728 | } | ||
1729 | } | ||
1730 | lua_pop( L, 1); // pop value (next round) | ||
1731 | } | ||
1732 | STACK_MID( L, 0); | ||
1733 | STACK_MID( L2, 1); | ||
1751 | 1734 | ||
1752 | /* The following types cannot be copied */ | 1735 | /* Metatables are expected to be immutable, and copied only once. |
1736 | */ | ||
1737 | if( lua_getmetatable( L, i)) | ||
1738 | { | ||
1739 | // | ||
1740 | // L [-1]: metatable | ||
1753 | 1741 | ||
1754 | case LUA_TTHREAD: | 1742 | uint_t mt_id = get_mt_id( L, -1); // Unique id for the metatable |
1755 | ret=FALSE; break; | ||
1756 | } | ||
1757 | 1743 | ||
1758 | STACK_END(L2, ret? 1:0) | 1744 | STACK_GROW( L2, 4); |
1759 | 1745 | ||
1760 | return ret; | 1746 | push_registry_subtable( L2, REG_MTID); |
1747 | STACK_MID( L2, 2); | ||
1748 | lua_pushinteger( L2, mt_id); | ||
1749 | lua_rawget( L2, -2); | ||
1750 | // | ||
1751 | // L2 ([-3]: copied table) | ||
1752 | // [-2]: reg[REG_MTID] | ||
1753 | // [-1]: nil/metatable pre-known in L2 | ||
1754 | |||
1755 | STACK_MID( L2, 3); | ||
1756 | |||
1757 | if( lua_isnil( L2, -1)) | ||
1758 | { /* L2 did not know the metatable */ | ||
1759 | lua_pop( L2, 1); | ||
1760 | STACK_MID( L2, 2); | ||
1761 | ASSERT_L( lua_istable(L,-1)); | ||
1762 | if( inter_copy_one_( L2, L2_cache_i /*for function cacheing*/, L, lua_gettop(L) /*[-1]*/, VT_METATABLE)) | ||
1763 | { | ||
1764 | // | ||
1765 | // L2 ([-3]: copied table) | ||
1766 | // [-2]: reg[REG_MTID] | ||
1767 | // [-1]: metatable (copied from L) | ||
1768 | |||
1769 | STACK_MID( L2, 3); | ||
1770 | // mt_id -> metatable | ||
1771 | // | ||
1772 | lua_pushinteger( L2, mt_id); | ||
1773 | lua_pushvalue( L2, -2); | ||
1774 | lua_rawset( L2, -4); | ||
1775 | |||
1776 | // metatable -> mt_id | ||
1777 | // | ||
1778 | lua_pushvalue( L2, -1); | ||
1779 | lua_pushinteger( L2, mt_id); | ||
1780 | lua_rawset( L2, -4); | ||
1781 | |||
1782 | STACK_MID( L2, 3); | ||
1783 | } | ||
1784 | else | ||
1785 | { | ||
1786 | luaL_error( L, "Error copying a metatable"); | ||
1787 | } | ||
1788 | STACK_MID( L2, 3); | ||
1789 | } | ||
1790 | // L2 ([-3]: copied table) | ||
1791 | // [-2]: reg[REG_MTID] | ||
1792 | // [-1]: metatable (pre-known or copied from L) | ||
1793 | |||
1794 | lua_remove( L2, -2); // take away 'reg[REG_MTID]' | ||
1795 | // | ||
1796 | // L2: ([-2]: copied table) | ||
1797 | // [-1]: metatable for that table | ||
1798 | |||
1799 | lua_setmetatable( L2, -2); | ||
1800 | |||
1801 | // L2: [-1]: copied table (with metatable set if source had it) | ||
1802 | |||
1803 | lua_pop( L, 1); // remove source metatable (L, not L2!) | ||
1804 | } | ||
1805 | STACK_END( L2, 1); | ||
1806 | STACK_END( L, 0); | ||
1807 | } | ||
1808 | break; | ||
1809 | |||
1810 | /* The following types cannot be copied */ | ||
1811 | |||
1812 | case LUA_TTHREAD: | ||
1813 | ret = FALSE; | ||
1814 | break; | ||
1815 | } | ||
1816 | |||
1817 | STACK_END( L2, ret ? 1 : 0); | ||
1818 | |||
1819 | return ret; | ||
1761 | } | 1820 | } |
1762 | 1821 | ||
1763 | 1822 | ||
@@ -1829,9 +1888,11 @@ int luaG_inter_move( lua_State* L, lua_State* L2, uint_t n) | |||
1829 | 1888 | ||
1830 | void luaG_inter_copy_package( lua_State* L, lua_State* L2, int _idx) | 1889 | void luaG_inter_copy_package( lua_State* L, lua_State* L2, int _idx) |
1831 | { | 1890 | { |
1891 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_inter_copy_package()\n" INDENT_END)); | ||
1892 | DEBUGSPEW_CODE( ++ debugspew_indent_depth); | ||
1832 | // package | 1893 | // package |
1833 | STACK_CHECK( L) | 1894 | STACK_CHECK( L); |
1834 | STACK_CHECK( L2) | 1895 | STACK_CHECK( L2); |
1835 | _idx = lua_absindex( L, _idx); | 1896 | _idx = lua_absindex( L, _idx); |
1836 | if( lua_type( L, _idx) != LUA_TTABLE) | 1897 | if( lua_type( L, _idx) != LUA_TTABLE) |
1837 | { | 1898 | { |
@@ -1845,6 +1906,7 @@ void luaG_inter_copy_package( lua_State* L, lua_State* L2, int _idx) | |||
1845 | char const* entries[] = { "path", "cpath", "preload", (LUA_VERSION_NUM == 501) ? "loaders" : "searchers", NULL}; | 1906 | char const* entries[] = { "path", "cpath", "preload", (LUA_VERSION_NUM == 501) ? "loaders" : "searchers", NULL}; |
1846 | for( i = 0; entries[i]; ++ i) | 1907 | for( i = 0; entries[i]; ++ i) |
1847 | { | 1908 | { |
1909 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%s\n" INDENT_END, entries[i])); | ||
1848 | lua_getfield( L, _idx, entries[i]); | 1910 | lua_getfield( L, _idx, entries[i]); |
1849 | if( lua_isnil( L, -1)) | 1911 | if( lua_isnil( L, -1)) |
1850 | { | 1912 | { |
@@ -1852,14 +1914,21 @@ void luaG_inter_copy_package( lua_State* L, lua_State* L2, int _idx) | |||
1852 | } | 1914 | } |
1853 | else | 1915 | else |
1854 | { | 1916 | { |
1917 | DEBUGSPEW_CODE( ++ debugspew_indent_depth); | ||
1855 | luaG_inter_move( L, L2, 1); // moves the entry to L2 | 1918 | luaG_inter_move( L, L2, 1); // moves the entry to L2 |
1919 | DEBUGSPEW_CODE( -- debugspew_indent_depth); | ||
1856 | lua_setfield( L2, -2, entries[i]); // set package[entries[i]] | 1920 | lua_setfield( L2, -2, entries[i]); // set package[entries[i]] |
1857 | } | 1921 | } |
1858 | } | 1922 | } |
1859 | } | 1923 | } |
1924 | else | ||
1925 | { | ||
1926 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "'package' not loaded, nothing to do\n" INDENT_END)); | ||
1927 | } | ||
1860 | lua_pop( L2, 1); | 1928 | lua_pop( L2, 1); |
1861 | STACK_END( L2, 0) | 1929 | STACK_END( L2, 0); |
1862 | STACK_END( L, 0) | 1930 | STACK_END( L, 0); |
1931 | DEBUGSPEW_CODE( -- debugspew_indent_depth); | ||
1863 | } | 1932 | } |
1864 | 1933 | ||
1865 | 1934 | ||
@@ -1882,7 +1951,7 @@ static int new_require( lua_State *L) | |||
1882 | //char const* modname = luaL_checkstring( L, 1); | 1951 | //char const* modname = luaL_checkstring( L, 1); |
1883 | 1952 | ||
1884 | STACK_GROW( L, args + 1); | 1953 | STACK_GROW( L, args + 1); |
1885 | STACK_CHECK( L) | 1954 | STACK_CHECK( L); |
1886 | 1955 | ||
1887 | lua_pushvalue( L, lua_upvalueindex(1)); | 1956 | lua_pushvalue( L, lua_upvalueindex(1)); |
1888 | for( i = 1; i <= args; ++ i) | 1957 | for( i = 1; i <= args; ++ i) |
@@ -1900,7 +1969,7 @@ static int new_require( lua_State *L) | |||
1900 | MUTEX_UNLOCK( &require_cs); | 1969 | MUTEX_UNLOCK( &require_cs); |
1901 | 1970 | ||
1902 | // the required module (or an error message) is left on the stack as returned value by original require function | 1971 | // the required module (or an error message) is left on the stack as returned value by original require function |
1903 | STACK_END( L, 1) | 1972 | STACK_END( L, 1); |
1904 | 1973 | ||
1905 | if (rc) | 1974 | if (rc) |
1906 | lua_error(L); // error message already at [-1] | 1975 | lua_error(L); // error message already at [-1] |
@@ -1914,7 +1983,7 @@ static int new_require( lua_State *L) | |||
1914 | void serialize_require( lua_State *L ) | 1983 | void serialize_require( lua_State *L ) |
1915 | { | 1984 | { |
1916 | STACK_GROW( L, 1); | 1985 | STACK_GROW( L, 1); |
1917 | STACK_CHECK( L) | 1986 | STACK_CHECK( L); |
1918 | 1987 | ||
1919 | // Check 'require' is there; if not, do nothing | 1988 | // Check 'require' is there; if not, do nothing |
1920 | // | 1989 | // |
@@ -1931,5 +2000,5 @@ void serialize_require( lua_State *L ) | |||
1931 | lua_pop( L, 1); | 2000 | lua_pop( L, 1); |
1932 | } | 2001 | } |
1933 | 2002 | ||
1934 | STACK_END( L, 0) | 2003 | STACK_END( L, 0); |
1935 | } | 2004 | } |
diff --git a/src/tools.h b/src/tools.h index e4fbd94..f79d2ad 100644 --- a/src/tools.h +++ b/src/tools.h | |||
@@ -38,6 +38,9 @@ | |||
38 | #define USE_DEBUG_SPEW 0 | 38 | #define USE_DEBUG_SPEW 0 |
39 | #if USE_DEBUG_SPEW | 39 | #if USE_DEBUG_SPEW |
40 | extern char const* debugspew_indent; | 40 | extern char const* debugspew_indent; |
41 | extern int debugspew_indent_depth; | ||
42 | #define INDENT_BEGIN "%.*s " | ||
43 | #define INDENT_END , debugspew_indent_depth, debugspew_indent | ||
41 | #define DEBUGSPEW_CODE(_code) _code | 44 | #define DEBUGSPEW_CODE(_code) _code |
42 | #else // USE_DEBUG_SPEW | 45 | #else // USE_DEBUG_SPEW |
43 | #define DEBUGSPEW_CODE(_code) | 46 | #define DEBUGSPEW_CODE(_code) |
@@ -53,10 +56,16 @@ extern char const* debugspew_indent; | |||
53 | #else | 56 | #else |
54 | #define _ASSERT_L(lua,c) do { if (!(c)) luaL_error( lua, "ASSERT failed: %s:%d '%s'", __FILE__, __LINE__, #c ); } while( 0) | 57 | #define _ASSERT_L(lua,c) do { if (!(c)) luaL_error( lua, "ASSERT failed: %s:%d '%s'", __FILE__, __LINE__, #c ); } while( 0) |
55 | // | 58 | // |
56 | #define STACK_CHECK(L) { int _oldtop_##L = lua_gettop(L); | 59 | #define STACK_CHECK(L) { int const _oldtop_##L = lua_gettop( L) |
57 | #define STACK_MID(L,change) { int a= lua_gettop(L)-_oldtop_##L; int b= (change); \ | 60 | #define STACK_MID(L,change) \ |
58 | if (a != b) luaL_error( L, "STACK ASSERT failed (%d not %d): %s:%d", a, b, __FILE__, __LINE__ ); } | 61 | do \ |
59 | #define STACK_END(L,change) STACK_MID(L,change) } | 62 | { \ |
63 | int a = lua_gettop( L) - _oldtop_##L; \ | ||
64 | int b = (change); \ | ||
65 | if( a != b) \ | ||
66 | luaL_error( L, "STACK ASSERT failed (%d not %d): %s:%d", a, b, __FILE__, __LINE__ ); \ | ||
67 | } while( 0) | ||
68 | #define STACK_END(L,change) STACK_MID(L,change); } | ||
60 | 69 | ||
61 | #define STACK_DUMP(L) luaG_dump(L); | 70 | #define STACK_DUMP(L) luaG_dump(L); |
62 | #endif | 71 | #endif |