diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2022-12-07 15:12:52 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2022-12-07 15:12:52 -0300 |
| commit | d738c8d18bcc5651109b3a46103d6aa983772e68 (patch) | |
| tree | e66f2f38d7cc1600da3ea19b134c7c21636a3870 | |
| parent | 0270c204c235a495ce4702ac3891eb30752d0c8d (diff) | |
| download | lua-d738c8d18bcc5651109b3a46103d6aa983772e68.tar.gz lua-d738c8d18bcc5651109b3a46103d6aa983772e68.tar.bz2 lua-d738c8d18bcc5651109b3a46103d6aa983772e68.zip | |
New function 'luaL_openselectedlibs'
Makes it easier to start Lua with only some standard libraries.
| -rw-r--r-- | linit.c | 51 | ||||
| -rw-r--r-- | ltests.c | 24 | ||||
| -rw-r--r-- | ltests.h | 4 | ||||
| -rw-r--r-- | lua.c | 6 | ||||
| -rw-r--r-- | lualib.h | 39 | ||||
| -rw-r--r-- | testes/api.lua | 14 | ||||
| -rw-r--r-- | testes/coroutine.lua | 2 |
7 files changed, 71 insertions, 69 deletions
| @@ -8,21 +8,6 @@ | |||
| 8 | #define linit_c | 8 | #define linit_c |
| 9 | #define LUA_LIB | 9 | #define LUA_LIB |
| 10 | 10 | ||
| 11 | /* | ||
| 12 | ** If you embed Lua in your program and need to open the standard | ||
| 13 | ** libraries, call luaL_openlibs in your program. If you need a | ||
| 14 | ** different set of libraries, copy this file to your project and edit | ||
| 15 | ** it to suit your needs. | ||
| 16 | ** | ||
| 17 | ** You can also *preload* libraries, so that a later 'require' can | ||
| 18 | ** open the library, which is already linked to the application. | ||
| 19 | ** For that, do the following code: | ||
| 20 | ** | ||
| 21 | ** luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); | ||
| 22 | ** lua_pushcfunction(L, luaopen_modname); | ||
| 23 | ** lua_setfield(L, -2, modname); | ||
| 24 | ** lua_pop(L, 1); // remove PRELOAD table | ||
| 25 | */ | ||
| 26 | 11 | ||
| 27 | #include "lprefix.h" | 12 | #include "lprefix.h" |
| 28 | 13 | ||
| @@ -36,30 +21,44 @@ | |||
| 36 | 21 | ||
| 37 | 22 | ||
| 38 | /* | 23 | /* |
| 39 | ** these libs are loaded by lua.c and are readily available to any Lua | 24 | ** Standard Libraries |
| 40 | ** program | ||
| 41 | */ | 25 | */ |
| 42 | static const luaL_Reg loadedlibs[] = { | 26 | static const luaL_Reg stdlibs[] = { |
| 43 | {LUA_GNAME, luaopen_base}, | 27 | {LUA_GNAME, luaopen_base}, |
| 44 | {LUA_LOADLIBNAME, luaopen_package}, | 28 | {LUA_LOADLIBNAME, luaopen_package}, |
| 29 | |||
| 45 | {LUA_COLIBNAME, luaopen_coroutine}, | 30 | {LUA_COLIBNAME, luaopen_coroutine}, |
| 46 | {LUA_TABLIBNAME, luaopen_table}, | 31 | {LUA_DBLIBNAME, luaopen_debug}, |
| 47 | {LUA_IOLIBNAME, luaopen_io}, | 32 | {LUA_IOLIBNAME, luaopen_io}, |
| 33 | {LUA_MATHLIBNAME, luaopen_math}, | ||
| 48 | {LUA_OSLIBNAME, luaopen_os}, | 34 | {LUA_OSLIBNAME, luaopen_os}, |
| 49 | {LUA_STRLIBNAME, luaopen_string}, | 35 | {LUA_STRLIBNAME, luaopen_string}, |
| 50 | {LUA_MATHLIBNAME, luaopen_math}, | 36 | {LUA_TABLIBNAME, luaopen_table}, |
| 51 | {LUA_UTF8LIBNAME, luaopen_utf8}, | 37 | {LUA_UTF8LIBNAME, luaopen_utf8}, |
| 52 | {LUA_DBLIBNAME, luaopen_debug}, | 38 | |
| 53 | {NULL, NULL} | 39 | {NULL, NULL} |
| 54 | }; | 40 | }; |
| 55 | 41 | ||
| 56 | 42 | ||
| 57 | LUALIB_API void luaL_openlibs (lua_State *L) { | 43 | /* |
| 44 | ** require selected standard libraries and add the others to the | ||
| 45 | ** preload table. | ||
| 46 | */ | ||
| 47 | LUALIB_API void luaL_openselectedlibs (lua_State *L, int what) { | ||
| 48 | int mask = 1; | ||
| 58 | const luaL_Reg *lib; | 49 | const luaL_Reg *lib; |
| 59 | /* "require" functions from 'loadedlibs' and set results to global table */ | 50 | luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); |
| 60 | for (lib = loadedlibs; lib->func; lib++) { | 51 | for (lib = stdlibs; lib->func; (lib++, mask <<= 1)) { |
| 61 | luaL_requiref(L, lib->name, lib->func, 1); | 52 | if (what & mask) { /* selected? */ |
| 62 | lua_pop(L, 1); /* remove lib */ | 53 | luaL_requiref(L, lib->name, lib->func, 1); /* require library */ |
| 54 | lua_pop(L, 1); /* remove result from the stack */ | ||
| 55 | } | ||
| 56 | else { /* add library to PRELOAD table */ | ||
| 57 | lua_pushcfunction(L, lib->func); | ||
| 58 | lua_setfield(L, -2, lib->name); | ||
| 59 | } | ||
| 63 | } | 60 | } |
| 61 | lua_assert((mask >> 1) == LUA_UTF8LIBK); | ||
| 62 | lua_pop(L, 1); // remove PRELOAD table | ||
| 64 | } | 63 | } |
| 65 | 64 | ||
| @@ -1178,31 +1178,15 @@ static lua_State *getstate (lua_State *L) { | |||
| 1178 | 1178 | ||
| 1179 | 1179 | ||
| 1180 | static int loadlib (lua_State *L) { | 1180 | static int loadlib (lua_State *L) { |
| 1181 | static const luaL_Reg libs[] = { | ||
| 1182 | {LUA_GNAME, luaopen_base}, | ||
| 1183 | {"coroutine", luaopen_coroutine}, | ||
| 1184 | {"debug", luaopen_debug}, | ||
| 1185 | {"io", luaopen_io}, | ||
| 1186 | {"os", luaopen_os}, | ||
| 1187 | {"math", luaopen_math}, | ||
| 1188 | {"string", luaopen_string}, | ||
| 1189 | {"table", luaopen_table}, | ||
| 1190 | {"T", luaB_opentests}, | ||
| 1191 | {NULL, NULL} | ||
| 1192 | }; | ||
| 1193 | lua_State *L1 = getstate(L); | 1181 | lua_State *L1 = getstate(L); |
| 1194 | int i; | 1182 | int what = luaL_checkinteger(L, 2); |
| 1195 | luaL_requiref(L1, "package", luaopen_package, 0); | 1183 | luaL_openselectedlibs(L1, what); |
| 1184 | luaL_requiref(L1, "T", luaB_opentests, 0); | ||
| 1196 | lua_assert(lua_type(L1, -1) == LUA_TTABLE); | 1185 | lua_assert(lua_type(L1, -1) == LUA_TTABLE); |
| 1197 | /* 'requiref' should not reload module already loaded... */ | 1186 | /* 'requiref' should not reload module already loaded... */ |
| 1198 | luaL_requiref(L1, "package", NULL, 1); /* seg. fault if it reloads */ | 1187 | luaL_requiref(L1, "T", NULL, 1); /* seg. fault if it reloads */ |
| 1199 | /* ...but should return the same module */ | 1188 | /* ...but should return the same module */ |
| 1200 | lua_assert(lua_compare(L1, -1, -2, LUA_OPEQ)); | 1189 | lua_assert(lua_compare(L1, -1, -2, LUA_OPEQ)); |
| 1201 | luaL_getsubtable(L1, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); | ||
| 1202 | for (i = 0; libs[i].name; i++) { | ||
| 1203 | lua_pushcfunction(L1, libs[i].func); | ||
| 1204 | lua_setfield(L1, -2, libs[i].name); | ||
| 1205 | } | ||
| 1206 | return 0; | 1190 | return 0; |
| 1207 | } | 1191 | } |
| 1208 | 1192 | ||
| @@ -103,8 +103,8 @@ LUA_API void *debug_realloc (void *ud, void *block, | |||
| 103 | 103 | ||
| 104 | #if defined(lua_c) | 104 | #if defined(lua_c) |
| 105 | #define luaL_newstate() lua_newstate(debug_realloc, &l_memcontrol) | 105 | #define luaL_newstate() lua_newstate(debug_realloc, &l_memcontrol) |
| 106 | #define luaL_openlibs(L) \ | 106 | #define luai_openlibs(L) \ |
| 107 | { (luaL_openlibs)(L); \ | 107 | { luaL_openlibs(L); \ |
| 108 | luaL_requiref(L, "T", luaB_opentests, 1); \ | 108 | luaL_requiref(L, "T", luaB_opentests, 1); \ |
| 109 | lua_pop(L, 1); } | 109 | lua_pop(L, 1); } |
| 110 | #endif | 110 | #endif |
| @@ -609,6 +609,10 @@ static void doREPL (lua_State *L) { | |||
| 609 | 609 | ||
| 610 | /* }================================================================== */ | 610 | /* }================================================================== */ |
| 611 | 611 | ||
| 612 | #if !defined(luai_openlibs) | ||
| 613 | #define luai_openlibs(L) luaL_openlibs(L) | ||
| 614 | #endif | ||
| 615 | |||
| 612 | 616 | ||
| 613 | /* | 617 | /* |
| 614 | ** Main body of stand-alone interpreter (to be called in protected mode). | 618 | ** Main body of stand-alone interpreter (to be called in protected mode). |
| @@ -631,7 +635,7 @@ static int pmain (lua_State *L) { | |||
| 631 | lua_pushboolean(L, 1); /* signal for libraries to ignore env. vars. */ | 635 | lua_pushboolean(L, 1); /* signal for libraries to ignore env. vars. */ |
| 632 | lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); | 636 | lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); |
| 633 | } | 637 | } |
| 634 | luaL_openlibs(L); /* open standard libraries */ | 638 | luai_openlibs(L); /* open standard libraries */ |
| 635 | createargtable(L, argv, argc, script); /* create table 'arg' */ | 639 | createargtable(L, argv, argc, script); /* create table 'arg' */ |
| 636 | lua_gc(L, LUA_GCRESTART); /* start GC... */ | 640 | lua_gc(L, LUA_GCRESTART); /* start GC... */ |
| 637 | lua_gc(L, LUA_GCGEN, 0, 0); /* ...in generational mode */ | 641 | lua_gc(L, LUA_GCGEN, 0, 0); /* ...in generational mode */ |
| @@ -14,39 +14,52 @@ | |||
| 14 | /* version suffix for environment variable names */ | 14 | /* version suffix for environment variable names */ |
| 15 | #define LUA_VERSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR | 15 | #define LUA_VERSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR |
| 16 | 16 | ||
| 17 | 17 | #define LUA_GK 1 | |
| 18 | LUAMOD_API int (luaopen_base) (lua_State *L); | 18 | LUAMOD_API int (luaopen_base) (lua_State *L); |
| 19 | 19 | ||
| 20 | #define LUA_LOADLIBNAME "package" | ||
| 21 | #define LUA_LOADLIBK (LUA_GK << 1) | ||
| 22 | LUAMOD_API int (luaopen_package) (lua_State *L); | ||
| 23 | |||
| 24 | |||
| 20 | #define LUA_COLIBNAME "coroutine" | 25 | #define LUA_COLIBNAME "coroutine" |
| 26 | #define LUA_COLIBK (LUA_LOADLIBK << 1) | ||
| 21 | LUAMOD_API int (luaopen_coroutine) (lua_State *L); | 27 | LUAMOD_API int (luaopen_coroutine) (lua_State *L); |
| 22 | 28 | ||
| 23 | #define LUA_TABLIBNAME "table" | 29 | #define LUA_DBLIBNAME "debug" |
| 24 | LUAMOD_API int (luaopen_table) (lua_State *L); | 30 | #define LUA_DBLIBK (LUA_COLIBK << 1) |
| 31 | LUAMOD_API int (luaopen_debug) (lua_State *L); | ||
| 25 | 32 | ||
| 26 | #define LUA_IOLIBNAME "io" | 33 | #define LUA_IOLIBNAME "io" |
| 34 | #define LUA_IOLIBK (LUA_DBLIBK << 1) | ||
| 27 | LUAMOD_API int (luaopen_io) (lua_State *L); | 35 | LUAMOD_API int (luaopen_io) (lua_State *L); |
| 28 | 36 | ||
| 37 | #define LUA_MATHLIBNAME "math" | ||
| 38 | #define LUA_MATHLIBK (LUA_IOLIBK << 1) | ||
| 39 | LUAMOD_API int (luaopen_math) (lua_State *L); | ||
| 40 | |||
| 29 | #define LUA_OSLIBNAME "os" | 41 | #define LUA_OSLIBNAME "os" |
| 42 | #define LUA_OSLIBK (LUA_MATHLIBK << 1) | ||
| 30 | LUAMOD_API int (luaopen_os) (lua_State *L); | 43 | LUAMOD_API int (luaopen_os) (lua_State *L); |
| 31 | 44 | ||
| 32 | #define LUA_STRLIBNAME "string" | 45 | #define LUA_STRLIBNAME "string" |
| 46 | #define LUA_STRLIBK (LUA_OSLIBK << 1) | ||
| 33 | LUAMOD_API int (luaopen_string) (lua_State *L); | 47 | LUAMOD_API int (luaopen_string) (lua_State *L); |
| 34 | 48 | ||
| 49 | #define LUA_TABLIBNAME "table" | ||
| 50 | #define LUA_TABLIBK (LUA_STRLIBK << 1) | ||
| 51 | LUAMOD_API int (luaopen_table) (lua_State *L); | ||
| 52 | |||
| 35 | #define LUA_UTF8LIBNAME "utf8" | 53 | #define LUA_UTF8LIBNAME "utf8" |
| 54 | #define LUA_UTF8LIBK (LUA_TABLIBK << 1) | ||
| 36 | LUAMOD_API int (luaopen_utf8) (lua_State *L); | 55 | LUAMOD_API int (luaopen_utf8) (lua_State *L); |
| 37 | 56 | ||
| 38 | #define LUA_MATHLIBNAME "math" | ||
| 39 | LUAMOD_API int (luaopen_math) (lua_State *L); | ||
| 40 | |||
| 41 | #define LUA_DBLIBNAME "debug" | ||
| 42 | LUAMOD_API int (luaopen_debug) (lua_State *L); | ||
| 43 | |||
| 44 | #define LUA_LOADLIBNAME "package" | ||
| 45 | LUAMOD_API int (luaopen_package) (lua_State *L); | ||
| 46 | 57 | ||
| 58 | /* open selected libraries */ | ||
| 59 | LUALIB_API void (luaL_openselectedlibs) (lua_State *L, int what); | ||
| 47 | 60 | ||
| 48 | /* open all previous libraries */ | 61 | /* open all libraries */ |
| 49 | LUALIB_API void (luaL_openlibs) (lua_State *L); | 62 | #define luaL_openlibs(L) luaL_openselectedlibs(L, ~0) |
| 50 | 63 | ||
| 51 | 64 | ||
| 52 | #endif | 65 | #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 | |||
| 1039 | a, b, c = T.doremote(L1, "return a+") | 1039 | a, b, c = T.doremote(L1, "return a+") |
| 1040 | assert(a == nil and c == 3 and type(b) == "string") -- 3 == syntax error | 1040 | assert(a == nil and c == 3 and type(b) == "string") -- 3 == syntax error |
| 1041 | 1041 | ||
| 1042 | T.loadlib(L1) | 1042 | T.loadlib(L1, 2) -- load only 'package' |
| 1043 | a, b, c = T.doremote(L1, [[ | 1043 | a, b, c = T.doremote(L1, [[ |
| 1044 | string = require'string' | 1044 | string = require'string' |
| 1045 | a = require'_G'; assert(a == _G and require("_G") == a) | 1045 | local initialG = _G -- not loaded yet |
| 1046 | local a = require'_G'; assert(a == _G and require("_G") == a) | ||
| 1047 | assert(initialG == nil and io == nil) -- now we have 'assert' | ||
| 1046 | io = require'io'; assert(type(io.read) == "function") | 1048 | io = require'io'; assert(type(io.read) == "function") |
| 1047 | assert(require("io") == io) | 1049 | assert(require("io") == io) |
| 1048 | a = require'table'; assert(type(a.insert) == "function") | 1050 | a = require'table'; assert(type(a.insert) == "function") |
| @@ -1056,7 +1058,7 @@ T.closestate(L1); | |||
| 1056 | 1058 | ||
| 1057 | 1059 | ||
| 1058 | L1 = T.newstate() | 1060 | L1 = T.newstate() |
| 1059 | T.loadlib(L1) | 1061 | T.loadlib(L1, 0) |
| 1060 | T.doremote(L1, "a = {}") | 1062 | T.doremote(L1, "a = {}") |
| 1061 | T.testC(L1, [[getglobal "a"; pushstring "x"; pushint 1; | 1063 | T.testC(L1, [[getglobal "a"; pushstring "x"; pushint 1; |
| 1062 | settable -3]]) | 1064 | settable -3]]) |
| @@ -1436,10 +1438,10 @@ end | |||
| 1436 | 1438 | ||
| 1437 | do -- garbage collection with no extra memory | 1439 | do -- garbage collection with no extra memory |
| 1438 | local L = T.newstate() | 1440 | local L = T.newstate() |
| 1439 | T.loadlib(L) | 1441 | T.loadlib(L, 1 | 2) -- load _G and 'package' |
| 1440 | local res = (T.doremote(L, [[ | 1442 | local res = (T.doremote(L, [[ |
| 1441 | _ENV = require"_G" | 1443 | _ENV = _G |
| 1442 | local T = require"T" | 1444 | assert(string == nil) |
| 1443 | local a = {} | 1445 | local a = {} |
| 1444 | for i = 1, 1000 do a[i] = 'i' .. i end -- grow string table | 1446 | for i = 1, 1000 do a[i] = 'i' .. i end -- grow string table |
| 1445 | local stsize, stuse = T.querystr() | 1447 | 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 | |||
| 694 | 694 | ||
| 695 | T.testC(state, "settop 0") | 695 | T.testC(state, "settop 0") |
| 696 | 696 | ||
| 697 | T.loadlib(state) | 697 | T.loadlib(state, 1 | 2) -- load _G and 'package' |
| 698 | 698 | ||
| 699 | assert(T.doremote(state, [[ | 699 | assert(T.doremote(state, [[ |
| 700 | coroutine = require'coroutine'; | 700 | coroutine = require'coroutine'; |
