diff --git a/linit.c b/linit.c index 69808f84..675fb65f 100644 --- a/linit.c +++ b/linit.c @@ -8,21 +8,6 @@ #define linit_c #define LUA_LIB -/* -** If you embed Lua in your program and need to open the standard -** libraries, call luaL_openlibs in your program. If you need a -** different set of libraries, copy this file to your project and edit -** it to suit your needs. -** -** You can also *preload* libraries, so that a later 'require' can -** open the library, which is already linked to the application. -** For that, do the following code: -** -** luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); -** lua_pushcfunction(L, luaopen_modname); -** lua_setfield(L, -2, modname); -** lua_pop(L, 1); // remove PRELOAD table -*/ #include "lprefix.h" @@ -36,30 +21,44 @@ /* -** these libs are loaded by lua.c and are readily available to any Lua -** program +** Standard Libraries */ -static const luaL_Reg loadedlibs[] = { +static const luaL_Reg stdlibs[] = { {LUA_GNAME, luaopen_base}, {LUA_LOADLIBNAME, luaopen_package}, + {LUA_COLIBNAME, luaopen_coroutine}, - {LUA_TABLIBNAME, luaopen_table}, + {LUA_DBLIBNAME, luaopen_debug}, {LUA_IOLIBNAME, luaopen_io}, + {LUA_MATHLIBNAME, luaopen_math}, {LUA_OSLIBNAME, luaopen_os}, {LUA_STRLIBNAME, luaopen_string}, - {LUA_MATHLIBNAME, luaopen_math}, + {LUA_TABLIBNAME, luaopen_table}, {LUA_UTF8LIBNAME, luaopen_utf8}, - {LUA_DBLIBNAME, luaopen_debug}, + {NULL, NULL} }; -LUALIB_API void luaL_openlibs (lua_State *L) { +/* +** require selected standard libraries and add the others to the +** preload table. +*/ +LUALIB_API void luaL_openselectedlibs (lua_State *L, int what) { + int mask = 1; const luaL_Reg *lib; - /* "require" functions from 'loadedlibs' and set results to global table */ - for (lib = loadedlibs; lib->func; lib++) { - luaL_requiref(L, lib->name, lib->func, 1); - lua_pop(L, 1); /* remove lib */ + luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); + for (lib = stdlibs; lib->func; (lib++, mask <<= 1)) { + if (what & mask) { /* selected? */ + luaL_requiref(L, lib->name, lib->func, 1); /* require library */ + lua_pop(L, 1); /* remove result from the stack */ + } + else { /* add library to PRELOAD table */ + lua_pushcfunction(L, lib->func); + lua_setfield(L, -2, lib->name); + } } + lua_assert((mask >> 1) == LUA_UTF8LIBK); + lua_pop(L, 1); // remove PRELOAD table } diff --git a/ltests.c b/ltests.c index 3f67c23a..d5d2ae68 100644 --- a/ltests.c +++ b/ltests.c @@ -1178,31 +1178,15 @@ static lua_State *getstate (lua_State *L) { static int loadlib (lua_State *L) { - static const luaL_Reg libs[] = { - {LUA_GNAME, luaopen_base}, - {"coroutine", luaopen_coroutine}, - {"debug", luaopen_debug}, - {"io", luaopen_io}, - {"os", luaopen_os}, - {"math", luaopen_math}, - {"string", luaopen_string}, - {"table", luaopen_table}, - {"T", luaB_opentests}, - {NULL, NULL} - }; lua_State *L1 = getstate(L); - int i; - luaL_requiref(L1, "package", luaopen_package, 0); + int what = luaL_checkinteger(L, 2); + luaL_openselectedlibs(L1, what); + luaL_requiref(L1, "T", luaB_opentests, 0); lua_assert(lua_type(L1, -1) == LUA_TTABLE); /* 'requiref' should not reload module already loaded... */ - luaL_requiref(L1, "package", NULL, 1); /* seg. fault if it reloads */ + luaL_requiref(L1, "T", NULL, 1); /* seg. fault if it reloads */ /* ...but should return the same module */ lua_assert(lua_compare(L1, -1, -2, LUA_OPEQ)); - luaL_getsubtable(L1, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); - for (i = 0; libs[i].name; i++) { - lua_pushcfunction(L1, libs[i].func); - lua_setfield(L1, -2, libs[i].name); - } return 0; } diff --git a/ltests.h b/ltests.h index ec520498..45d5beba 100644 --- a/ltests.h +++ b/ltests.h @@ -103,8 +103,8 @@ LUA_API void *debug_realloc (void *ud, void *block, #if defined(lua_c) #define luaL_newstate() lua_newstate(debug_realloc, &l_memcontrol) -#define luaL_openlibs(L) \ - { (luaL_openlibs)(L); \ +#define luai_openlibs(L) \ + { luaL_openlibs(L); \ luaL_requiref(L, "T", luaB_opentests, 1); \ lua_pop(L, 1); } #endif diff --git a/lua.c b/lua.c index 715430a0..af20754e 100644 --- a/lua.c +++ b/lua.c @@ -609,6 +609,10 @@ static void doREPL (lua_State *L) { /* }================================================================== */ +#if !defined(luai_openlibs) +#define luai_openlibs(L) luaL_openlibs(L) +#endif + /* ** Main body of stand-alone interpreter (to be called in protected mode). @@ -631,7 +635,7 @@ static int pmain (lua_State *L) { lua_pushboolean(L, 1); /* signal for libraries to ignore env. vars. */ lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); } - luaL_openlibs(L); /* open standard libraries */ + luai_openlibs(L); /* open standard libraries */ createargtable(L, argv, argc, script); /* create table 'arg' */ lua_gc(L, LUA_GCRESTART); /* start GC... */ lua_gc(L, LUA_GCGEN, 0, 0); /* ...in generational mode */ diff --git a/lualib.h b/lualib.h index 26255290..e124cf1b 100644 --- a/lualib.h +++ b/lualib.h @@ -14,39 +14,52 @@ /* version suffix for environment variable names */ #define LUA_VERSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR - +#define LUA_GK 1 LUAMOD_API int (luaopen_base) (lua_State *L); -#define LUA_COLIBNAME "coroutine" -LUAMOD_API int (luaopen_coroutine) (lua_State *L); - -#define LUA_TABLIBNAME "table" -LUAMOD_API int (luaopen_table) (lua_State *L); - -#define LUA_IOLIBNAME "io" -LUAMOD_API int (luaopen_io) (lua_State *L); - -#define LUA_OSLIBNAME "os" -LUAMOD_API int (luaopen_os) (lua_State *L); - -#define LUA_STRLIBNAME "string" -LUAMOD_API int (luaopen_string) (lua_State *L); - -#define LUA_UTF8LIBNAME "utf8" -LUAMOD_API int (luaopen_utf8) (lua_State *L); - -#define LUA_MATHLIBNAME "math" -LUAMOD_API int (luaopen_math) (lua_State *L); - -#define LUA_DBLIBNAME "debug" -LUAMOD_API int (luaopen_debug) (lua_State *L); - #define LUA_LOADLIBNAME "package" +#define LUA_LOADLIBK (LUA_GK << 1) LUAMOD_API int (luaopen_package) (lua_State *L); -/* open all previous libraries */ -LUALIB_API void (luaL_openlibs) (lua_State *L); +#define LUA_COLIBNAME "coroutine" +#define LUA_COLIBK (LUA_LOADLIBK << 1) +LUAMOD_API int (luaopen_coroutine) (lua_State *L); + +#define LUA_DBLIBNAME "debug" +#define LUA_DBLIBK (LUA_COLIBK << 1) +LUAMOD_API int (luaopen_debug) (lua_State *L); + +#define LUA_IOLIBNAME "io" +#define LUA_IOLIBK (LUA_DBLIBK << 1) +LUAMOD_API int (luaopen_io) (lua_State *L); + +#define LUA_MATHLIBNAME "math" +#define LUA_MATHLIBK (LUA_IOLIBK << 1) +LUAMOD_API int (luaopen_math) (lua_State *L); + +#define LUA_OSLIBNAME "os" +#define LUA_OSLIBK (LUA_MATHLIBK << 1) +LUAMOD_API int (luaopen_os) (lua_State *L); + +#define LUA_STRLIBNAME "string" +#define LUA_STRLIBK (LUA_OSLIBK << 1) +LUAMOD_API int (luaopen_string) (lua_State *L); + +#define LUA_TABLIBNAME "table" +#define LUA_TABLIBK (LUA_STRLIBK << 1) +LUAMOD_API int (luaopen_table) (lua_State *L); + +#define LUA_UTF8LIBNAME "utf8" +#define LUA_UTF8LIBK (LUA_TABLIBK << 1) +LUAMOD_API int (luaopen_utf8) (lua_State *L); + + +/* open selected libraries */ +LUALIB_API void (luaL_openselectedlibs) (lua_State *L, int what); + +/* open all libraries */ +#define luaL_openlibs(L) luaL_openselectedlibs(L, ~0) #endif diff --git a/testes/api.lua b/testes/api.lua index bd85a923..f8e36ae3 100644 --- a/testes/api.lua +++ b/testes/api.lua @@ -1039,10 +1039,12 @@ assert(a == nil and b == 2) -- 2 == run-time error a, b, c = T.doremote(L1, "return a+") assert(a == nil and c == 3 and type(b) == "string") -- 3 == syntax error -T.loadlib(L1) +T.loadlib(L1, 2) -- load only 'package' a, b, c = T.doremote(L1, [[ string = require'string' - a = require'_G'; assert(a == _G and require("_G") == a) + local initialG = _G -- not loaded yet + local a = require'_G'; assert(a == _G and require("_G") == a) + assert(initialG == nil and io == nil) -- now we have 'assert' io = require'io'; assert(type(io.read) == "function") assert(require("io") == io) a = require'table'; assert(type(a.insert) == "function") @@ -1056,7 +1058,7 @@ T.closestate(L1); L1 = T.newstate() -T.loadlib(L1) +T.loadlib(L1, 0) T.doremote(L1, "a = {}") T.testC(L1, [[getglobal "a"; pushstring "x"; pushint 1; settable -3]]) @@ -1436,10 +1438,10 @@ end do -- garbage collection with no extra memory local L = T.newstate() - T.loadlib(L) + T.loadlib(L, 1 | 2) -- load _G and 'package' local res = (T.doremote(L, [[ - _ENV = require"_G" - local T = require"T" + _ENV = _G + assert(string == nil) local a = {} for i = 1, 1000 do a[i] = 'i' .. i end -- grow string table local stsize, stuse = T.querystr() diff --git a/testes/coroutine.lua b/testes/coroutine.lua index 15fccc30..f05672a5 100644 --- a/testes/coroutine.lua +++ b/testes/coroutine.lua @@ -694,7 +694,7 @@ else T.testC(state, "settop 0") - T.loadlib(state) + T.loadlib(state, 1 | 2) -- load _G and 'package' assert(T.doremote(state, [[ coroutine = require'coroutine';