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.
Diffstat (limited to '')
-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'; |