New interface to function 'luaL_openselectedlibs'
Instead of preloading all non-loaded libraries, there is another mask to select which libraries to preload.
This commit is contained in:
22
linit.c
22
linit.c
@@ -21,12 +21,12 @@
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Standard Libraries
|
** Standard Libraries. (Must be listed in the same ORDER of their
|
||||||
|
** respective constants LUA_<libname>K.)
|
||||||
*/
|
*/
|
||||||
static const luaL_Reg stdlibs[] = {
|
static const luaL_Reg stdlibs[] = {
|
||||||
{LUA_GNAME, luaopen_base},
|
{LUA_GNAME, luaopen_base},
|
||||||
{LUA_LOADLIBNAME, luaopen_package},
|
{LUA_LOADLIBNAME, luaopen_package},
|
||||||
|
|
||||||
{LUA_COLIBNAME, luaopen_coroutine},
|
{LUA_COLIBNAME, luaopen_coroutine},
|
||||||
{LUA_DBLIBNAME, luaopen_debug},
|
{LUA_DBLIBNAME, luaopen_debug},
|
||||||
{LUA_IOLIBNAME, luaopen_io},
|
{LUA_IOLIBNAME, luaopen_io},
|
||||||
@@ -35,30 +35,28 @@ static const luaL_Reg stdlibs[] = {
|
|||||||
{LUA_STRLIBNAME, luaopen_string},
|
{LUA_STRLIBNAME, luaopen_string},
|
||||||
{LUA_TABLIBNAME, luaopen_table},
|
{LUA_TABLIBNAME, luaopen_table},
|
||||||
{LUA_UTF8LIBNAME, luaopen_utf8},
|
{LUA_UTF8LIBNAME, luaopen_utf8},
|
||||||
|
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** require selected standard libraries and add the others to the
|
** require and preload selected standard libraries
|
||||||
** preload table.
|
|
||||||
*/
|
*/
|
||||||
LUALIB_API void luaL_openselectedlibs (lua_State *L, int what) {
|
LUALIB_API void luaL_openselectedlibs (lua_State *L, int load, int preload) {
|
||||||
int mask = 1;
|
int mask;
|
||||||
const luaL_Reg *lib;
|
const luaL_Reg *lib;
|
||||||
luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE);
|
luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE);
|
||||||
for (lib = stdlibs; lib->func; (lib++, mask <<= 1)) {
|
for (lib = stdlibs, mask = 1; lib->name != NULL; lib++, mask <<= 1) {
|
||||||
if (what & mask) { /* selected? */
|
if (load & mask) { /* selected? */
|
||||||
luaL_requiref(L, lib->name, lib->func, 1); /* require library */
|
luaL_requiref(L, lib->name, lib->func, 1); /* require library */
|
||||||
lua_pop(L, 1); /* remove result from the stack */
|
lua_pop(L, 1); /* remove result from the stack */
|
||||||
}
|
}
|
||||||
else { /* add library to PRELOAD table */
|
else if (preload & mask) { /* selected? */
|
||||||
lua_pushcfunction(L, lib->func);
|
lua_pushcfunction(L, lib->func);
|
||||||
lua_setfield(L, -2, lib->name);
|
lua_setfield(L, -2, lib->name); /* add library to PRELOAD table */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lua_assert((mask >> 1) == LUA_UTF8LIBK);
|
lua_assert((mask >> 1) == LUA_UTF8LIBK);
|
||||||
lua_pop(L, 1); // remove PRELOAD table
|
lua_pop(L, 1); /* remove PRELOAD table */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
5
ltests.c
5
ltests.c
@@ -1223,8 +1223,9 @@ static lua_State *getstate (lua_State *L) {
|
|||||||
|
|
||||||
static int loadlib (lua_State *L) {
|
static int loadlib (lua_State *L) {
|
||||||
lua_State *L1 = getstate(L);
|
lua_State *L1 = getstate(L);
|
||||||
int what = luaL_checkinteger(L, 2);
|
int load = luaL_checkinteger(L, 2);
|
||||||
luaL_openselectedlibs(L1, what);
|
int preload = luaL_checkinteger(L, 3);
|
||||||
|
luaL_openselectedlibs(L1, load, preload);
|
||||||
luaL_requiref(L1, "T", luaB_opentests, 0);
|
luaL_requiref(L1, "T", luaB_opentests, 0);
|
||||||
lua_assert(lua_type(L1, -1) == LUA_TTABLE);
|
lua_assert(lua_type(L1, -1) == LUA_TTABLE);
|
||||||
/* 'requiref' should not reload module already loaded... */
|
/* 'requiref' should not reload module already loaded... */
|
||||||
|
|||||||
2
lua.c
2
lua.c
@@ -618,7 +618,7 @@ static void doREPL (lua_State *L) {
|
|||||||
/* }================================================================== */
|
/* }================================================================== */
|
||||||
|
|
||||||
#if !defined(luai_openlibs)
|
#if !defined(luai_openlibs)
|
||||||
#define luai_openlibs(L) luaL_openlibs(L)
|
#define luai_openlibs(L) luaL_openselectedlibs(L, ~0, 0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
8
lualib.h
8
lualib.h
@@ -14,11 +14,11 @@
|
|||||||
/* version suffix for environment variable names */
|
/* version suffix for environment variable names */
|
||||||
#define LUA_VERSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR
|
#define LUA_VERSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR
|
||||||
|
|
||||||
#define LUA_GK 1
|
#define LUA_GLIBK 1
|
||||||
LUAMOD_API int (luaopen_base) (lua_State *L);
|
LUAMOD_API int (luaopen_base) (lua_State *L);
|
||||||
|
|
||||||
#define LUA_LOADLIBNAME "package"
|
#define LUA_LOADLIBNAME "package"
|
||||||
#define LUA_LOADLIBK (LUA_GK << 1)
|
#define LUA_LOADLIBK (LUA_GLIBK << 1)
|
||||||
LUAMOD_API int (luaopen_package) (lua_State *L);
|
LUAMOD_API int (luaopen_package) (lua_State *L);
|
||||||
|
|
||||||
|
|
||||||
@@ -56,10 +56,10 @@ LUAMOD_API int (luaopen_utf8) (lua_State *L);
|
|||||||
|
|
||||||
|
|
||||||
/* open selected libraries */
|
/* open selected libraries */
|
||||||
LUALIB_API void (luaL_openselectedlibs) (lua_State *L, int what);
|
LUALIB_API void (luaL_openselectedlibs) (lua_State *L, int load, int preload);
|
||||||
|
|
||||||
/* open all libraries */
|
/* open all libraries */
|
||||||
#define luaL_openlibs(L) luaL_openselectedlibs(L, ~0)
|
#define luaL_openlibs(L) luaL_openselectedlibs(L, ~0, 0)
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -358,7 +358,7 @@ item = function (s)
|
|||||||
local t, p = string.match(s, "^([^\n|]+)|()")
|
local t, p = string.match(s, "^([^\n|]+)|()")
|
||||||
if t then
|
if t then
|
||||||
s = string.sub(s, p)
|
s = string.sub(s, p)
|
||||||
s = Tag.b(t..": ") .. s
|
s = Tag.b(t) ..": " .. s
|
||||||
end
|
end
|
||||||
return Tag.li(fixpara(s))
|
return Tag.li(fixpara(s))
|
||||||
end,
|
end,
|
||||||
|
|||||||
@@ -664,7 +664,6 @@ Values equal to or less than 100 mean the collector will not wait to
|
|||||||
start a new cycle.
|
start a new cycle.
|
||||||
A value of 200 means that the collector waits for
|
A value of 200 means that the collector waits for
|
||||||
the total number of objects to double before starting a new cycle.
|
the total number of objects to double before starting a new cycle.
|
||||||
The default value is 200.
|
|
||||||
|
|
||||||
The garbage-collector step size controls the
|
The garbage-collector step size controls the
|
||||||
size of each incremental step,
|
size of each incremental step,
|
||||||
@@ -672,7 +671,6 @@ specifically how many objects the interpreter creates
|
|||||||
before performing a step:
|
before performing a step:
|
||||||
A value of @M{n} means the interpreter will create
|
A value of @M{n} means the interpreter will create
|
||||||
approximately @M{n} objects between steps.
|
approximately @M{n} objects between steps.
|
||||||
The default value is 250.
|
|
||||||
|
|
||||||
The garbage-collector step multiplier
|
The garbage-collector step multiplier
|
||||||
controls the size of each GC step.
|
controls the size of each GC step.
|
||||||
@@ -681,7 +679,6 @@ in each step, @M{n%} objects for each created object.
|
|||||||
Larger values make the collector more aggressive.
|
Larger values make the collector more aggressive.
|
||||||
Beware that values too small can
|
Beware that values too small can
|
||||||
make the collector too slow to ever finish a cycle.
|
make the collector too slow to ever finish a cycle.
|
||||||
The default value is 200.
|
|
||||||
As a special case, a zero value means unlimited work,
|
As a special case, a zero value means unlimited work,
|
||||||
effectively producing a non-incremental, stop-the-world collector.
|
effectively producing a non-incremental, stop-the-world collector.
|
||||||
|
|
||||||
@@ -711,7 +708,6 @@ after the last major collection.
|
|||||||
For instance, for a multiplier of 20,
|
For instance, for a multiplier of 20,
|
||||||
the collector will do a minor collection when the number of objects
|
the collector will do a minor collection when the number of objects
|
||||||
gets 20% larger than the total after the last major collection.
|
gets 20% larger than the total after the last major collection.
|
||||||
The default value is 25.
|
|
||||||
|
|
||||||
The minor-major multiplier controls the shift to major collections.
|
The minor-major multiplier controls the shift to major collections.
|
||||||
For a multiplier @M{x},
|
For a multiplier @M{x},
|
||||||
@@ -721,7 +717,6 @@ than the total after the previous major collection.
|
|||||||
For instance, for a multiplier of 100,
|
For instance, for a multiplier of 100,
|
||||||
the collector will do a major collection when the number of old objects
|
the collector will do a major collection when the number of old objects
|
||||||
gets larger than twice the total after the previous major collection.
|
gets larger than twice the total after the previous major collection.
|
||||||
The default value is 100.
|
|
||||||
|
|
||||||
The major-minor multiplier controls the shift back to minor collections.
|
The major-minor multiplier controls the shift back to minor collections.
|
||||||
For a multiplier @M{x},
|
For a multiplier @M{x},
|
||||||
@@ -731,7 +726,6 @@ of the objects allocated during the last cycle.
|
|||||||
In particular, for a multiplier of 0,
|
In particular, for a multiplier of 0,
|
||||||
the collector will immediately shift back to minor collections
|
the collector will immediately shift back to minor collections
|
||||||
after doing one cycle of major collections.
|
after doing one cycle of major collections.
|
||||||
The default value is 50.
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5885,13 +5879,6 @@ or @id{NULL} if there is a @x{memory allocation error}.
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@APIEntry{void luaL_openlibs (lua_State *L);|
|
|
||||||
@apii{0,0,e}
|
|
||||||
|
|
||||||
Opens all standard Lua libraries into the given state.
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@APIEntry{
|
@APIEntry{
|
||||||
T luaL_opt (L, func, arg, dflt);|
|
T luaL_opt (L, func, arg, dflt);|
|
||||||
@apii{0,0,-}
|
@apii{0,0,-}
|
||||||
@@ -6073,7 +6060,7 @@ and sets the call result to @T{package.loaded[modname]},
|
|||||||
as if that function has been called through @Lid{require}.
|
as if that function has been called through @Lid{require}.
|
||||||
|
|
||||||
If @id{glb} is true,
|
If @id{glb} is true,
|
||||||
also stores the module into the global @id{modname}.
|
also stores the module into the global variable @id{modname}.
|
||||||
|
|
||||||
Leaves a copy of the module on the stack.
|
Leaves a copy of the module on the stack.
|
||||||
|
|
||||||
@@ -6290,23 +6277,61 @@ Except for the basic and the package libraries,
|
|||||||
each library provides all its functions as fields of a global table
|
each library provides all its functions as fields of a global table
|
||||||
or as methods of its objects.
|
or as methods of its objects.
|
||||||
|
|
||||||
To have access to these libraries,
|
}
|
||||||
the @N{C host} program should call the @Lid{luaL_openlibs} function,
|
|
||||||
which opens all standard libraries.
|
|
||||||
|
@sect2{lualib-h| @title{Loading the Libraries in C code}
|
||||||
|
|
||||||
|
A @N{C host} program must explicitly load
|
||||||
|
the standard libraries into a state,
|
||||||
|
if it wants its scripts to use them.
|
||||||
|
For that,
|
||||||
|
the host program can call the function @Lid{luaL_openlibs}.
|
||||||
Alternatively,
|
Alternatively,
|
||||||
the host program can open them individually by using
|
the host can select which libraries to open,
|
||||||
@Lid{luaL_requiref} to call
|
by using @Lid{luaL_openselectedlibs}.
|
||||||
@defid{luaopen_base} (for the basic library),
|
Both functions are defined in the header file @id{lualib.h}.
|
||||||
@defid{luaopen_package} (for the package library),
|
@index{lualib.h}
|
||||||
@defid{luaopen_coroutine} (for the coroutine library),
|
|
||||||
@defid{luaopen_string} (for the string library),
|
The stand-alone interpreter @id{lua} @see{lua-sa}
|
||||||
@defid{luaopen_utf8} (for the UTF-8 library),
|
already opens all standard libraries.
|
||||||
@defid{luaopen_table} (for the table library),
|
|
||||||
@defid{luaopen_math} (for the mathematical library),
|
@APIEntry{void luaL_openlibs (lua_State *L);|
|
||||||
@defid{luaopen_io} (for the I/O library),
|
@apii{0,0,e}
|
||||||
@defid{luaopen_os} (for the operating system library),
|
|
||||||
and @defid{luaopen_debug} (for the debug library).
|
Opens all standard Lua libraries into the given state.
|
||||||
These functions are declared in @defid{lualib.h}.
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@APIEntry{void luaL_openselectedlibs (lua_State *L, int load, int preload);|
|
||||||
|
@apii{0,0,e}
|
||||||
|
|
||||||
|
Opens (loads) and preloads selected libraries into the state @id{L}.
|
||||||
|
(To @emph{preload} means to add
|
||||||
|
the library loader into the table @Lid{package.preload},
|
||||||
|
so that the library can be required later by the program.
|
||||||
|
Keep in mind that @Lid{require} itself is provided
|
||||||
|
by the @emph{package} library.
|
||||||
|
If a program does not load that library,
|
||||||
|
it will be unable to require anything.)
|
||||||
|
|
||||||
|
The integer @id{load} selects which libraries to load;
|
||||||
|
the integer @id{preload} selects which to preload, among those not loaded.
|
||||||
|
Both are masks formed by a bitwise OR of the following constants:
|
||||||
|
@description{
|
||||||
|
@item{@defid{LUA_GLIBK} | the basic library.}
|
||||||
|
@item{@defid{LUA_LOADLIBK} | the package library.}
|
||||||
|
@item{@defid{LUA_COLIBK} | the coroutine library.}
|
||||||
|
@item{@defid{LUA_STRLIBK} | the string library.}
|
||||||
|
@item{@defid{LUA_UTF8LIBK} | the UTF-8 library.}
|
||||||
|
@item{@defid{LUA_TABLIBK} | the table library.}
|
||||||
|
@item{@defid{LUA_MATHLIBK} | the mathematical library.}
|
||||||
|
@item{@defid{LUA_IOLIBK} | the I/O library.}
|
||||||
|
@item{@defid{LUA_OSLIBK} | the operating system library.}
|
||||||
|
@item{@defid{LUA_DBLIBK} | the debug library.}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -546,9 +546,9 @@ do
|
|||||||
]], source)
|
]], source)
|
||||||
collectgarbage()
|
collectgarbage()
|
||||||
local m2 = collectgarbage"count" * 1024
|
local m2 = collectgarbage"count" * 1024
|
||||||
-- load used fewer than 350 bytes. Code alone has more than 3*N bytes,
|
-- load used fewer than 400 bytes. Code alone has more than 3*N bytes,
|
||||||
-- and string literal has N bytes. Both were not loaded.
|
-- and string literal has N bytes. Both were not loaded.
|
||||||
assert(m2 > m1 and m2 - m1 < 350)
|
assert(m2 > m1 and m2 - m1 < 400)
|
||||||
X = 0; code(); assert(X == N and Y == string.rep("a", N))
|
X = 0; code(); assert(X == N and Y == string.rep("a", N))
|
||||||
X = nil; Y = nil
|
X = nil; Y = nil
|
||||||
|
|
||||||
@@ -1122,7 +1122,7 @@ assert(a == nil and c == 2) -- 2 == run-time error
|
|||||||
a, b, c = T.doremote(L1, "return a+")
|
a, b, c = T.doremote(L1, "return a+")
|
||||||
assert(a == nil and c == 3 and type(b) == "string") -- 3 == syntax error
|
assert(a == nil and c == 3 and type(b) == "string") -- 3 == syntax error
|
||||||
|
|
||||||
T.loadlib(L1, 2) -- load only 'package'
|
T.loadlib(L1, 2, ~2) -- load only 'package', preload all others
|
||||||
a, b, c = T.doremote(L1, [[
|
a, b, c = T.doremote(L1, [[
|
||||||
string = require'string'
|
string = require'string'
|
||||||
local initialG = _G -- not loaded yet
|
local initialG = _G -- not loaded yet
|
||||||
@@ -1141,7 +1141,7 @@ T.closestate(L1);
|
|||||||
|
|
||||||
|
|
||||||
L1 = T.newstate()
|
L1 = T.newstate()
|
||||||
T.loadlib(L1, 0)
|
T.loadlib(L1, 0, 0)
|
||||||
T.doremote(L1, "a = {}")
|
T.doremote(L1, "a = {}")
|
||||||
T.testC(L1, [[getglobal "a"; pushstring "x"; pushint 1;
|
T.testC(L1, [[getglobal "a"; pushstring "x"; pushint 1;
|
||||||
settable -3]])
|
settable -3]])
|
||||||
@@ -1524,7 +1524,7 @@ end
|
|||||||
|
|
||||||
do -- garbage collection with no extra memory
|
do -- garbage collection with no extra memory
|
||||||
local L = T.newstate()
|
local L = T.newstate()
|
||||||
T.loadlib(L, 1 | 2) -- load _G and 'package'
|
T.loadlib(L, 1 | 2, 0) -- load _G and 'package'
|
||||||
local res = (T.doremote(L, [[
|
local res = (T.doremote(L, [[
|
||||||
_ENV = _G
|
_ENV = _G
|
||||||
assert(string == nil)
|
assert(string == nil)
|
||||||
|
|||||||
@@ -705,7 +705,7 @@ else
|
|||||||
|
|
||||||
T.testC(state, "settop 0")
|
T.testC(state, "settop 0")
|
||||||
|
|
||||||
T.loadlib(state, 1 | 2) -- load _G and 'package'
|
T.loadlib(state, 1 | 2, 4) -- load _G and 'package', preload 'coroutine'
|
||||||
|
|
||||||
assert(T.doremote(state, [[
|
assert(T.doremote(state, [[
|
||||||
coroutine = require'coroutine';
|
coroutine = require'coroutine';
|
||||||
|
|||||||
Reference in New Issue
Block a user