diff options
| author | Benoit Germain <bnt.germain@gmail.com> | 2013-02-13 20:30:04 +0100 |
|---|---|---|
| committer | Benoit Germain <bnt.germain@gmail.com> | 2013-02-13 20:30:26 +0100 |
| commit | 577bca074df12c520f49e9361381f0cad78200c1 (patch) | |
| tree | 188a4d1e3366a9351ea5b9689efbaf3f98996100 /src | |
| parent | 131c11c2ae327de5b4db743a6a81eb9b57470d0e (diff) | |
| download | lanes-577bca074df12c520f49e9361381f0cad78200c1.tar.gz lanes-577bca074df12c520f49e9361381f0cad78200c1.tar.bz2 lanes-577bca074df12c520f49e9361381f0cad78200c1.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 'src')
| -rw-r--r-- | src/keeper.c | 2 | ||||
| -rw-r--r-- | src/lanes.c | 82 | ||||
| -rw-r--r-- | src/lanes.h | 17 | ||||
| -rw-r--r-- | src/lanes.lua | 30 | ||||
| -rw-r--r-- | src/threading.c | 21 | ||||
| -rw-r--r-- | src/threading.h | 18 | ||||
| -rw-r--r-- | src/tools.c | 80 | ||||
| -rw-r--r-- | src/tools.h | 1 |
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 | ||
| 55 | char const* VERSION = "3.5.0"; | 55 | char 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 | */ | ||
| 2589 | void 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 | ||
| 2845 | int | 2866 | int 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) | ||
| 2849 | luaopen_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 | |||
| 2895 | static 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 | ||
| 2906 | void 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 | |||
| 12 | extern int LANES_API luaopen_lanes_core( lua_State* L); | ||
| 13 | |||
| 14 | // Call this to work with embedded Lanes instead of calling luaopen_lanes_core() | ||
| 15 | extern 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 | ||
| 202 | local valid_libs= { | 202 | local 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) |
| 87 | static void FAIL( const char *funcname, int rc ) { | 87 | static 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 | */ |
| 103 | time_d now_secs(void) { | 103 | time_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 | ||
| 50 | static 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 | |||
| 66 | void 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 | |||
| 45 | DEBUGSPEW_CODE( char const* debugspew_indent = "----+----!----+----!----+----!----+----!----+----!----+----!----+----!----+"); | 83 | DEBUGSPEW_CODE( char const* debugspew_indent = "----+----!----+----!----+----!----+----!----+----!----+----!----+----!----+"); |
| 46 | DEBUGSPEW_CODE( int debugspew_indent_depth = 0); | 84 | DEBUGSPEW_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 | ||
| 139 | static 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 | |||
| 101 | static const luaL_Reg libs[] = | 147 | static 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 | */ |
| 497 | extern void register_core_libfuncs_for_keeper( lua_State* L); | ||
| 446 | 498 | ||
| 447 | lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char const* libs) | 499 | lua_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 |
| 30 | void 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 |
