diff options
Diffstat (limited to 'src/tools.c')
-rw-r--r-- | src/tools.c | 172 |
1 files changed, 94 insertions, 78 deletions
diff --git a/src/tools.c b/src/tools.c index fe1728d..ade8cb8 100644 --- a/src/tools.c +++ b/src/tools.c | |||
@@ -100,17 +100,19 @@ static const luaL_Reg libs[] = | |||
100 | { | 100 | { |
101 | { LUA_LOADLIBNAME, luaopen_package}, | 101 | { LUA_LOADLIBNAME, luaopen_package}, |
102 | { LUA_TABLIBNAME, luaopen_table}, | 102 | { LUA_TABLIBNAME, luaopen_table}, |
103 | { LUA_IOLIBNAME, luaopen_io}, | ||
104 | { LUA_OSLIBNAME, luaopen_os}, | ||
105 | { LUA_STRLIBNAME, luaopen_string}, | 103 | { LUA_STRLIBNAME, luaopen_string}, |
106 | { LUA_MATHLIBNAME, luaopen_math}, | 104 | { LUA_MATHLIBNAME, luaopen_math}, |
105 | { LUA_OSLIBNAME, luaopen_os}, | ||
106 | { LUA_IOLIBNAME, luaopen_io}, | ||
107 | #if LUA_VERSION_NUM >= 502 | 107 | #if LUA_VERSION_NUM >= 502 |
108 | { LUA_BITLIBNAME, luaopen_bit32}, | 108 | { LUA_BITLIBNAME, luaopen_bit32}, |
109 | { LUA_COLIBNAME, luaopen_coroutine}, // Lua 5.2: coroutine is no longer a part of base! | ||
110 | #else // LUA_VERSION_NUM | ||
111 | { LUA_COLIBNAME, NULL}, // Lua 5.1: part of base package | ||
109 | #endif // LUA_VERSION_NUM | 112 | #endif // LUA_VERSION_NUM |
110 | { LUA_DBLIBNAME, luaopen_debug}, | 113 | { LUA_DBLIBNAME, luaopen_debug}, |
111 | // | 114 | // |
112 | { "base", NULL }, // ignore "base" (already acquired it) | 115 | { "base", NULL}, // ignore "base" (already acquired it) |
113 | { LUA_COLIBNAME, NULL }, // part of Lua 5.[1|2] base package | ||
114 | { NULL, NULL } | 116 | { NULL, NULL } |
115 | }; | 117 | }; |
116 | 118 | ||
@@ -124,18 +126,16 @@ static void open1lib( lua_State* L, char const* name, size_t len) | |||
124 | if( libs[i].func) | 126 | if( libs[i].func) |
125 | { | 127 | { |
126 | DEBUGSPEW_CODE( fprintf( stderr, "opening %.*s library\n", len, name)); | 128 | DEBUGSPEW_CODE( fprintf( stderr, "opening %.*s library\n", len, name)); |
127 | STACK_GROW( L, 1); | ||
128 | STACK_CHECK( L) | 129 | STACK_CHECK( L) |
129 | lua_pushcfunction( L, libs[i].func); | ||
130 | // pushes the module table on the stack | ||
131 | lua_call( L, 0, 1); | ||
132 | populate_func_lookup_table( L, -1, libs[i].name); | ||
133 | #if LUA_VERSION_NUM >= 502 | 130 | #if LUA_VERSION_NUM >= 502 |
134 | // Lua 5.2: luaopen_x doesn't create the global, we have to do it ourselves! | 131 | // open the library as if through require(), and create a global as well (the library table is left on the stack) |
135 | lua_setglobal( L, libs[i].name); | 132 | luaL_requiref( L, libs[i].name, libs[i].func, 1); |
136 | #else // LUA_VERSION_NUM | ||
137 | // Lua 5.1: remove the module when we are done | ||
138 | lua_pop( L, 1); | 133 | lua_pop( L, 1); |
134 | #else // LUA_VERSION_NUM | ||
135 | STACK_GROW( L, 1); | ||
136 | lua_pushcfunction( L, libs[i].func); | ||
137 | // pushes the module table on the stack | ||
138 | lua_call( L, 0, 0); | ||
139 | #endif // LUA_VERSION_NUM | 139 | #endif // LUA_VERSION_NUM |
140 | STACK_END( L, 0) | 140 | STACK_END( L, 0) |
141 | } | 141 | } |
@@ -427,75 +427,93 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* _name) | |||
427 | * | 427 | * |
428 | * Base ("unpack", "print" etc.) is always added, unless 'libs' is NULL. | 428 | * Base ("unpack", "print" etc.) is always added, unless 'libs' is NULL. |
429 | * | 429 | * |
430 | * Returns NULL for ok, position of error within 'libs' on failure. | ||
431 | */ | 430 | */ |
432 | #define is_name_char(c) (isalpha(c) || (c)=='*') | ||
433 | 431 | ||
434 | lua_State* luaG_newstate( char const* libs, lua_CFunction _on_state_create) | 432 | lua_State* luaG_newstate( lua_State* _from, char const* libs, lua_CFunction _on_state_create) |
435 | { | 433 | { |
436 | lua_State* const L = luaL_newstate(); | 434 | // reuse alloc function from the originating state |
435 | void* allocUD; | ||
436 | lua_Alloc allocF = lua_getallocf( _from, &allocUD); | ||
437 | lua_State* L = lua_newstate( allocF, allocUD); | ||
437 | 438 | ||
438 | // no libs, or special init func (not even 'base') | 439 | if( !L) |
439 | if (libs || _on_state_create) | ||
440 | { | 440 | { |
441 | // 'lua.c' stops GC during initialization so perhaps its a good idea. :) | 441 | luaL_error( _from, "'lua_newstate()' failed; out of memory"); |
442 | // | 442 | } |
443 | lua_gc( L, LUA_GCSTOP, 0); | ||
444 | 443 | ||
445 | // Anything causes 'base' to be taken in | 444 | // neither libs (not even 'base') nor special init func: we are done |
446 | // | 445 | if( !libs && !_on_state_create) |
447 | STACK_GROW( L, 2); | 446 | { |
448 | STACK_CHECK( L) | 447 | return L; |
449 | if( _on_state_create) | 448 | } |
449 | |||
450 | STACK_GROW( L, 2); | ||
451 | STACK_CHECK( L) | ||
452 | if( _on_state_create) | ||
453 | { | ||
454 | DEBUGSPEW_CODE( fprintf( stderr, "calling on_state_create()\n")); | ||
455 | lua_pushcfunction( L, _on_state_create); | ||
456 | lua_call( L, 0, 0); | ||
457 | } | ||
458 | |||
459 | // 'lua.c' stops GC during initialization so perhaps its a good idea. :) | ||
460 | // but do it after _on_state_create in case it does a lot of stuff... | ||
461 | lua_gc( L, LUA_GCSTOP, 0); | ||
462 | |||
463 | // Anything causes 'base' to be taken in | ||
464 | // | ||
465 | if( libs) | ||
466 | { | ||
467 | if( libs[0] == '*' && libs[1] == 0) // special "*" case (mainly to help with LuaJIT compatibility) | ||
450 | { | 468 | { |
451 | lua_pushcfunction( L, _on_state_create); | 469 | DEBUGSPEW_CODE( fprintf( stderr, "opening ALL standard libraries\n")); |
452 | lua_call( L, 0, 0); | 470 | luaL_openlibs( L); |
471 | libs = NULL; // done with libs | ||
453 | } | 472 | } |
454 | if( libs) | 473 | else |
455 | { | 474 | { |
456 | if( libs[0] == '*' && libs[1] == 0) // special "*" case (mainly to help with LuaJIT compatibility) | 475 | DEBUGSPEW_CODE( fprintf( stderr, "opening base library\n")); |
457 | { | 476 | #if LUA_VERSION_NUM >= 502 |
458 | DEBUGSPEW_CODE( fprintf( stderr, "opening ALL base libraries\n")); | 477 | // open base library the same way as in luaL_openlibs() |
459 | luaL_openlibs( L); | 478 | luaL_requiref( L, "_G", luaopen_base, 1); |
460 | libs = NULL; // done with libs | 479 | lua_pop( L, 1); |
461 | } | 480 | #else // LUA_VERSION_NUM |
462 | else | 481 | lua_pushcfunction( L, luaopen_base); |
463 | { | 482 | lua_pushstring( L, ""); |
464 | DEBUGSPEW_CODE( fprintf( stderr, "opening base library\n")); | 483 | lua_call( L, 1, 0); |
465 | lua_pushcfunction( L, luaopen_base); | 484 | #endif // LUA_VERSION_NUM |
466 | lua_call( L, 0, 0); | ||
467 | } | ||
468 | } | 485 | } |
486 | } | ||
487 | STACK_END( L, 0) | ||
469 | 488 | ||
470 | // after opening base, register the functions it exported in our name<->function database | 489 | // scan all libraries, open them one by one |
471 | lua_pushglobaltable( L); // Lua 5.2 no longer has LUA_GLOBALSINDEX: we must push globals table on the stack | 490 | if( libs) |
472 | populate_func_lookup_table( L, -1, NULL); | 491 | { |
473 | lua_pop( L, 1); | 492 | char const* p; |
474 | 493 | unsigned int len = 0; | |
475 | STACK_MID( L, 0); | 494 | for( p = libs; *p; p += len) |
476 | { | 495 | { |
477 | char const* p; | 496 | len = 0; |
478 | unsigned int len = 0; | 497 | // skip delimiters |
479 | if( libs) | 498 | while( *p && !isalnum( *p)) |
480 | { | 499 | ++ p; |
481 | for( p = libs; *p; p += len) | 500 | // skip name |
482 | { | 501 | while( isalnum( p[len])) |
483 | len = 0; | 502 | ++ len; |
484 | // skip delimiters | 503 | // open library |
485 | while( *p && !is_name_char( *p)) | 504 | open1lib( L, p, len); |
486 | ++ p; | ||
487 | // skip name | ||
488 | while( is_name_char( p[len])) | ||
489 | ++ len; | ||
490 | // open library | ||
491 | open1lib( L, p, len); | ||
492 | } | ||
493 | serialize_require( L); | ||
494 | } | ||
495 | } | 505 | } |
496 | STACK_END(L,0) | 506 | serialize_require( L); |
497 | lua_gc( L, LUA_GCRESTART, 0); | ||
498 | } | 507 | } |
508 | |||
509 | lua_gc( L, LUA_GCRESTART, 0); | ||
510 | |||
511 | STACK_CHECK( L) | ||
512 | // 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 | ||
514 | populate_func_lookup_table( L, -1, NULL); | ||
515 | lua_pop( L, 1); | ||
516 | STACK_END( L, 0) | ||
499 | return L; | 517 | return L; |
500 | } | 518 | } |
501 | 519 | ||
@@ -1895,25 +1913,23 @@ static int new_require( lua_State *L) | |||
1895 | */ | 1913 | */ |
1896 | void serialize_require( lua_State *L ) | 1914 | void serialize_require( lua_State *L ) |
1897 | { | 1915 | { |
1898 | STACK_GROW(L,1); | 1916 | STACK_GROW( L, 1); |
1899 | STACK_CHECK(L) | 1917 | STACK_CHECK( L) |
1900 | 1918 | ||
1901 | // Check 'require' is there; if not, do nothing | 1919 | // Check 'require' is there; if not, do nothing |
1902 | // | 1920 | // |
1903 | lua_getglobal( L, "require" ); | 1921 | lua_getglobal( L, "require"); |
1904 | if (lua_isfunction( L, -1 )) | 1922 | if( lua_isfunction( L, -1)) |
1905 | { | 1923 | { |
1906 | // [-1]: original 'require' function | 1924 | // [-1]: original 'require' function |
1907 | 1925 | lua_pushcclosure( L, new_require, 1 /*upvalues*/); | |
1908 | lua_pushcclosure( L, new_require, 1 /*upvalues*/ ); | 1926 | lua_setglobal( L, "require"); |
1909 | lua_setglobal( L, "require" ); | ||
1910 | |||
1911 | } | 1927 | } |
1912 | else | 1928 | else |
1913 | { | 1929 | { |
1914 | // [-1]: nil | 1930 | // [-1]: nil |
1915 | lua_pop(L,1); | 1931 | lua_pop( L, 1); |
1916 | } | 1932 | } |
1917 | 1933 | ||
1918 | STACK_END(L,0) | 1934 | STACK_END( L, 0) |
1919 | } | 1935 | } |