aboutsummaryrefslogtreecommitdiff
path: root/src/tools.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools.c')
-rw-r--r--src/tools.c260
1 files changed, 108 insertions, 152 deletions
diff --git a/src/tools.c b/src/tools.c
index a2ec517..2f3140d 100644
--- a/src/tools.c
+++ b/src/tools.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * TOOLS.C Copyright (c) 2002-08, Asko Kauppi 2 * TOOLS.C Copyright (c) 2002-10, Asko Kauppi
3 * 3 *
4 * Lua tools to support Lanes. 4 * Lua tools to support Lanes.
5*/ 5*/
@@ -7,7 +7,7 @@
7/* 7/*
8=============================================================================== 8===============================================================================
9 9
10Copyright (C) 2002-08 Asko Kauppi <akauppi@gmail.com> 10Copyright (C) 2002-10 Asko Kauppi <akauppi@gmail.com>
11 11
12Permission is hereby granted, free of charge, to any person obtaining a copy 12Permission is hereby granted, free of charge, to any person obtaining a copy
13of this software and associated documentation files (the "Software"), to deal 13of this software and associated documentation files (the "Software"), to deal
@@ -40,8 +40,6 @@ THE SOFTWARE.
40#include <ctype.h> 40#include <ctype.h>
41#include <stdlib.h> 41#include <stdlib.h>
42 42
43static volatile lua_CFunction hijacked_tostring; // = NULL
44
45MUTEX_T deep_lock; 43MUTEX_T deep_lock;
46MUTEX_T mtid_lock; 44MUTEX_T mtid_lock;
47 45
@@ -600,7 +598,7 @@ uint_t get_mt_id( lua_State *L, int i ) {
600 // [-2]: reg[REG_MTID] 598 // [-2]: reg[REG_MTID]
601 // [-1]: nil/uint 599 // [-1]: nil/uint
602 600
603 id= lua_tointeger(L,-1); // 0 for nil 601 id= (uint_t)lua_tointeger(L,-1); // 0 for nil
604 lua_pop(L,1); 602 lua_pop(L,1);
605 STACK_MID(L,1) 603 STACK_MID(L,1)
606 604
@@ -644,73 +642,60 @@ static int buf_writer( lua_State *L, const void* b, size_t n, void* B ) {
644 * Returns TRUE if the table was cached (no need to fill it!); FALSE if 642 * Returns TRUE if the table was cached (no need to fill it!); FALSE if
645 * it's a virgin. 643 * it's a virgin.
646 */ 644 */
647static 645static bool_t push_cached_table( lua_State *L2, uint_t L2_cache_i, lua_State *L, uint_t i )
648bool_t push_cached_table( lua_State *L2, uint_t L2_cache_i, lua_State *L, uint_t i ) { 646{
649 bool_t ret; 647 bool_t ret;
650
651 ASSERT_L( hijacked_tostring );
652 ASSERT_L( L2_cache_i != 0 );
653
654 STACK_GROW(L,2);
655 STACK_GROW(L2,3);
656 648
657 // Create an identity string for table at [i]; it should stay unique at 649 ASSERT_L( L2_cache_i != 0 );
658 // least during copying of the data (then we can clear the caches).
659 //
660 STACK_CHECK(L)
661 lua_pushcfunction( L, hijacked_tostring );
662 lua_pushvalue( L, i );
663 lua_call( L, 1 /*args*/, 1 /*retvals*/ );
664 //
665 // [-1]: "table: 0x...."
666 650
667 STACK_END(L,1) 651 STACK_GROW(L2,3);
668 ASSERT_L( lua_type(L,-1) == LUA_TSTRING );
669 652
670 // L2_cache[id_str]= [{...}] 653 // L2_cache[id_str]= [{...}]
671 // 654 //
672 STACK_CHECK(L2) 655 STACK_CHECK(L2)
673 656
674 // We don't need to use the from state ('L') in ID since the life span 657 // We don't need to use the from state ('L') in ID since the life span
675 // is only for the duration of a copy (both states are locked). 658 // is only for the duration of a copy (both states are locked).
676 // 659 //
677 lua_pushstring( L2, lua_tostring(L,-1) ); 660 lua_pushlightuserdata( L2, (void*)lua_topointer( L, i )); // push a light userdata uniquely representing the table
678 lua_pop(L,1); // remove the 'tostring(tbl)' value (in L!)
679 661
680//fprintf( stderr, "<< ID: %s >>\n", lua_tostring(L2,-1) ); 662 //fprintf( stderr, "<< ID: %s >>\n", lua_tostring(L2,-1) );
681 663
682 lua_pushvalue( L2, -1 ); 664 lua_pushvalue( L2, -1 );
683 lua_rawget( L2, L2_cache_i ); 665 lua_rawget( L2, L2_cache_i );
684 // 666 //
685 // [-2]: identity string ("table: 0x...") 667 // [-2]: identity table pointer lightuserdata
686 // [-1]: table|nil 668 // [-1]: table|nil
687
688 if (lua_isnil(L2,-1)) {
689 lua_pop(L2,1);
690 lua_newtable(L2);
691 lua_pushvalue(L2,-1);
692 lua_insert(L2,-3);
693 //
694 // [-3]: new table (2nd ref)
695 // [-2]: identity string
696 // [-1]: new table
697 669
698 lua_rawset(L2, L2_cache_i); 670 if (lua_isnil(L2,-1))
699 // 671 {
700 // [-1]: new table (tied to 'L2_cache' table') 672 lua_pop(L2,1);
701 673 lua_newtable(L2);
702 ret= FALSE; // brand new 674 lua_pushvalue(L2,-1);
703 675 lua_insert(L2,-3);
704 } else { 676 //
705 lua_remove(L2,-2); 677 // [-3]: new table (2nd ref)
706 ret= TRUE; // from cache 678 // [-2]: identity table pointer lightuserdata
707 } 679 // [-1]: new table
708 STACK_END(L2,1)
709 //
710 // L2 [-1]: table to use as destination
711 680
712 ASSERT_L( lua_istable(L2,-1) ); 681 lua_rawset(L2, L2_cache_i);
713 return ret; 682 //
683 // [-1]: new table (tied to 'L2_cache' table')
684
685 ret= FALSE; // brand new
686
687 }
688 else
689 {
690 lua_remove(L2,-2);
691 ret= TRUE; // from cache
692 }
693 STACK_END(L2,1)
694 //
695 // L2 [-1]: table to use as destination
696
697 ASSERT_L( lua_istable(L2,-1) );
698 return ret;
714} 699}
715 700
716 701
@@ -722,82 +707,76 @@ bool_t push_cached_table( lua_State *L2, uint_t L2_cache_i, lua_State *L, uint_t
722 */ 707 */
723static void inter_copy_func( lua_State *L2, uint_t L2_cache_i, lua_State *L, uint_t i ); 708static void inter_copy_func( lua_State *L2, uint_t L2_cache_i, lua_State *L, uint_t i );
724 709
725static 710static void push_cached_func( lua_State *L2, uint_t L2_cache_i, lua_State *L, uint_t i )
726void push_cached_func( lua_State *L2, uint_t L2_cache_i, lua_State *L, uint_t i ) { 711{
727 // TBD: Merge this and same code for tables 712 // TBD: Merge this and same code for tables
728 713
729 ASSERT_L( hijacked_tostring ); 714 ASSERT_L( L2_cache_i != 0 );
730 ASSERT_L( L2_cache_i != 0 );
731 715
732 STACK_GROW(L,2); 716 STACK_GROW(L2,3);
733 STACK_GROW(L2,3);
734 717
735 STACK_CHECK(L) 718 // L2_cache[id_str]= function
736 lua_pushcfunction( L, hijacked_tostring ); 719 //
737 lua_pushvalue( L, i ); 720 STACK_CHECK(L2)
738 lua_call( L, 1 /*args*/, 1 /*retvals*/ );
739 //
740 // [-1]: "function: 0x...."
741 721
742 STACK_END(L,1) 722 // We don't need to use the from state ('L') in ID since the life span
743 ASSERT_L( lua_type(L,-1) == LUA_TSTRING ); 723 // is only for the duration of a copy (both states are locked).
744 724 //
745 // L2_cache[id_str]= function 725 lua_pushlightuserdata( L2, (void*)lua_topointer( L, i )); // push a light userdata uniquely representing the function
746 //
747 STACK_CHECK(L2)
748 726
749 // We don't need to use the from state ('L') in ID since the life span 727 //fprintf( stderr, "<< ID: %s >>\n", lua_tostring(L2,-1) );
750 // is only for the duration of a copy (both states are locked).
751 //
752 lua_pushstring( L2, lua_tostring(L,-1) );
753 lua_pop(L,1); // remove the 'tostring(tbl)' value (in L!)
754 728
755//fprintf( stderr, "<< ID: %s >>\n", lua_tostring(L2,-1) ); 729 lua_pushvalue( L2, -1 );
730 lua_rawget( L2, L2_cache_i );
731 //
732 // [-2]: identity lightuserdata function pointer
733 // [-1]: function|nil|true (true means: we're working on it; recursive)
756 734
757 lua_pushvalue( L2, -1 ); 735 if (lua_isnil(L2,-1))
758 lua_rawget( L2, L2_cache_i ); 736 {
759 // 737 lua_pop(L2,1);
760 // [-2]: identity string ("function: 0x...")
761 // [-1]: function|nil|true (true means: we're working on it; recursive)
762 738
763 if (lua_isnil(L2,-1)) { 739 // Set to 'true' for the duration of creation; need to find self-references
764 lua_pop(L2,1); 740 // via upvalues
765 741 //
766 // Set to 'true' for the duration of creation; need to find self-references 742 lua_pushvalue( L2, -1);
767 // via upvalues 743 lua_pushboolean(L2,TRUE);
768 // 744 lua_rawset( L2, L2_cache_i);
769 lua_pushboolean(L2,TRUE);
770 lua_setfield( L2, L2_cache_i, lua_tostring(L2,-2) );
771
772 inter_copy_func( L2, L2_cache_i, L, i ); // pushes a copy of the func
773 745
774 lua_pushvalue(L2,-1); 746 inter_copy_func( L2, L2_cache_i, L, i ); // pushes a copy of the func
775 lua_insert(L2,-3);
776 //
777 // [-3]: function (2nd ref)
778 // [-2]: identity string
779 // [-1]: function
780 747
781 lua_rawset(L2,L2_cache_i); 748 lua_pushvalue(L2,-1);
782 // 749 lua_insert(L2,-3);
783 // [-1]: function (tied to 'L2_cache' table') 750 //
784 751 // [-3]: function (2nd ref)
785 } else if (lua_isboolean(L2,-1)) { 752 // [-2]: identity lightuserdata function pointer
786 // Loop in preparing upvalues; either direct or via a table 753 // [-1]: function
787 //
788 // Note: This excludes the case where a function directly addresses
789 // itself as an upvalue (recursive lane creation).
790 //
791 luaL_error( L, "Recursive use of upvalues; cannot copy the function" );
792
793 } else {
794 lua_remove(L2,-2);
795 }
796 STACK_END(L2,1)
797 //
798 // L2 [-1]: function
799 754
800 ASSERT_L( lua_isfunction(L2,-1) ); 755 lua_rawset(L2,L2_cache_i);
756 //
757 // [-1]: function (tied to 'L2_cache' table')
758
759 }
760 else if (lua_isboolean(L2,-1))
761 {
762 // Loop in preparing upvalues; either direct or via a table
763 //
764 // Note: This excludes the case where a function directly addresses
765 // itself as an upvalue (recursive lane creation).
766 //
767 STACK_GROW(L,1);
768 luaL_error( L, "Recursive use of upvalues; cannot copy the function" );
769
770 }
771 else
772 {
773 lua_remove(L2,-2);
774 }
775 STACK_END(L2,1)
776 //
777 // L2 [-1]: function
778
779 ASSERT_L( lua_isfunction(L2,-1) );
801} 780}
802 781
803 782
@@ -1137,29 +1116,6 @@ void luaG_inter_copy( lua_State* L, lua_State *L2, uint_t n )
1137 uint_t top_L2= lua_gettop(L2); 1116 uint_t top_L2= lua_gettop(L2);
1138 uint_t i; 1117 uint_t i;
1139 1118
1140 /* steal Lua library's 'luaB_tostring()' from the first call. Other calls
1141 * don't have to have access to it.
1142 *
1143 * Note: multiple threads won't come here at once; this function will
1144 * be called before there can be multiple threads (no locking needed).
1145 */
1146 if (!hijacked_tostring) {
1147 STACK_GROW( L,1 );
1148
1149 STACK_CHECK(L)
1150 lua_getglobal( L, "tostring" );
1151 //
1152 // [-1]: function|nil
1153
1154 hijacked_tostring= lua_tocfunction( L, -1 );
1155 lua_pop(L,1);
1156 STACK_END(L,0)
1157
1158 if (!hijacked_tostring) {
1159 luaL_error( L, "Need to see 'tostring()' once" );
1160 }
1161 }
1162
1163 if (n > top_L) 1119 if (n > top_L)
1164 luaL_error( L, "Not enough values: %d < %d", top_L, n ); 1120 luaL_error( L, "Not enough values: %d < %d", top_L, n );
1165 1121