2
** $Id: loadlib.c,v 1.111 2012/05/30 12:33:44 roberto Exp $
3
** Dynamic library loader for Lua
4
** See Copyright Notice in lua.h
6
** This module contains an implementation of loadlib for Unix systems
7
** that have dlfcn, an implementation for Windows, and a stub for other
13
** if needed, includes windows header before everything else
34
** LUA_PATH and LUA_CPATH are the names of the environment
35
** variables that Lua check to set its paths.
37
#if !defined(LUA_PATH)
38
#define LUA_PATH "LUA_PATH"
41
#if !defined(LUA_CPATH)
42
#define LUA_CPATH "LUA_CPATH"
45
#define LUA_PATHSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR
47
#define LUA_PATHVERSION LUA_PATH LUA_PATHSUFFIX
48
#define LUA_CPATHVERSION LUA_CPATH LUA_PATHSUFFIX
51
** LUA_PATH_SEP is the character that separates templates in a path.
52
** LUA_PATH_MARK is the string that marks the substitution points in a
54
** LUA_EXEC_DIR in a Windows path is replaced by the executable's
56
** LUA_IGMARK is a mark to ignore all before it when building the
57
** luaopen_ function name.
59
#if !defined (LUA_PATH_SEP)
60
#define LUA_PATH_SEP ";"
62
#if !defined (LUA_PATH_MARK)
63
#define LUA_PATH_MARK "?"
65
#if !defined (LUA_EXEC_DIR)
66
#define LUA_EXEC_DIR "!"
68
#if !defined (LUA_IGMARK)
69
#define LUA_IGMARK "-"
74
** LUA_CSUBSEP is the character that replaces dots in submodule names
75
** when searching for a C loader.
76
** LUA_LSUBSEP is the character that replaces dots in submodule names
77
** when searching for a Lua loader.
79
#if !defined(LUA_CSUBSEP)
80
#define LUA_CSUBSEP LUA_DIRSEP
83
#if !defined(LUA_LSUBSEP)
84
#define LUA_LSUBSEP LUA_DIRSEP
88
/* prefix for open functions in C libraries */
89
#define LUA_POF "luaopen_"
91
/* separator for open functions in C libraries */
95
/* table (in the registry) that keeps handles for all loaded C libraries */
96
#define CLIBS "_CLIBS"
98
#define LIB_FAIL "open"
101
/* error codes for ll_loadfunc */
105
#define setprogdir(L) ((void)0)
109
** system-dependent functions
111
static void ll_unloadlib (void *lib);
112
static void *ll_load (lua_State *L, const char *path, int seeglb);
113
static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym);
117
#if defined(LUA_USE_DLOPEN)
119
** {========================================================================
120
** This is an implementation of loadlib based on the dlfcn interface.
121
** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD,
122
** NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least
123
** as an emulation layer on top of native functions.
124
** =========================================================================
129
static void ll_unloadlib (void *lib) {
134
static void *ll_load (lua_State *L, const char *path, int seeglb) {
135
void *lib = dlopen(path, RTLD_NOW | (seeglb ? RTLD_GLOBAL : RTLD_LOCAL));
136
if (lib == NULL) lua_pushstring(L, dlerror());
141
static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
142
lua_CFunction f = (lua_CFunction)dlsym(lib, sym);
143
if (f == NULL) lua_pushstring(L, dlerror());
147
/* }====================================================== */
151
#elif defined(LUA_DL_DLL)
153
** {======================================================================
154
** This is an implementation of loadlib for Windows using native functions.
155
** =======================================================================
161
** optional flags for LoadLibraryEx
163
#if !defined(LUA_LLE_FLAGS)
164
#define LUA_LLE_FLAGS 0
168
static void setprogdir (lua_State *L) {
169
char buff[MAX_PATH + 1];
171
DWORD nsize = sizeof(buff)/sizeof(char);
172
DWORD n = GetModuleFileNameA(NULL, buff, nsize);
173
if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL)
174
luaL_error(L, "unable to get ModuleFileName");
177
luaL_gsub(L, lua_tostring(L, -1), LUA_EXEC_DIR, buff);
178
lua_remove(L, -2); /* remove original string */
183
static void pusherror (lua_State *L) {
184
int error = GetLastError();
186
if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
187
NULL, error, 0, buffer, sizeof(buffer)/sizeof(char), NULL))
188
lua_pushstring(L, buffer);
190
lua_pushfstring(L, "system error %d\n", error);
193
static void ll_unloadlib (void *lib) {
194
FreeLibrary((HMODULE)lib);
198
static void *ll_load (lua_State *L, const char *path, int seeglb) {
199
HMODULE lib = LoadLibraryExA(path, NULL, LUA_LLE_FLAGS);
200
(void)(seeglb); /* not used: symbols are 'global' by default */
201
if (lib == NULL) pusherror(L);
206
static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
207
lua_CFunction f = (lua_CFunction)GetProcAddress((HMODULE)lib, sym);
208
if (f == NULL) pusherror(L);
212
/* }====================================================== */
217
** {======================================================
218
** Fallback for other systems
219
** =======================================================
223
#define LIB_FAIL "absent"
226
#define DLMSG "dynamic libraries not enabled; check your Lua installation"
229
static void ll_unloadlib (void *lib) {
230
(void)(lib); /* not used */
234
static void *ll_load (lua_State *L, const char *path, int seeglb) {
235
(void)(path); (void)(seeglb); /* not used */
236
lua_pushliteral(L, DLMSG);
241
static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
242
(void)(lib); (void)(sym); /* not used */
243
lua_pushliteral(L, DLMSG);
247
/* }====================================================== */
251
static void *ll_checkclib (lua_State *L, const char *path) {
253
lua_getfield(L, LUA_REGISTRYINDEX, CLIBS);
254
lua_getfield(L, -1, path);
255
plib = lua_touserdata(L, -1); /* plib = CLIBS[path] */
256
lua_pop(L, 2); /* pop CLIBS table and 'plib' */
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 */
272
** __gc tag method for CLIBS table: calls 'll_unloadlib' for all lib
273
** handles in list CLIBS
275
static int gctm (lua_State *L) {
276
int n = luaL_len(L, 1);
277
for (; n >= 1; n--) { /* for each handle, in reverse order */
278
lua_rawgeti(L, 1, n); /* get handle CLIBS[n] */
279
ll_unloadlib(lua_touserdata(L, -1));
280
lua_pop(L, 1); /* pop handle */
286
static int ll_loadfunc (lua_State *L, const char *path, const char *sym) {
287
void *reg = ll_checkclib(L, path); /* check loaded C libraries */
288
if (reg == NULL) { /* must 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);
293
if (*sym == '*') { /* loading only library (no function)? */
294
lua_pushboolean(L, 1); /* return 'true' */
295
return 0; /* no errors */
298
lua_CFunction f = ll_sym(L, reg, sym);
300
return ERRFUNC; /* unable to find function */
301
lua_pushcfunction(L, f); /* else create new function */
302
return 0; /* no errors */
307
static int ll_loadlib (lua_State *L) {
308
const char *path = luaL_checkstring(L, 1);
309
const char *init = luaL_checkstring(L, 2);
310
int stat = ll_loadfunc(L, path, init);
311
if (stat == 0) /* no errors? */
312
return 1; /* return the loaded function */
313
else { /* error; error message is on stack top */
316
lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init");
317
return 3; /* return nil, error message, and where */
324
** {======================================================
325
** 'require' function
326
** =======================================================
330
static int readable (const char *filename) {
331
FILE *f = fopen(filename, "r"); /* try to open file */
332
if (f == NULL) return 0; /* open failed */
338
static const char *pushnexttemplate (lua_State *L, const char *path) {
340
while (*path == *LUA_PATH_SEP) path++; /* skip separators */
341
if (*path == '\0') return NULL; /* no more templates */
342
l = strchr(path, *LUA_PATH_SEP); /* find next separator */
343
if (l == NULL) l = path + strlen(path);
344
lua_pushlstring(L, path, l - path); /* template */
349
static const char *searchpath (lua_State *L, const char *name,
352
const char *dirsep) {
353
luaL_Buffer msg; /* to build error message */
354
luaL_buffinit(L, &msg);
355
if (*sep != '\0') /* non-empty separator? */
356
name = luaL_gsub(L, name, sep, dirsep); /* replace it by 'dirsep' */
357
while ((path = pushnexttemplate(L, path)) != NULL) {
358
const char *filename = luaL_gsub(L, lua_tostring(L, -1),
359
LUA_PATH_MARK, name);
360
lua_remove(L, -2); /* remove path template */
361
if (readable(filename)) /* does file exist and is readable? */
362
return filename; /* return that file name */
363
lua_pushfstring(L, "\n\tno file " LUA_QS, filename);
364
lua_remove(L, -2); /* remove file name */
365
luaL_addvalue(&msg); /* concatenate error msg. entry */
367
luaL_pushresult(&msg); /* create error message */
368
return NULL; /* not found */
372
static int ll_searchpath (lua_State *L) {
373
const char *f = searchpath(L, luaL_checkstring(L, 1),
374
luaL_checkstring(L, 2),
375
luaL_optstring(L, 3, "."),
376
luaL_optstring(L, 4, LUA_DIRSEP));
377
if (f != NULL) return 1;
378
else { /* error message is on top of the stack */
381
return 2; /* return nil + error message */
386
static const char *findfile (lua_State *L, const char *name,
388
const char *dirsep) {
390
lua_getfield(L, lua_upvalueindex(1), pname);
391
path = lua_tostring(L, -1);
393
luaL_error(L, LUA_QL("package.%s") " must be a string", pname);
394
return searchpath(L, name, path, ".", dirsep);
398
static int checkload (lua_State *L, int stat, const char *filename) {
399
if (stat) { /* module loaded successfully? */
400
lua_pushstring(L, filename); /* will be 2nd argument to module */
401
return 2; /* return open function and file name */
404
return luaL_error(L, "error loading module " LUA_QS
405
" from file " LUA_QS ":\n\t%s",
406
lua_tostring(L, 1), filename, lua_tostring(L, -1));
410
static int searcher_Lua (lua_State *L) {
411
const char *filename;
412
const char *name = luaL_checkstring(L, 1);
413
filename = findfile(L, name, "path", LUA_LSUBSEP);
414
if (filename == NULL) return 1; /* module not found in this path */
415
return checkload(L, (luaL_loadfile(L, filename) == LUA_OK), filename);
419
static int loadfunc (lua_State *L, const char *filename, const char *modname) {
420
const char *funcname;
422
modname = luaL_gsub(L, modname, ".", LUA_OFSEP);
423
mark = strchr(modname, *LUA_IGMARK);
426
funcname = lua_pushlstring(L, modname, mark - modname);
427
funcname = lua_pushfstring(L, LUA_POF"%s", funcname);
428
stat = ll_loadfunc(L, filename, funcname);
429
if (stat != ERRFUNC) return stat;
430
modname = mark + 1; /* else go ahead and try old-style name */
432
funcname = lua_pushfstring(L, LUA_POF"%s", modname);
433
return ll_loadfunc(L, filename, funcname);
437
static int searcher_C (lua_State *L) {
438
const char *name = luaL_checkstring(L, 1);
439
const char *filename = findfile(L, name, "cpath", LUA_CSUBSEP);
440
if (filename == NULL) return 1; /* module not found in this path */
441
return checkload(L, (loadfunc(L, filename, name) == 0), filename);
445
static int searcher_Croot (lua_State *L) {
446
const char *filename;
447
const char *name = luaL_checkstring(L, 1);
448
const char *p = strchr(name, '.');
450
if (p == NULL) return 0; /* is root */
451
lua_pushlstring(L, name, p - name);
452
filename = findfile(L, lua_tostring(L, -1), "cpath", LUA_CSUBSEP);
453
if (filename == NULL) return 1; /* root not found */
454
if ((stat = loadfunc(L, filename, name)) != 0) {
456
return checkload(L, 0, filename); /* real error */
457
else { /* open function not found */
458
lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS,
463
lua_pushstring(L, filename); /* will be 2nd argument to module */
468
static int searcher_preload (lua_State *L) {
469
const char *name = luaL_checkstring(L, 1);
470
lua_getfield(L, LUA_REGISTRYINDEX, "_PRELOAD");
471
lua_getfield(L, -1, name);
472
if (lua_isnil(L, -1)) /* not found? */
473
lua_pushfstring(L, "\n\tno field package.preload['%s']", name);
478
static void findloader (lua_State *L, const char *name) {
480
luaL_Buffer msg; /* to build error message */
481
luaL_buffinit(L, &msg);
482
lua_getfield(L, lua_upvalueindex(1), "searchers"); /* will be at index 3 */
483
if (!lua_istable(L, 3))
484
luaL_error(L, LUA_QL("package.searchers") " must be a table");
485
/* iterate over available searchers to find a loader */
487
lua_rawgeti(L, 3, i); /* get a searcher */
488
if (lua_isnil(L, -1)) { /* no more searchers? */
489
lua_pop(L, 1); /* remove nil */
490
luaL_pushresult(&msg); /* create error message */
491
luaL_error(L, "module " LUA_QS " not found:%s",
492
name, lua_tostring(L, -1));
494
lua_pushstring(L, name);
495
lua_call(L, 1, 2); /* call it */
496
if (lua_isfunction(L, -2)) /* did it find a loader? */
497
return; /* module loader found */
498
else if (lua_isstring(L, -2)) { /* searcher returned error message? */
499
lua_pop(L, 1); /* remove extra return */
500
luaL_addvalue(&msg); /* concatenate error message */
503
lua_pop(L, 2); /* remove both returns */
508
static int ll_require (lua_State *L) {
509
const char *name = luaL_checkstring(L, 1);
510
lua_settop(L, 1); /* _LOADED table will be at index 2 */
511
lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
512
lua_getfield(L, 2, name); /* _LOADED[name] */
513
if (lua_toboolean(L, -1)) /* is it there? */
514
return 1; /* package is already loaded */
515
/* else must load package */
516
lua_pop(L, 1); /* remove 'getfield' result */
518
lua_pushstring(L, name); /* pass name as argument to module loader */
519
lua_insert(L, -2); /* name is 1st argument (before search data) */
520
lua_call(L, 2, 1); /* run loader to load module */
521
if (!lua_isnil(L, -1)) /* non-nil return? */
522
lua_setfield(L, 2, name); /* _LOADED[name] = returned value */
523
lua_getfield(L, 2, name);
524
if (lua_isnil(L, -1)) { /* module did not set a value? */
525
lua_pushboolean(L, 1); /* use true as result */
526
lua_pushvalue(L, -1); /* extra copy to be returned */
527
lua_setfield(L, 2, name); /* _LOADED[name] = true */
532
/* }====================================================== */
537
** {======================================================
539
** =======================================================
541
#if defined(LUA_COMPAT_MODULE)
544
** changes the environment variable of calling function
546
static void set_env (lua_State *L) {
548
if (lua_getstack(L, 1, &ar) == 0 ||
549
lua_getinfo(L, "f", &ar) == 0 || /* get calling function */
550
lua_iscfunction(L, -1))
551
luaL_error(L, LUA_QL("module") " not called from a Lua function");
552
lua_pushvalue(L, -2); /* copy new environment table to top */
553
lua_setupvalue(L, -2, 1);
554
lua_pop(L, 1); /* remove function */
558
static void dooptions (lua_State *L, int n) {
560
for (i = 2; i <= n; i++) {
561
if (lua_isfunction(L, i)) { /* avoid 'calling' extra info. */
562
lua_pushvalue(L, i); /* get option (a function) */
563
lua_pushvalue(L, -2); /* module */
570
static void modinit (lua_State *L, const char *modname) {
572
lua_pushvalue(L, -1);
573
lua_setfield(L, -2, "_M"); /* module._M = module */
574
lua_pushstring(L, modname);
575
lua_setfield(L, -2, "_NAME");
576
dot = strrchr(modname, '.'); /* look for last dot in module name */
577
if (dot == NULL) dot = modname;
579
/* set _PACKAGE as package name (full module name minus last part) */
580
lua_pushlstring(L, modname, dot - modname);
581
lua_setfield(L, -2, "_PACKAGE");
585
static int ll_module (lua_State *L) {
586
const char *modname = luaL_checkstring(L, 1);
587
int lastarg = lua_gettop(L); /* last parameter */
588
luaL_pushmodule(L, modname, 1); /* get/create module table */
589
/* check whether table already has a _NAME field */
590
lua_getfield(L, -1, "_NAME");
591
if (!lua_isnil(L, -1)) /* is table an initialized module? */
593
else { /* no; initialize it */
597
lua_pushvalue(L, -1);
599
dooptions(L, lastarg);
604
static int ll_seeall (lua_State *L) {
605
luaL_checktype(L, 1, LUA_TTABLE);
606
if (!lua_getmetatable(L, 1)) {
607
lua_createtable(L, 0, 1); /* create new metatable */
608
lua_pushvalue(L, -1);
609
lua_setmetatable(L, 1);
611
lua_pushglobaltable(L);
612
lua_setfield(L, -2, "__index"); /* mt.__index = _G */
617
/* }====================================================== */
621
/* auxiliary mark (for internal use) */
626
** return registry.LUA_NOENV as a boolean
628
static int noenv (lua_State *L) {
630
lua_getfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");
631
b = lua_toboolean(L, -1);
632
lua_pop(L, 1); /* remove value */
637
static void setpath (lua_State *L, const char *fieldname, const char *envname1,
638
const char *envname2, const char *def) {
639
const char *path = getenv(envname1);
640
if (path == NULL) /* no environment variable? */
641
path = getenv(envname2); /* try alternative name */
642
if (path == NULL || noenv(L)) /* no environment variable? */
643
lua_pushstring(L, def); /* use default */
645
/* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */
646
path = luaL_gsub(L, path, LUA_PATH_SEP LUA_PATH_SEP,
647
LUA_PATH_SEP AUXMARK LUA_PATH_SEP);
648
luaL_gsub(L, path, AUXMARK, def);
652
lua_setfield(L, -2, fieldname);
656
static const luaL_Reg pk_funcs[] = {
657
{"loadlib", ll_loadlib},
658
{"searchpath", ll_searchpath},
659
#if defined(LUA_COMPAT_MODULE)
660
{"seeall", ll_seeall},
666
static const luaL_Reg ll_funcs[] = {
667
#if defined(LUA_COMPAT_MODULE)
668
{"module", ll_module},
670
{"require", ll_require},
675
static void createsearcherstable (lua_State *L) {
676
static const lua_CFunction searchers[] =
677
{searcher_preload, searcher_Lua, searcher_C, searcher_Croot, NULL};
679
/* create 'searchers' table */
680
lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0);
681
/* fill it with pre-defined searchers */
682
for (i=0; searchers[i] != NULL; i++) {
683
lua_pushvalue(L, -2); /* set 'package' as upvalue for all searchers */
684
lua_pushcclosure(L, searchers[i], 1);
685
lua_rawseti(L, -2, i+1);
690
LUAMOD_API int luaopen_package (lua_State *L) {
691
/* create table CLIBS to keep track of loaded C libraries */
692
luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS);
693
lua_createtable(L, 0, 1); /* metatable for CLIBS */
694
lua_pushcfunction(L, gctm);
695
lua_setfield(L, -2, "__gc"); /* set finalizer for CLIBS table */
696
lua_setmetatable(L, -2);
697
/* create `package' table */
698
luaL_newlib(L, pk_funcs);
699
createsearcherstable(L);
700
#if defined(LUA_COMPAT_LOADERS)
701
lua_pushvalue(L, -1); /* make a copy of 'searchers' table */
702
lua_setfield(L, -3, "loaders"); /* put it in field `loaders' */
704
lua_setfield(L, -2, "searchers"); /* put it in field 'searchers' */
705
/* set field 'path' */
706
setpath(L, "path", LUA_PATHVERSION, LUA_PATH, LUA_PATH_DEFAULT);
707
/* set field 'cpath' */
708
setpath(L, "cpath", LUA_CPATHVERSION, LUA_CPATH, LUA_CPATH_DEFAULT);
709
/* store config information */
710
lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATH_SEP "\n" LUA_PATH_MARK "\n"
711
LUA_EXEC_DIR "\n" LUA_IGMARK "\n");
712
lua_setfield(L, -2, "config");
713
/* set field `loaded' */
714
luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED");
715
lua_setfield(L, -2, "loaded");
716
/* set field `preload' */
717
luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD");
718
lua_setfield(L, -2, "preload");
719
lua_pushglobaltable(L);
720
lua_pushvalue(L, -2); /* set 'package' as upvalue for next lib */
721
luaL_setfuncs(L, ll_funcs, 1); /* open lib into global table */
722
lua_pop(L, 1); /* pop global table */
723
return 1; /* return 'package' table */