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' */ |