summaryrefslogtreecommitdiff
path: root/src/tools.c
diff options
context:
space:
mode:
authorBenoit Germain <bnt.germain@gmail.com>2011-01-04 21:31:17 +0100
committerBenoit Germain <bnt.germain@gmail.com>2011-01-04 21:31:17 +0100
commit79e46938c5d8daf164ab2d934f668fa27b32e4cf (patch)
tree407761f25bbdc3d5b2066a705dcbcf8711690242 /src/tools.c
parented07b457b6b45ece85d367dc8b89bf3c040abd9a (diff)
downloadlanes-79e46938c5d8daf164ab2d934f668fa27b32e4cf.tar.gz
lanes-79e46938c5d8daf164ab2d934f668fa27b32e4cf.tar.bz2
lanes-79e46938c5d8daf164ab2d934f668fa27b32e4cf.zip
Take all code from Asko Kauppi's SVN server, and push it here so that the github repository becomes the official Lanes source codebase.
Note that Asko's SVN server holds version 2.0.9, whereas this is version 2.0.10, but I don't see any real need to update SVN if it is to become deprecated. Next steps: - upgrade the rockspec to the latest version - make the html help available online somewhere Signed-off-by: Benoit Germain <bnt.germain@gmail.com>
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