diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2014-07-28 14:47:53 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2014-07-28 14:47:53 -0300 |
| commit | 255d59ed5e2743b97626eff57444f44defc39270 (patch) | |
| tree | 1c240056965f157fdffd0b715d5d138b9d56219d /loadlib.c | |
| parent | 925d1b59f931ad3cf23e67f39f6771b9a9e06f5f (diff) | |
| download | lua-255d59ed5e2743b97626eff57444f44defc39270.tar.gz lua-255d59ed5e2743b97626eff57444f44defc39270.tar.bz2 lua-255d59ed5e2743b97626eff57444f44defc39270.zip | |
some janitorial work (comments, small refactoring)
Diffstat (limited to 'loadlib.c')
| -rw-r--r-- | loadlib.c | 141 |
1 files changed, 96 insertions, 45 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: loadlib.c,v 1.113 2014/03/12 20:57:40 roberto Exp roberto $ | 2 | ** $Id: loadlib.c,v 1.114 2014/07/16 13:56:14 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 | ** |
| @@ -97,20 +97,33 @@ | |||
| 97 | 97 | ||
| 98 | #define LIB_FAIL "open" | 98 | #define LIB_FAIL "open" |
| 99 | 99 | ||
| 100 | |||
| 101 | /* error codes for ll_loadfunc */ | ||
| 102 | #define ERRLIB 1 | ||
| 103 | #define ERRFUNC 2 | ||
| 104 | |||
| 105 | #define setprogdir(L) ((void)0) | 100 | #define setprogdir(L) ((void)0) |
| 106 | 101 | ||
| 107 | 102 | ||
| 108 | /* | 103 | /* |
| 109 | ** system-dependent functions | 104 | ** system-dependent functions |
| 110 | */ | 105 | */ |
| 111 | static void ll_unloadlib (void *lib); | 106 | |
| 112 | static void *ll_load (lua_State *L, const char *path, int seeglb); | 107 | /* |
| 113 | static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym); | 108 | ** unload library 'lib' |
| 109 | */ | ||
| 110 | static void lsys_unloadlib (void *lib); | ||
| 111 | |||
| 112 | /* | ||
| 113 | ** load C library in file 'path'. If 'seeglb', load with all names in | ||
| 114 | ** the library global. | ||
| 115 | ** Returns the library; in case of error, returns NULL plus an | ||
| 116 | ** error string in the stack. | ||
| 117 | */ | ||
| 118 | static void *lsys_load (lua_State *L, const char *path, int seeglb); | ||
| 119 | |||
| 120 | /* | ||
| 121 | ** Try to find a function named 'sym' in library 'lib'. | ||
| 122 | ** Returns the function; in case of error, returns NULL plus an | ||
| 123 | ** error string in the stack. | ||
| 124 | */ | ||
| 125 | static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym); | ||
| 126 | |||
| 114 | 127 | ||
| 115 | 128 | ||
| 116 | 129 | ||
| @@ -126,19 +139,19 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym); | |||
| 126 | 139 | ||
| 127 | #include <dlfcn.h> | 140 | #include <dlfcn.h> |
| 128 | 141 | ||
| 129 | static void ll_unloadlib (void *lib) { | 142 | static void lsys_unloadlib (void *lib) { |
| 130 | dlclose(lib); | 143 | dlclose(lib); |
| 131 | } | 144 | } |
| 132 | 145 | ||
| 133 | 146 | ||
| 134 | static void *ll_load (lua_State *L, const char *path, int seeglb) { | 147 | static void *lsys_load (lua_State *L, const char *path, int seeglb) { |
| 135 | void *lib = dlopen(path, RTLD_NOW | (seeglb ? RTLD_GLOBAL : RTLD_LOCAL)); | 148 | void *lib = dlopen(path, RTLD_NOW | (seeglb ? RTLD_GLOBAL : RTLD_LOCAL)); |
| 136 | if (lib == NULL) lua_pushstring(L, dlerror()); | 149 | if (lib == NULL) lua_pushstring(L, dlerror()); |
| 137 | return lib; | 150 | return lib; |
| 138 | } | 151 | } |
| 139 | 152 | ||
| 140 | 153 | ||
| 141 | static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { | 154 | static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) { |
| 142 | lua_CFunction f = (lua_CFunction)dlsym(lib, sym); | 155 | lua_CFunction f = (lua_CFunction)dlsym(lib, sym); |
| 143 | if (f == NULL) lua_pushstring(L, dlerror()); | 156 | if (f == NULL) lua_pushstring(L, dlerror()); |
| 144 | return f; | 157 | return f; |
| @@ -190,12 +203,12 @@ static void pusherror (lua_State *L) { | |||
| 190 | lua_pushfstring(L, "system error %d\n", error); | 203 | lua_pushfstring(L, "system error %d\n", error); |
| 191 | } | 204 | } |
| 192 | 205 | ||
| 193 | static void ll_unloadlib (void *lib) { | 206 | static void lsys_unloadlib (void *lib) { |
| 194 | FreeLibrary((HMODULE)lib); | 207 | FreeLibrary((HMODULE)lib); |
| 195 | } | 208 | } |
| 196 | 209 | ||
| 197 | 210 | ||
| 198 | static void *ll_load (lua_State *L, const char *path, int seeglb) { | 211 | static void *lsys_load (lua_State *L, const char *path, int seeglb) { |
| 199 | HMODULE lib = LoadLibraryExA(path, NULL, LUA_LLE_FLAGS); | 212 | HMODULE lib = LoadLibraryExA(path, NULL, LUA_LLE_FLAGS); |
| 200 | (void)(seeglb); /* not used: symbols are 'global' by default */ | 213 | (void)(seeglb); /* not used: symbols are 'global' by default */ |
| 201 | if (lib == NULL) pusherror(L); | 214 | if (lib == NULL) pusherror(L); |
| @@ -203,7 +216,7 @@ static void *ll_load (lua_State *L, const char *path, int seeglb) { | |||
| 203 | } | 216 | } |
| 204 | 217 | ||
| 205 | 218 | ||
| 206 | static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { | 219 | static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) { |
| 207 | lua_CFunction f = (lua_CFunction)GetProcAddress((HMODULE)lib, sym); | 220 | lua_CFunction f = (lua_CFunction)GetProcAddress((HMODULE)lib, sym); |
| 208 | if (f == NULL) pusherror(L); | 221 | if (f == NULL) pusherror(L); |
| 209 | return f; | 222 | return f; |
| @@ -226,19 +239,19 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { | |||
| 226 | #define DLMSG "dynamic libraries not enabled; check your Lua installation" | 239 | #define DLMSG "dynamic libraries not enabled; check your Lua installation" |
| 227 | 240 | ||
| 228 | 241 | ||
| 229 | static void ll_unloadlib (void *lib) { | 242 | static void lsys_unloadlib (void *lib) { |
| 230 | (void)(lib); /* not used */ | 243 | (void)(lib); /* not used */ |
| 231 | } | 244 | } |
| 232 | 245 | ||
| 233 | 246 | ||
| 234 | static void *ll_load (lua_State *L, const char *path, int seeglb) { | 247 | static void *lsys_load (lua_State *L, const char *path, int seeglb) { |
| 235 | (void)(path); (void)(seeglb); /* not used */ | 248 | (void)(path); (void)(seeglb); /* not used */ |
| 236 | lua_pushliteral(L, DLMSG); | 249 | lua_pushliteral(L, DLMSG); |
| 237 | return NULL; | 250 | return NULL; |
| 238 | } | 251 | } |
| 239 | 252 | ||
| 240 | 253 | ||
| 241 | static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { | 254 | static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) { |
| 242 | (void)(lib); (void)(sym); /* not used */ | 255 | (void)(lib); (void)(sym); /* not used */ |
| 243 | lua_pushliteral(L, DLMSG); | 256 | lua_pushliteral(L, DLMSG); |
| 244 | return NULL; | 257 | return NULL; |
| @@ -248,7 +261,10 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { | |||
| 248 | #endif | 261 | #endif |
| 249 | 262 | ||
| 250 | 263 | ||
| 251 | static void *ll_checkclib (lua_State *L, const char *path) { | 264 | /* |
| 265 | ** return registry.CLIBS[path] | ||
| 266 | */ | ||
| 267 | static void *checkclib (lua_State *L, const char *path) { | ||
| 252 | void *plib; | 268 | void *plib; |
| 253 | lua_getfield(L, LUA_REGISTRYINDEX, CLIBS); | 269 | lua_getfield(L, LUA_REGISTRYINDEX, CLIBS); |
| 254 | lua_getfield(L, -1, path); | 270 | lua_getfield(L, -1, path); |
| @@ -258,7 +274,11 @@ static void *ll_checkclib (lua_State *L, const char *path) { | |||
| 258 | } | 274 | } |
| 259 | 275 | ||
| 260 | 276 | ||
| 261 | static void ll_addtoclib (lua_State *L, const char *path, void *plib) { | 277 | /* |
| 278 | ** registry.CLIBS[path] = plib -- for queries | ||
| 279 | ** registry.CLIBS[#CLIBS + 1] = plib -- also keep a list of all libraries | ||
| 280 | */ | ||
| 281 | static void addtoclib (lua_State *L, const char *path, void *plib) { | ||
| 262 | lua_getfield(L, LUA_REGISTRYINDEX, CLIBS); | 282 | lua_getfield(L, LUA_REGISTRYINDEX, CLIBS); |
| 263 | lua_pushlightuserdata(L, plib); | 283 | lua_pushlightuserdata(L, plib); |
| 264 | lua_pushvalue(L, -1); | 284 | lua_pushvalue(L, -1); |
| @@ -269,33 +289,49 @@ static void ll_addtoclib (lua_State *L, const char *path, void *plib) { | |||
| 269 | 289 | ||
| 270 | 290 | ||
| 271 | /* | 291 | /* |
| 272 | ** __gc tag method for CLIBS table: calls 'll_unloadlib' for all lib | 292 | ** __gc tag method for CLIBS table: calls 'lsys_unloadlib' for all lib |
| 273 | ** handles in list CLIBS | 293 | ** handles in list CLIBS |
| 274 | */ | 294 | */ |
| 275 | static int gctm (lua_State *L) { | 295 | static int gctm (lua_State *L) { |
| 276 | int n = luaL_len(L, 1); | 296 | int n = luaL_len(L, 1); |
| 277 | for (; n >= 1; n--) { /* for each handle, in reverse order */ | 297 | for (; n >= 1; n--) { /* for each handle, in reverse order */ |
| 278 | lua_rawgeti(L, 1, n); /* get handle CLIBS[n] */ | 298 | lua_rawgeti(L, 1, n); /* get handle CLIBS[n] */ |
| 279 | ll_unloadlib(lua_touserdata(L, -1)); | 299 | lsys_unloadlib(lua_touserdata(L, -1)); |
| 280 | lua_pop(L, 1); /* pop handle */ | 300 | lua_pop(L, 1); /* pop handle */ |
| 281 | } | 301 | } |
| 282 | return 0; | 302 | return 0; |
| 283 | } | 303 | } |
| 284 | 304 | ||
| 285 | 305 | ||
| 286 | static int ll_loadfunc (lua_State *L, const char *path, const char *sym) { | 306 | |
| 287 | void *reg = ll_checkclib(L, path); /* check loaded C libraries */ | 307 | /* error codes for 'lookforfunc' */ |
| 308 | #define ERRLIB 1 | ||
| 309 | #define ERRFUNC 2 | ||
| 310 | |||
| 311 | /* | ||
| 312 | ** Look for a C function named 'sym' in a dynamically loaded library | ||
| 313 | ** 'path'. | ||
| 314 | ** First, check whether the library is already loaded; if not, try | ||
| 315 | ** to load it. | ||
| 316 | ** Then, if 'sym' is '*', return true (as library has been loaded). | ||
| 317 | ** Otherwise, look for symbol 'sym' in the library and push a | ||
| 318 | ** C function with that symbol. | ||
| 319 | ** Return 0 and 'true' or a function in the stack; in case of | ||
| 320 | ** errors, return an error code and an error message in the stack. | ||
| 321 | */ | ||
| 322 | static int lookforfunc (lua_State *L, const char *path, const char *sym) { | ||
| 323 | void *reg = checkclib(L, path); /* check loaded C libraries */ | ||
| 288 | if (reg == NULL) { /* must load library? */ | 324 | if (reg == NULL) { /* must load library? */ |
| 289 | reg = ll_load(L, path, *sym == '*'); | 325 | reg = lsys_load(L, path, *sym == '*'); /* global symbols if 'sym'=='*' */ |
| 290 | if (reg == NULL) return ERRLIB; /* unable to load library */ | 326 | if (reg == NULL) return ERRLIB; /* unable to load library */ |
| 291 | ll_addtoclib(L, path, reg); | 327 | addtoclib(L, path, reg); |
| 292 | } | 328 | } |
| 293 | if (*sym == '*') { /* loading only library (no function)? */ | 329 | if (*sym == '*') { /* loading only library (no function)? */ |
| 294 | lua_pushboolean(L, 1); /* return 'true' */ | 330 | lua_pushboolean(L, 1); /* return 'true' */ |
| 295 | return 0; /* no errors */ | 331 | return 0; /* no errors */ |
| 296 | } | 332 | } |
| 297 | else { | 333 | else { |
| 298 | lua_CFunction f = ll_sym(L, reg, sym); | 334 | lua_CFunction f = lsys_sym(L, reg, sym); |
| 299 | if (f == NULL) | 335 | if (f == NULL) |
| 300 | return ERRFUNC; /* unable to find function */ | 336 | return ERRFUNC; /* unable to find function */ |
| 301 | lua_pushcfunction(L, f); /* else create new function */ | 337 | lua_pushcfunction(L, f); /* else create new function */ |
| @@ -307,7 +343,7 @@ static int ll_loadfunc (lua_State *L, const char *path, const char *sym) { | |||
| 307 | static int ll_loadlib (lua_State *L) { | 343 | static int ll_loadlib (lua_State *L) { |
| 308 | const char *path = luaL_checkstring(L, 1); | 344 | const char *path = luaL_checkstring(L, 1); |
| 309 | const char *init = luaL_checkstring(L, 2); | 345 | const char *init = luaL_checkstring(L, 2); |
| 310 | int stat = ll_loadfunc(L, path, init); | 346 | int stat = lookforfunc(L, path, init); |
| 311 | if (stat == 0) /* no errors? */ | 347 | if (stat == 0) /* no errors? */ |
| 312 | return 1; /* return the loaded function */ | 348 | return 1; /* return the loaded function */ |
| 313 | else { /* error; error message is on stack top */ | 349 | else { /* error; error message is on stack top */ |
| @@ -416,21 +452,29 @@ static int searcher_Lua (lua_State *L) { | |||
| 416 | } | 452 | } |
| 417 | 453 | ||
| 418 | 454 | ||
| 455 | /* | ||
| 456 | ** Try to find a load function for module 'modname' at file 'filename'. | ||
| 457 | ** First, change '.' to '_' in 'modname'; then, if 'modname' has | ||
| 458 | ** the form X-Y (that is, it has an "ignore mark"), build a function | ||
| 459 | ** name "luaopen_X" and look for it. (For compatibility, if that | ||
| 460 | ** fails, it also tries "luaopen_Y".) If there is no ignore mark, | ||
| 461 | ** look for a function named "luaopen_modname". | ||
| 462 | */ | ||
| 419 | static int loadfunc (lua_State *L, const char *filename, const char *modname) { | 463 | static int loadfunc (lua_State *L, const char *filename, const char *modname) { |
| 420 | const char *funcname; | 464 | const char *openfunc; |
| 421 | const char *mark; | 465 | const char *mark; |
| 422 | modname = luaL_gsub(L, modname, ".", LUA_OFSEP); | 466 | modname = luaL_gsub(L, modname, ".", LUA_OFSEP); |
| 423 | mark = strchr(modname, *LUA_IGMARK); | 467 | mark = strchr(modname, *LUA_IGMARK); |
| 424 | if (mark) { | 468 | if (mark) { |
| 425 | int stat; | 469 | int stat; |
| 426 | funcname = lua_pushlstring(L, modname, mark - modname); | 470 | openfunc = lua_pushlstring(L, modname, mark - modname); |
| 427 | funcname = lua_pushfstring(L, LUA_POF"%s", funcname); | 471 | openfunc = lua_pushfstring(L, LUA_POF"%s", openfunc); |
| 428 | stat = ll_loadfunc(L, filename, funcname); | 472 | stat = lookforfunc(L, filename, openfunc); |
| 429 | if (stat != ERRFUNC) return stat; | 473 | if (stat != ERRFUNC) return stat; |
| 430 | modname = mark + 1; /* else go ahead and try old-style name */ | 474 | modname = mark + 1; /* else go ahead and try old-style name */ |
| 431 | } | 475 | } |
| 432 | funcname = lua_pushfstring(L, LUA_POF"%s", modname); | 476 | openfunc = lua_pushfstring(L, LUA_POF"%s", modname); |
| 433 | return ll_loadfunc(L, filename, funcname); | 477 | return lookforfunc(L, filename, openfunc); |
| 434 | } | 478 | } |
| 435 | 479 | ||
| 436 | 480 | ||
| @@ -686,24 +730,31 @@ static void createsearcherstable (lua_State *L) { | |||
| 686 | lua_pushcclosure(L, searchers[i], 1); | 730 | lua_pushcclosure(L, searchers[i], 1); |
| 687 | lua_rawseti(L, -2, i+1); | 731 | lua_rawseti(L, -2, i+1); |
| 688 | } | 732 | } |
| 733 | #if defined(LUA_COMPAT_LOADERS) | ||
| 734 | lua_pushvalue(L, -1); /* make a copy of 'searchers' table */ | ||
| 735 | lua_setfield(L, -3, "loaders"); /* put it in field `loaders' */ | ||
| 736 | #endif | ||
| 737 | lua_setfield(L, -2, "searchers"); /* put it in field 'searchers' */ | ||
| 689 | } | 738 | } |
| 690 | 739 | ||
| 691 | 740 | ||
| 692 | LUAMOD_API int luaopen_package (lua_State *L) { | 741 | /* |
| 693 | /* create table CLIBS to keep track of loaded C libraries */ | 742 | ** create table CLIBS to keep track of loaded C libraries, |
| 694 | luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS); | 743 | ** setting a finalizer to close all libraries when closing state. |
| 695 | lua_createtable(L, 0, 1); /* metatable for CLIBS */ | 744 | */ |
| 745 | static void createclibstable (lua_State *L) { | ||
| 746 | luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS); /* create CLIBS table */ | ||
| 747 | lua_createtable(L, 0, 1); /* create metatable for CLIBS */ | ||
| 696 | lua_pushcfunction(L, gctm); | 748 | lua_pushcfunction(L, gctm); |
| 697 | lua_setfield(L, -2, "__gc"); /* set finalizer for CLIBS table */ | 749 | lua_setfield(L, -2, "__gc"); /* set finalizer for CLIBS table */ |
| 698 | lua_setmetatable(L, -2); | 750 | lua_setmetatable(L, -2); |
| 699 | /* create `package' table */ | 751 | } |
| 700 | luaL_newlib(L, pk_funcs); | 752 | |
| 753 | |||
| 754 | LUAMOD_API int luaopen_package (lua_State *L) { | ||
| 755 | createclibstable(L); | ||
| 756 | luaL_newlib(L, pk_funcs); /* create `package' table */ | ||
| 701 | createsearcherstable(L); | 757 | createsearcherstable(L); |
| 702 | #if defined(LUA_COMPAT_LOADERS) | ||
| 703 | lua_pushvalue(L, -1); /* make a copy of 'searchers' table */ | ||
| 704 | lua_setfield(L, -3, "loaders"); /* put it in field `loaders' */ | ||
| 705 | #endif | ||
| 706 | lua_setfield(L, -2, "searchers"); /* put it in field 'searchers' */ | ||
| 707 | /* set field 'path' */ | 758 | /* set field 'path' */ |
| 708 | setpath(L, "path", LUA_PATHVARVERSION, LUA_PATH_VAR, LUA_PATH_DEFAULT); | 759 | setpath(L, "path", LUA_PATHVARVERSION, LUA_PATH_VAR, LUA_PATH_DEFAULT); |
| 709 | /* set field 'cpath' */ | 760 | /* set field 'cpath' */ |
