|
@@ -1,5 +1,5 @@
|
|
|
/*
|
|
|
-** $Id: loadlib.c,v 1.107 2011/11/30 12:58:57 roberto Exp roberto $
|
|
|
+** $Id: loadlib.c,v 1.108 2011/12/12 16:34:03 roberto Exp roberto $
|
|
|
** Dynamic library loader for Lua
|
|
|
** See Copyright Notice in lua.h
|
|
|
**
|
|
@@ -92,9 +92,9 @@
|
|
|
#define LUA_OFSEP "_"
|
|
|
|
|
|
|
|
|
-#define LIBPREFIX "LOADLIB: "
|
|
|
+/* table (in the registry) that keeps handles for all loaded C libraries */
|
|
|
+#define CLIBS "_CLIBS"
|
|
|
|
|
|
-#define POF LUA_POF
|
|
|
#define LIB_FAIL "open"
|
|
|
|
|
|
|
|
@@ -248,48 +248,54 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
|
|
|
#endif
|
|
|
|
|
|
|
|
|
-
|
|
|
-static void **ll_register (lua_State *L, const char *path) {
|
|
|
- void **plib;
|
|
|
- lua_pushfstring(L, "%s%s", LIBPREFIX, path);
|
|
|
- lua_gettable(L, LUA_REGISTRYINDEX); /* check library in registry? */
|
|
|
- if (!lua_isnil(L, -1)) /* is there an entry? */
|
|
|
- plib = (void **)lua_touserdata(L, -1);
|
|
|
- else { /* no entry yet; create one */
|
|
|
- lua_pop(L, 1); /* remove result from gettable */
|
|
|
- plib = (void **)lua_newuserdata(L, sizeof(const void *));
|
|
|
- *plib = NULL;
|
|
|
- luaL_setmetatable(L, "_LOADLIB");
|
|
|
- lua_pushfstring(L, "%s%s", LIBPREFIX, path);
|
|
|
- lua_pushvalue(L, -2);
|
|
|
- lua_settable(L, LUA_REGISTRYINDEX);
|
|
|
- }
|
|
|
+static void *ll_checkclib (lua_State *L, const char *path) {
|
|
|
+ void *plib;
|
|
|
+ lua_getfield(L, LUA_REGISTRYINDEX, CLIBS);
|
|
|
+ lua_getfield(L, -1, path);
|
|
|
+ plib = lua_touserdata(L, -1); /* plib = CLIBS[path] */
|
|
|
+ lua_pop(L, 2); /* pop CLIBS table and 'plib' */
|
|
|
return plib;
|
|
|
}
|
|
|
|
|
|
|
|
|
+static void ll_addtoclib (lua_State *L, const char *path, void *plib) {
|
|
|
+ lua_getfield(L, LUA_REGISTRYINDEX, CLIBS);
|
|
|
+ lua_pushlightuserdata(L, plib);
|
|
|
+ lua_pushvalue(L, -1);
|
|
|
+ lua_setfield(L, -3, path); /* CLIBS[path] = plib */
|
|
|
+ lua_rawseti(L, -2, luaL_len(L, -2) + 1); /* CLIBS[#CLIBS + 1] = plib */
|
|
|
+ lua_pop(L, 1); /* pop CLIBS table */
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
/*
|
|
|
-** __gc tag method: calls library's `ll_unloadlib' function with the lib
|
|
|
-** handle
|
|
|
+** __gc tag method for CLIBS table: calls 'll_unloadlib' for all lib
|
|
|
+** handles in list CLIBS
|
|
|
*/
|
|
|
static int gctm (lua_State *L) {
|
|
|
- void **lib = (void **)luaL_checkudata(L, 1, "_LOADLIB");
|
|
|
- if (*lib) ll_unloadlib(*lib);
|
|
|
- *lib = NULL; /* mark library as closed */
|
|
|
+ int n = luaL_len(L, 1);
|
|
|
+ for (; n >= 1; n--) { /* for each handle, in reverse order */
|
|
|
+ lua_rawgeti(L, 1, n); /* get handle CLIBS[n] */
|
|
|
+ ll_unloadlib(lua_touserdata(L, -1));
|
|
|
+ lua_pop(L, 1); /* pop handle */
|
|
|
+ }
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
|
|
|
static int ll_loadfunc (lua_State *L, const char *path, const char *sym) {
|
|
|
- void **reg = ll_register(L, path);
|
|
|
- if (*reg == NULL) *reg = ll_load(L, path, *sym == '*');
|
|
|
- if (*reg == NULL) return ERRLIB; /* unable to load library */
|
|
|
+ void *reg = ll_checkclib(L, path); /* check loaded C libraries */
|
|
|
+ if (reg == NULL) { /* must load library? */
|
|
|
+ reg = ll_load(L, path, *sym == '*');
|
|
|
+ if (reg == NULL) return ERRLIB; /* unable to load library */
|
|
|
+ ll_addtoclib(L, path, reg);
|
|
|
+ }
|
|
|
if (*sym == '*') { /* loading only library (no function)? */
|
|
|
lua_pushboolean(L, 1); /* return 'true' */
|
|
|
return 0; /* no errors */
|
|
|
}
|
|
|
else {
|
|
|
- lua_CFunction f = ll_sym(L, *reg, sym);
|
|
|
+ lua_CFunction f = ll_sym(L, reg, sym);
|
|
|
if (f == NULL)
|
|
|
return ERRFUNC; /* unable to find function */
|
|
|
lua_pushcfunction(L, f); /* else create new function */
|
|
@@ -418,12 +424,12 @@ static int loadfunc (lua_State *L, const char *filename, const char *modname) {
|
|
|
if (mark) {
|
|
|
int stat;
|
|
|
funcname = lua_pushlstring(L, modname, mark - modname);
|
|
|
- funcname = lua_pushfstring(L, POF"%s", funcname);
|
|
|
+ funcname = lua_pushfstring(L, LUA_POF"%s", funcname);
|
|
|
stat = ll_loadfunc(L, filename, funcname);
|
|
|
if (stat != ERRFUNC) return stat;
|
|
|
modname = mark + 1; /* else go ahead and try old-style name */
|
|
|
}
|
|
|
- funcname = lua_pushfstring(L, POF"%s", modname);
|
|
|
+ funcname = lua_pushfstring(L, LUA_POF"%s", modname);
|
|
|
return ll_loadfunc(L, filename, funcname);
|
|
|
}
|
|
|
|
|
@@ -672,10 +678,12 @@ static const lua_CFunction searchers[] =
|
|
|
|
|
|
LUAMOD_API int luaopen_package (lua_State *L) {
|
|
|
int i;
|
|
|
- /* create new type _LOADLIB */
|
|
|
- luaL_newmetatable(L, "_LOADLIB");
|
|
|
+ /* create table CLIBS to keep track of loaded C libraries */
|
|
|
+ luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS);
|
|
|
+ lua_createtable(L, 0, 1); /* metatable for CLIBS */
|
|
|
lua_pushcfunction(L, gctm);
|
|
|
- lua_setfield(L, -2, "__gc");
|
|
|
+ lua_setfield(L, -2, "__gc"); /* set finalizer for CLIBS table */
|
|
|
+ lua_setmetatable(L, -2);
|
|
|
/* create `package' table */
|
|
|
luaL_newlib(L, pk_funcs);
|
|
|
/* create 'searchers' table */
|