aboutsummaryrefslogtreecommitdiff
path: root/loadlib.c
diff options
context:
space:
mode:
Diffstat (limited to 'loadlib.c')
-rw-r--r--loadlib.c74
1 files changed, 41 insertions, 33 deletions
diff --git a/loadlib.c b/loadlib.c
index f2d7fe3c..2526096c 100644
--- a/loadlib.c
+++ b/loadlib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: loadlib.c,v 1.107 2011/11/30 12:58:57 roberto Exp roberto $ 2** $Id: loadlib.c,v 1.108 2011/12/12 16:34:03 roberto Exp roberto $
3** Dynamic library loader for Lua 3** Dynamic library loader for Lua
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5** 5**
@@ -92,9 +92,9 @@
92#define LUA_OFSEP "_" 92#define LUA_OFSEP "_"
93 93
94 94
95#define LIBPREFIX "LOADLIB: " 95/* table (in the registry) that keeps handles for all loaded C libraries */
96#define CLIBS "_CLIBS"
96 97
97#define POF LUA_POF
98#define LIB_FAIL "open" 98#define LIB_FAIL "open"
99 99
100 100
@@ -248,48 +248,54 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
248#endif 248#endif
249 249
250 250
251 251static void *ll_checkclib (lua_State *L, const char *path) {
252static void **ll_register (lua_State *L, const char *path) { 252 void *plib;
253 void **plib; 253 lua_getfield(L, LUA_REGISTRYINDEX, CLIBS);
254 lua_pushfstring(L, "%s%s", LIBPREFIX, path); 254 lua_getfield(L, -1, path);
255 lua_gettable(L, LUA_REGISTRYINDEX); /* check library in registry? */ 255 plib = lua_touserdata(L, -1); /* plib = CLIBS[path] */
256 if (!lua_isnil(L, -1)) /* is there an entry? */ 256 lua_pop(L, 2); /* pop CLIBS table and 'plib' */
257 plib = (void **)lua_touserdata(L, -1);
258 else { /* no entry yet; create one */
259 lua_pop(L, 1); /* remove result from gettable */
260 plib = (void **)lua_newuserdata(L, sizeof(const void *));
261 *plib = NULL;
262 luaL_setmetatable(L, "_LOADLIB");
263 lua_pushfstring(L, "%s%s", LIBPREFIX, path);
264 lua_pushvalue(L, -2);
265 lua_settable(L, LUA_REGISTRYINDEX);
266 }
267 return plib; 257 return plib;
268} 258}
269 259
270 260
261static void ll_addtoclib (lua_State *L, const char *path, void *plib) {
262 lua_getfield(L, LUA_REGISTRYINDEX, CLIBS);
263 lua_pushlightuserdata(L, plib);
264 lua_pushvalue(L, -1);
265 lua_setfield(L, -3, path); /* CLIBS[path] = plib */
266 lua_rawseti(L, -2, luaL_len(L, -2) + 1); /* CLIBS[#CLIBS + 1] = plib */
267 lua_pop(L, 1); /* pop CLIBS table */
268}
269
270
271/* 271/*
272** __gc tag method: calls library's `ll_unloadlib' function with the lib 272** __gc tag method for CLIBS table: calls 'll_unloadlib' for all lib
273** handle 273** handles in list CLIBS
274*/ 274*/
275static int gctm (lua_State *L) { 275static int gctm (lua_State *L) {
276 void **lib = (void **)luaL_checkudata(L, 1, "_LOADLIB"); 276 int n = luaL_len(L, 1);
277 if (*lib) ll_unloadlib(*lib); 277 for (; n >= 1; n--) { /* for each handle, in reverse order */
278 *lib = NULL; /* mark library as closed */ 278 lua_rawgeti(L, 1, n); /* get handle CLIBS[n] */
279 ll_unloadlib(lua_touserdata(L, -1));
280 lua_pop(L, 1); /* pop handle */
281 }
279 return 0; 282 return 0;
280} 283}
281 284
282 285
283static int ll_loadfunc (lua_State *L, const char *path, const char *sym) { 286static int ll_loadfunc (lua_State *L, const char *path, const char *sym) {
284 void **reg = ll_register(L, path); 287 void *reg = ll_checkclib(L, path); /* check loaded C libraries */
285 if (*reg == NULL) *reg = ll_load(L, path, *sym == '*'); 288 if (reg == NULL) { /* must load library? */
286 if (*reg == NULL) return ERRLIB; /* unable to load library */ 289 reg = ll_load(L, path, *sym == '*');
290 if (reg == NULL) return ERRLIB; /* unable to load library */
291 ll_addtoclib(L, path, reg);
292 }
287 if (*sym == '*') { /* loading only library (no function)? */ 293 if (*sym == '*') { /* loading only library (no function)? */
288 lua_pushboolean(L, 1); /* return 'true' */ 294 lua_pushboolean(L, 1); /* return 'true' */
289 return 0; /* no errors */ 295 return 0; /* no errors */
290 } 296 }
291 else { 297 else {
292 lua_CFunction f = ll_sym(L, *reg, sym); 298 lua_CFunction f = ll_sym(L, reg, sym);
293 if (f == NULL) 299 if (f == NULL)
294 return ERRFUNC; /* unable to find function */ 300 return ERRFUNC; /* unable to find function */
295 lua_pushcfunction(L, f); /* else create new function */ 301 lua_pushcfunction(L, f); /* else create new function */
@@ -418,12 +424,12 @@ static int loadfunc (lua_State *L, const char *filename, const char *modname) {
418 if (mark) { 424 if (mark) {
419 int stat; 425 int stat;
420 funcname = lua_pushlstring(L, modname, mark - modname); 426 funcname = lua_pushlstring(L, modname, mark - modname);
421 funcname = lua_pushfstring(L, POF"%s", funcname); 427 funcname = lua_pushfstring(L, LUA_POF"%s", funcname);
422 stat = ll_loadfunc(L, filename, funcname); 428 stat = ll_loadfunc(L, filename, funcname);
423 if (stat != ERRFUNC) return stat; 429 if (stat != ERRFUNC) return stat;
424 modname = mark + 1; /* else go ahead and try old-style name */ 430 modname = mark + 1; /* else go ahead and try old-style name */
425 } 431 }
426 funcname = lua_pushfstring(L, POF"%s", modname); 432 funcname = lua_pushfstring(L, LUA_POF"%s", modname);
427 return ll_loadfunc(L, filename, funcname); 433 return ll_loadfunc(L, filename, funcname);
428} 434}
429 435
@@ -672,10 +678,12 @@ static const lua_CFunction searchers[] =
672 678
673LUAMOD_API int luaopen_package (lua_State *L) { 679LUAMOD_API int luaopen_package (lua_State *L) {
674 int i; 680 int i;
675 /* create new type _LOADLIB */ 681 /* create table CLIBS to keep track of loaded C libraries */
676 luaL_newmetatable(L, "_LOADLIB"); 682 luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS);
683 lua_createtable(L, 0, 1); /* metatable for CLIBS */
677 lua_pushcfunction(L, gctm); 684 lua_pushcfunction(L, gctm);
678 lua_setfield(L, -2, "__gc"); 685 lua_setfield(L, -2, "__gc"); /* set finalizer for CLIBS table */
686 lua_setmetatable(L, -2);
679 /* create `package' table */ 687 /* create `package' table */
680 luaL_newlib(L, pk_funcs); 688 luaL_newlib(L, pk_funcs);
681 /* create 'searchers' table */ 689 /* create 'searchers' table */