aboutsummaryrefslogtreecommitdiff
path: root/loadlib.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2014-07-28 14:47:53 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2014-07-28 14:47:53 -0300
commit255d59ed5e2743b97626eff57444f44defc39270 (patch)
tree1c240056965f157fdffd0b715d5d138b9d56219d /loadlib.c
parent925d1b59f931ad3cf23e67f39f6771b9a9e06f5f (diff)
downloadlua-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.c141
1 files changed, 96 insertions, 45 deletions
diff --git a/loadlib.c b/loadlib.c
index 08190cb5..c85ef405 100644
--- a/loadlib.c
+++ b/loadlib.c
@@ -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*/
111static void ll_unloadlib (void *lib); 106
112static void *ll_load (lua_State *L, const char *path, int seeglb); 107/*
113static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym); 108** unload library 'lib'
109*/
110static 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*/
118static 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*/
125static 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
129static void ll_unloadlib (void *lib) { 142static void lsys_unloadlib (void *lib) {
130 dlclose(lib); 143 dlclose(lib);
131} 144}
132 145
133 146
134static void *ll_load (lua_State *L, const char *path, int seeglb) { 147static 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
141static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { 154static 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
193static void ll_unloadlib (void *lib) { 206static void lsys_unloadlib (void *lib) {
194 FreeLibrary((HMODULE)lib); 207 FreeLibrary((HMODULE)lib);
195} 208}
196 209
197 210
198static void *ll_load (lua_State *L, const char *path, int seeglb) { 211static 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
206static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { 219static 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
229static void ll_unloadlib (void *lib) { 242static void lsys_unloadlib (void *lib) {
230 (void)(lib); /* not used */ 243 (void)(lib); /* not used */
231} 244}
232 245
233 246
234static void *ll_load (lua_State *L, const char *path, int seeglb) { 247static 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
241static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { 254static 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
251static void *ll_checkclib (lua_State *L, const char *path) { 264/*
265** return registry.CLIBS[path]
266*/
267static 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
261static 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*/
281static 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*/
275static int gctm (lua_State *L) { 295static 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
286static 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*/
322static 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) {
307static int ll_loadlib (lua_State *L) { 343static 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*/
419static int loadfunc (lua_State *L, const char *filename, const char *modname) { 463static 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
692LUAMOD_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*/
745static 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
754LUAMOD_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' */