summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBenoit Germain <bnt.germain@gmail.com>2013-02-13 20:30:04 +0100
committerBenoit Germain <bnt.germain@gmail.com>2013-02-13 20:30:26 +0100
commit577bca074df12c520f49e9361381f0cad78200c1 (patch)
tree188a4d1e3366a9351ea5b9689efbaf3f98996100 /src
parent131c11c2ae327de5b4db743a6a81eb9b57470d0e (diff)
downloadlanes-3.5.1.tar.gz
lanes-3.5.1.tar.bz2
lanes-3.5.1.zip
version 3.5.1v3.5.1
* new lanes.h header and API call luaopen_lanes_embedded() for embedders * "lanes.core" is an acceptable library in the generator libs argument * library "*" wildcard also opens lanes.core * tweaked code for Xbox 360 build
Diffstat (limited to '')
-rw-r--r--src/keeper.c2
-rw-r--r--src/lanes.c82
-rw-r--r--src/lanes.h17
-rw-r--r--src/lanes.lua30
-rw-r--r--src/threading.c21
-rw-r--r--src/threading.h18
-rw-r--r--src/tools.c80
-rw-r--r--src/tools.h1
8 files changed, 190 insertions, 61 deletions
diff --git a/src/keeper.c b/src/keeper.c
index 3511b56..848fe2a 100644
--- a/src/keeper.c
+++ b/src/keeper.c
@@ -572,7 +572,7 @@ char const* init_keepers( lua_State* L, int _on_state_create, int const _nbKeepe
572 // 572 //
573 // '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
574 // 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
575 K = luaG_newstate( L, _on_state_create, "*"); 575 K = luaG_newstate( L, _on_state_create, "K");
576 576
577 STACK_CHECK( K); 577 STACK_CHECK( K);
578 578
diff --git a/src/lanes.c b/src/lanes.c
index 2b3d8ac..7bd29ee 100644
--- a/src/lanes.c
+++ b/src/lanes.c
@@ -52,7 +52,7 @@
52 * ... 52 * ...
53 */ 53 */
54 54
55char const* VERSION = "3.5.0"; 55char const* VERSION = "3.5.1";
56 56
57/* 57/*
58=============================================================================== 58===============================================================================
@@ -92,8 +92,9 @@ THE SOFTWARE.
92#include "threading.h" 92#include "threading.h"
93#include "tools.h" 93#include "tools.h"
94#include "keeper.h" 94#include "keeper.h"
95#include "lanes.h"
95 96
96#if !((defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC)) 97#if !(defined( PLATFORM_XBOX) || defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC))
97# include <sys/time.h> 98# include <sys/time.h>
98#endif 99#endif
99 100
@@ -2580,6 +2581,26 @@ static const struct luaL_Reg lanes_functions [] = {
2580 {NULL, NULL} 2581 {NULL, NULL}
2581}; 2582};
2582 2583
2584
2585/*
2586 * minimal function registration for keepers, just so that we can populate the transfer databases with them
2587 * without recursively deadlocking ourselves during one-time inits
2588 */
2589void register_core_libfuncs_for_keeper( lua_State* L)
2590{
2591 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lanes.register_core_libfuncs_for_keeper()\n" INDENT_END));
2592 DEBUGSPEW_CODE( ++ debugspew_indent_depth);
2593 STACK_GROW( L, 1);
2594 STACK_CHECK( L);
2595 lua_newtable( L);
2596 luaG_registerlibfuncs( L, lanes_functions);
2597 STACK_MID( L, 1);
2598 populate_func_lookup_table( L, -1, "lanes.core");
2599 lua_pop( L, 1);
2600 STACK_END( L, 0);
2601 DEBUGSPEW_CODE( -- debugspew_indent_depth);
2602}
2603
2583/* 2604/*
2584* One-time initializations 2605* One-time initializations
2585*/ 2606*/
@@ -2645,7 +2666,7 @@ static void init_once_LOCKED( lua_State* L, int const _on_state_create, int cons
2645 { 2666 {
2646 (void) luaL_error( L, "Unable to initialize: %s", err ); 2667 (void) luaL_error( L, "Unable to initialize: %s", err );
2647 } 2668 }
2648 2669
2649 // Initialize 'timer_deep'; a common Linda object shared by all states 2670 // Initialize 'timer_deep'; a common Linda object shared by all states
2650 // 2671 //
2651 ASSERT_L( timer_deep == NULL); 2672 ASSERT_L( timer_deep == NULL);
@@ -2842,43 +2863,54 @@ void EnableCrashingOnCrashes()
2842#endif // PLATFORM_WIN32 2863#endif // PLATFORM_WIN32
2843} 2864}
2844 2865
2845int 2866int LANES_API luaopen_lanes_core( lua_State* L)
2846#if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC)
2847__declspec(dllexport)
2848#endif // (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC)
2849luaopen_lanes_core( lua_State* L)
2850{ 2867{
2851 EnableCrashingOnCrashes(); 2868 EnableCrashingOnCrashes();
2852 2869
2853 STACK_GROW( L, 3); 2870 STACK_GROW( L, 3);
2854 STACK_CHECK( L); 2871 STACK_CHECK( L);
2855 2872
2856 // sanity check: let's see if _"VERSION" matches what we we built against
2857 lua_getglobal( L, "_VERSION");
2858 lua_pushstring( L, LUA_VERSION_NUM == 501 ? "Lua 5.1" : "Lua 5.2");
2859 if( !lua_rawequal( L, -1, -2))
2860 {
2861 return luaL_error( L, "Lanes is built against %s, but you are running %s", lua_tostring( L, -1), lua_tostring( L, -2));
2862 }
2863 lua_pop( L, 2);
2864
2865 // Create main module interface table 2873 // Create main module interface table
2866 // we only have 1 closure, which must be called to configure Lanes 2874 // we only have 1 closure, which must be called to configure Lanes
2867 lua_newtable(L); 2875 lua_newtable(L); // M
2868 lua_pushvalue(L, 1); // module name 2876 lua_pushvalue(L, 1); // M "lanes.core"
2869 lua_pushvalue(L, -2); // module table 2877 lua_pushvalue(L, -2); // M "lanes.core" M
2870 lua_pushcclosure( L, LG_configure, 2); 2878 lua_pushcclosure( L, LG_configure, 2); // M LG_configure()
2871 if( s_initCount == 0) 2879 if( s_initCount == 0)
2872 { 2880 {
2873 lua_setfield( L, -2, "configure"); 2881 lua_setfield( L, -2, "configure"); // M
2874 } 2882 }
2875 else // already initialized: call it immediately and be done 2883 else // already initialized: call it immediately and be done
2876 { 2884 {
2877 lua_pushinteger( L, 666); // any value will do, it will be ignored 2885 // any parameter value will do, they will be ignored
2878 lua_pushnil( L); // almost idem 2886 lua_pushinteger( L, 666); // M LG_configure() 666
2879 lua_call( L, 2, 0); 2887 lua_pushnil( L); // M LG_configure() 666 nil
2888 lua_call( L, 2, 0); // M
2880 } 2889 }
2881 2890
2882 STACK_END( L, 1); 2891 STACK_END( L, 1);
2883 return 1; 2892 return 1;
2884} 2893}
2894
2895static int default_luaopen_lanes( lua_State* L)
2896{
2897 int rc = luaL_loadfile( L, "lanes.lua") || lua_pcall( L, 0, 1, 0);
2898 if( rc != LUA_OK)
2899 {
2900 return luaL_error( L, "failed to initialize embedded Lanes");
2901 }
2902 return 1;
2903}
2904
2905// call this instead of luaopen_lanes_core() when embedding Lua and Lanes in a custom application
2906void LANES_API luaopen_lanes_embedded( lua_State* L, lua_CFunction _luaopen_lanes)
2907{
2908 STACK_CHECK( L);
2909 // pre-require lanes.core so that when lanes.lua calls require "lanes.core" it finds it is already loaded
2910 luaL_requiref( L, "lanes.core", luaopen_lanes_core, 0); // ... lanes.core
2911 lua_pop( L, 1); // ...
2912 STACK_MID( L, 0);
2913 // call user-provided function that runs the chunk "lanes.lua" from wherever they stored it
2914 luaL_requiref( L, "lanes", _luaopen_lanes ? _luaopen_lanes : default_luaopen_lanes, 0); // ... lanes
2915 STACK_END( L, 1);
2916}
diff --git a/src/lanes.h b/src/lanes.h
new file mode 100644
index 0000000..d07750a
--- /dev/null
+++ b/src/lanes.h
@@ -0,0 +1,17 @@
1#if !defined( __lanes_h__)
2#define __lanes_h__ 1
3
4#include "lua.h"
5
6#if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC)
7#define LANES_API __declspec(dllexport)
8#else
9#define LANES_API
10#endif // (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC)
11
12extern int LANES_API luaopen_lanes_core( lua_State* L);
13
14// Call this to work with embedded Lanes instead of calling luaopen_lanes_core()
15extern void LANES_API luaopen_lanes_embedded( lua_State* L, lua_CFunction _luaopen_lanes);
16
17#endif // __lanes_h__ \ No newline at end of file
diff --git a/src/lanes.lua b/src/lanes.lua
index f4eef81..729116e 100644
--- a/src/lanes.lua
+++ b/src/lanes.lua
@@ -52,7 +52,7 @@ lanes.configure = function( _params)
52 end 52 end
53 53
54 -- 54 --
55 -- Cache globals for code that might run under sandboxing 55 -- Cache globals for code that might run under sandboxing
56 -- 56 --
57 local assert = assert 57 local assert = assert
58 local string_gmatch = assert( string.gmatch) 58 local string_gmatch = assert( string.gmatch)
@@ -199,18 +199,20 @@ end
199-- and call the generator later (maybe multiple times, with different parameters) 199-- and call the generator later (maybe multiple times, with different parameters)
200-- or add on actual thread arguments to also ignite the thread on the same call. 200-- or add on actual thread arguments to also ignite the thread on the same call.
201 201
202local valid_libs= { 202local valid_libs=
203 ["package"]= true, 203{
204 ["table"]= true, 204 ["package"] = true,
205 ["io"]= true, 205 ["table"] = true,
206 ["os"]= true, 206 ["io"] = true,
207 ["string"]= true, 207 ["os"] = true,
208 ["math"]= true, 208 ["string"] = true,
209 ["debug"]= true, 209 ["math"] = true,
210 ["bit32"]= true, -- Lua 5.2 only, ignored silently under 5.1 210 ["debug"] = true,
211 -- 211 ["bit32"] = true, -- Lua 5.2 only, ignored silently under 5.1
212 ["base"]= true, 212 --
213 ["coroutine"]= true 213 ["base"] = true,
214 ["coroutine"] = true, -- part of "base" in Lua 5.1
215 ["lanes.core"] = true
214} 216}
215 217
216-- PUBLIC LANES API 218-- PUBLIC LANES API
@@ -253,7 +255,7 @@ local function gen( ... )
253 if libs and libs ~= "*" then 255 if libs and libs ~= "*" then
254 local found = {} 256 local found = {}
255 -- check that the caller only provides reserved library names 257 -- check that the caller only provides reserved library names
256 for s in string_gmatch(libs, "[%a%d]+") do 258 for s in string_gmatch(libs, "[%a%d.]+") do
257 if not valid_libs[s] then 259 if not valid_libs[s] then
258 error( "Bad library name: " .. s) 260 error( "Bad library name: " .. s)
259 else 261 else
diff --git a/src/threading.c b/src/threading.c
index d19fe1a..754b6d1 100644
--- a/src/threading.c
+++ b/src/threading.c
@@ -42,7 +42,7 @@ THE SOFTWARE.
42#include "threading.h" 42#include "threading.h"
43#include "lua.h" 43#include "lua.h"
44 44
45#if !defined( PLATFORM_WIN32) && !defined( PLATFORM_POCKETPC) 45#if !defined( PLATFORM_XBOX) && !defined( PLATFORM_WIN32) && !defined( PLATFORM_POCKETPC)
46# include <sys/time.h> 46# include <sys/time.h>
47#endif // non-WIN32 timing 47#endif // non-WIN32 timing
48 48
@@ -83,7 +83,7 @@ THE SOFTWARE.
83* FAIL is for unexpected API return values - essentially programming 83* FAIL is for unexpected API return values - essentially programming
84* error in _this_ code. 84* error in _this_ code.
85*/ 85*/
86#if defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC) 86#if defined( PLATFORM_XBOX) || defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC)
87static void FAIL( const char *funcname, int rc ) { 87static void FAIL( const char *funcname, int rc ) {
88 fprintf( stderr, "%s() failed! (%d)\n", funcname, rc ); 88 fprintf( stderr, "%s() failed! (%d)\n", funcname, rc );
89#ifdef _MSC_VER 89#ifdef _MSC_VER
@@ -102,7 +102,7 @@ static void FAIL( const char *funcname, int rc ) {
102*/ 102*/
103time_d now_secs(void) { 103time_d now_secs(void) {
104 104
105#if defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC) 105#if defined( PLATFORM_XBOX) || defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC)
106 /* 106 /*
107 * Windows FILETIME values are "100-nanosecond intervals since 107 * Windows FILETIME values are "100-nanosecond intervals since
108 * January 1, 1601 (UTC)" (MSDN). Well, we'd want Unix Epoch as 108 * January 1, 1601 (UTC)" (MSDN). Well, we'd want Unix Epoch as
@@ -226,7 +226,7 @@ static void prepare_timeout( struct timespec *ts, time_d abs_secs ) {
226// valid values N * 4KB 226// valid values N * 4KB
227// 227//
228#ifndef _THREAD_STACK_SIZE 228#ifndef _THREAD_STACK_SIZE
229# if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) || (defined PLATFORM_CYGWIN) 229# if defined( PLATFORM_XBOX) || defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC) || defined( PLATFORM_CYGWIN)
230# define _THREAD_STACK_SIZE 0 230# define _THREAD_STACK_SIZE 0
231 // Win32: does it work with less? 231 // Win32: does it work with less?
232# elif (defined PLATFORM_OSX) 232# elif (defined PLATFORM_OSX)
@@ -311,10 +311,15 @@ bool_t THREAD_WAIT_IMPL( THREAD_T *ref, double secs)
311 return TRUE; 311 return TRUE;
312 } 312 }
313 // 313 //
314 void THREAD_KILL( THREAD_T *ref ) { 314 void THREAD_KILL( THREAD_T *ref )
315 if (!TerminateThread( *ref, 0 )) FAIL("TerminateThread", GetLastError()); 315 {
316 *ref= NULL; 316 // nonexistent on Xbox360, simply disable until a better solution is found
317 } 317 #if !defined( PLATFORM_XBOX)
318 // in theory no-one should call this as it is very dangerous (memory and mutex leaks, no notification of DLLs, etc.)
319 if (!TerminateThread( *ref, 0 )) FAIL("TerminateThread", GetLastError());
320 #endif // PLATFORM_XBOX
321 *ref= NULL;
322 }
318 323
319#if !defined __GNUC__ 324#if !defined __GNUC__
320 //see http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx 325 //see http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
diff --git a/src/threading.h b/src/threading.h
index 1d304fa..1b218b9 100644
--- a/src/threading.h
+++ b/src/threading.h
@@ -11,6 +11,8 @@
11 */ 11 */
12#ifdef _WIN32_WCE 12#ifdef _WIN32_WCE
13 #define PLATFORM_POCKETPC 13 #define PLATFORM_POCKETPC
14#elif defined(_XBOX)
15 #define PLATFORM_XBOX
14#elif (defined _WIN32) 16#elif (defined _WIN32)
15 #define PLATFORM_WIN32 17 #define PLATFORM_WIN32
16#elif (defined __linux__) 18#elif (defined __linux__)
@@ -47,7 +49,7 @@ enum e_status { PENDING, RUNNING, WAITING, DONE, ERROR_ST, CANCELLED };
47#define THREADAPI_WINDOWS 1 49#define THREADAPI_WINDOWS 1
48#define THREADAPI_PTHREAD 2 50#define THREADAPI_PTHREAD 2
49 51
50#if( defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC)) && !defined( HAVE_WIN32_PTHREAD) 52#if( defined( PLATFORM_XBOX) || defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC)) && !defined( HAVE_WIN32_PTHREAD)
51#define THREADAPI THREADAPI_WINDOWS 53#define THREADAPI THREADAPI_WINDOWS
52#else // (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) 54#else // (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC)
53#define THREADAPI THREADAPI_PTHREAD 55#define THREADAPI THREADAPI_PTHREAD
@@ -57,10 +59,14 @@ enum e_status { PENDING, RUNNING, WAITING, DONE, ERROR_ST, CANCELLED };
57*/ 59*/
58 60
59#if THREADAPI == THREADAPI_WINDOWS 61#if THREADAPI == THREADAPI_WINDOWS
60 #define WIN32_LEAN_AND_MEAN 62 #if defined ( PLATFORM_XBOX)
61 // 'SignalObjectAndWait' needs this (targets Windows 2000 and above) 63 #include <xtl.h>
62 #define _WIN32_WINNT 0x0400 64 #else // !PLATFORM_XBOX
63 #include <windows.h> 65 #define WIN32_LEAN_AND_MEAN
66 // 'SignalObjectAndWait' needs this (targets Windows 2000 and above)
67 #define _WIN32_WINNT 0x0400
68 #include <windows.h>
69 #endif // !PLATFORM_XBOX
64 #include <process.h> 70 #include <process.h>
65 71
66 // MSDN: http://msdn2.microsoft.com/en-us/library/ms684254.aspx 72 // MSDN: http://msdn2.microsoft.com/en-us/library/ms684254.aspx
@@ -119,7 +125,7 @@ enum e_status { PENDING, RUNNING, WAITING, DONE, ERROR_ST, CANCELLED };
119 // 125 //
120 #if defined( PLATFORM_OSX) 126 #if defined( PLATFORM_OSX)
121 #define YIELD() pthread_yield_np() 127 #define YIELD() pthread_yield_np()
122 #elif defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC) 128 #elif defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC) // no PTHREAD for PLATFORM_XBOX
123 // for some reason win32-pthread doesn't have pthread_yield(), but sched_yield() 129 // for some reason win32-pthread doesn't have pthread_yield(), but sched_yield()
124 #define YIELD() sched_yield() 130 #define YIELD() sched_yield()
125 #else 131 #else
diff --git a/src/tools.c b/src/tools.c
index 13a3ebd..f72663f 100644
--- a/src/tools.c
+++ b/src/tools.c
@@ -33,6 +33,7 @@ THE SOFTWARE.
33 33
34#include "tools.h" 34#include "tools.h"
35#include "keeper.h" 35#include "keeper.h"
36#include "lanes.h"
36 37
37#include "lualib.h" 38#include "lualib.h"
38#include "lauxlib.h" 39#include "lauxlib.h"
@@ -42,6 +43,43 @@ THE SOFTWARE.
42#include <ctype.h> 43#include <ctype.h>
43#include <stdlib.h> 44#include <stdlib.h>
44 45
46/*
47** Copied from Lua 5.2 loadlib.c
48*/
49#if LUA_VERSION_NUM == 501
50static int luaL_getsubtable (lua_State *L, int idx, const char *fname)
51{
52 lua_getfield(L, idx, fname);
53 if (lua_istable(L, -1))
54 return 1; /* table already there */
55 else
56 {
57 lua_pop(L, 1); /* remove previous result */
58 idx = lua_absindex(L, idx);
59 lua_newtable(L);
60 lua_pushvalue(L, -1); /* copy to be left at top */
61 lua_setfield(L, idx, fname); /* assign new table to field */
62 return 0; /* false, because did not find table there */
63 }
64}
65
66void luaL_requiref (lua_State *L, const char *modname, lua_CFunction openf, int glb)
67{
68 lua_pushcfunction(L, openf);
69 lua_pushstring(L, modname); /* argument to open function */
70 lua_call(L, 1, 1); /* open module */
71 luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED");
72 lua_pushvalue(L, -2); /* make copy of module (call result) */
73 lua_setfield(L, -2, modname); /* _LOADED[modname] = module */
74 lua_pop(L, 1); /* remove _LOADED table */
75 if (glb)
76 {
77 lua_pushvalue(L, -1); /* copy of 'mod' */
78 lua_setglobal(L, modname); /* _G[modname] = module */
79 }
80}
81#endif // LUA_VERSION_NUM
82
45DEBUGSPEW_CODE( char const* debugspew_indent = "----+----!----+----!----+----!----+----!----+----!----+----!----+----!----+"); 83DEBUGSPEW_CODE( char const* debugspew_indent = "----+----!----+----!----+----!----+----!----+----!----+----!----+----!----+");
46DEBUGSPEW_CODE( int debugspew_indent_depth = 0); 84DEBUGSPEW_CODE( int debugspew_indent_depth = 0);
47 85
@@ -98,14 +136,24 @@ void luaG_dump( lua_State* L ) {
98 136
99/*---=== luaG_newstate ===---*/ 137/*---=== luaG_newstate ===---*/
100 138
139static int require_lanes_core( lua_State* L)
140{
141 // leaves a copy of 'lanes.core' module table on the stack
142 luaL_requiref( L, "lanes.core", luaopen_lanes_core, 0);
143 return 1;
144}
145
146
101static const luaL_Reg libs[] = 147static const luaL_Reg libs[] =
102{ 148{
103 { LUA_LOADLIBNAME, luaopen_package}, 149 { LUA_LOADLIBNAME, luaopen_package},
104 { LUA_TABLIBNAME, luaopen_table}, 150 { LUA_TABLIBNAME, luaopen_table},
105 { LUA_STRLIBNAME, luaopen_string}, 151 { LUA_STRLIBNAME, luaopen_string},
106 { LUA_MATHLIBNAME, luaopen_math}, 152 { LUA_MATHLIBNAME, luaopen_math},
153#ifndef PLATFORM_XBOX // no os/io libs on xbox
107 { LUA_OSLIBNAME, luaopen_os}, 154 { LUA_OSLIBNAME, luaopen_os},
108 { LUA_IOLIBNAME, luaopen_io}, 155 { LUA_IOLIBNAME, luaopen_io},
156#endif // PLATFORM_XBOX
109#if LUA_VERSION_NUM >= 502 157#if LUA_VERSION_NUM >= 502
110 { LUA_BITLIBNAME, luaopen_bit32}, 158 { LUA_BITLIBNAME, luaopen_bit32},
111 { LUA_COLIBNAME, luaopen_coroutine}, // Lua 5.2: coroutine is no longer a part of base! 159 { LUA_COLIBNAME, luaopen_coroutine}, // Lua 5.2: coroutine is no longer a part of base!
@@ -113,6 +161,7 @@ static const luaL_Reg libs[] =
113 { LUA_COLIBNAME, NULL}, // Lua 5.1: part of base package 161 { LUA_COLIBNAME, NULL}, // Lua 5.1: part of base package
114#endif // LUA_VERSION_NUM 162#endif // LUA_VERSION_NUM
115 { LUA_DBLIBNAME, luaopen_debug}, 163 { LUA_DBLIBNAME, luaopen_debug},
164 { "lanes.core", require_lanes_core}, // So that we can open it like any base library (possible since we have access to the init function)
116 // 165 //
117 { "base", NULL}, // ignore "base" (already acquired it) 166 { "base", NULL}, // ignore "base" (already acquired it)
118 { NULL, NULL } 167 { NULL, NULL }
@@ -135,9 +184,11 @@ static void open1lib( lua_State* L, char const* name, size_t len)
135 lua_pop( L, 1); 184 lua_pop( L, 1);
136#else // LUA_VERSION_NUM 185#else // LUA_VERSION_NUM
137 STACK_GROW( L, 1); 186 STACK_GROW( L, 1);
187 // push function and 1 argument on the stack
138 lua_pushcfunction( L, libs[i].func); 188 lua_pushcfunction( L, libs[i].func);
139 // pushes the module table on the stack 189 lua_pushstring( L, libs[i].name);
140 lua_call( L, 0, 0); 190 // call function, pushes the module table on the stack
191 lua_call( L, 1, 0);
141#endif // LUA_VERSION_NUM 192#endif // LUA_VERSION_NUM
142 STACK_END( L, 0); 193 STACK_END( L, 0);
143 } 194 }
@@ -443,6 +494,7 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* _name)
443* Base ("unpack", "print" etc.) is always added, unless 'libs' is NULL. 494* Base ("unpack", "print" etc.) is always added, unless 'libs' is NULL.
444* 495*
445*/ 496*/
497extern void register_core_libfuncs_for_keeper( lua_State* L);
446 498
447lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char const* libs) 499lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char const* libs)
448{ 500{
@@ -475,10 +527,24 @@ lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char con
475 // 527 //
476 if( libs) 528 if( libs)
477 { 529 {
478 if( libs[0] == '*' && libs[1] == 0) // special "*" case (mainly to help with LuaJIT compatibility) 530 // special "*" case (mainly to help with LuaJIT compatibility)
531 // "K" is used when opening keeper states: almost the same as "*", but for the fact we don't open lanes.core
532 // as we are called from luaopen_lanes_core() already, and that would deadlock
533 if( (libs[0] == '*' || libs[0] == 'K') && libs[1] == 0)
479 { 534 {
480 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening ALL standard libraries\n" INDENT_END)); 535 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening ALL standard libraries\n" INDENT_END));
481 luaL_openlibs( L); 536 luaL_openlibs( L);
537 if( libs[0] == '*')
538 {
539 // don't forget lanes.core for regular lane states
540 open1lib( L, "lanes.core", 10);
541 }
542 else
543 {
544 // In keeper states however, we only want to register the lanes.core functions to be able to transfer them through lindas
545 // (we don't care about a full lanes.core init in the keeper states as we won't call anything in there)
546 register_core_libfuncs_for_keeper( L);
547 }
482 libs = NULL; // done with libs 548 libs = NULL; // done with libs
483 } 549 }
484 else 550 else
@@ -504,12 +570,12 @@ lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char con
504 unsigned int len = 0; 570 unsigned int len = 0;
505 for( p = libs; *p; p += len) 571 for( p = libs; *p; p += len)
506 { 572 {
507 len = 0; 573 // skip delimiters ('.' can be part of name for "lanes.core")
508 // skip delimiters 574 while( *p && !isalnum( *p) && *p != '.')
509 while( *p && !isalnum( *p))
510 ++ p; 575 ++ p;
511 // skip name 576 // skip name
512 while( isalnum( p[len])) 577 len = 0;
578 while( isalnum( p[len]) || p[len] == '.')
513 ++ len; 579 ++ len;
514 // open library 580 // open library
515 open1lib( L, p, len); 581 open1lib( L, p, len);
diff --git a/src/tools.h b/src/tools.h
index a06e23f..10711d4 100644
--- a/src/tools.h
+++ b/src/tools.h
@@ -27,6 +27,7 @@
27#define luaG_registerlibfuncs( L, _funcs) luaL_register( L, NULL, _funcs) 27#define luaG_registerlibfuncs( L, _funcs) luaL_register( L, NULL, _funcs)
28#define LUA_OK 0 28#define LUA_OK 0
29#define LUA_ERRGCMM 666 // doesn't exist in Lua 5.1, we don't care about the actual value 29#define LUA_ERRGCMM 666 // doesn't exist in Lua 5.1, we don't care about the actual value
30void luaL_requiref (lua_State* L, const char* modname, lua_CFunction openf, int glb); // implementation copied from Lua 5.2 sources
30#endif // LUA_VERSION_NUM == 501 31#endif // LUA_VERSION_NUM == 501
31 32
32// wrap Lua 5.2 calls under Lua 5.1 API when it is simpler that way 33// wrap Lua 5.2 calls under Lua 5.1 API when it is simpler that way