diff options
| -rw-r--r-- | loadlib.c | 74 |
1 files changed, 41 insertions, 33 deletions
| @@ -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 | 251 | static void *ll_checkclib (lua_State *L, const char *path) { | |
| 252 | static 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 | ||
| 261 | static 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 | */ |
| 275 | static int gctm (lua_State *L) { | 275 | static 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 | ||
| 283 | static int ll_loadfunc (lua_State *L, const char *path, const char *sym) { | 286 | static 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 | ||
| 673 | LUAMOD_API int luaopen_package (lua_State *L) { | 679 | LUAMOD_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 */ |
