Mercurial > vba-clojure
diff src/lua/loadlib.c @ 11:27763b933818
raise lua sources up one level
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 11:07:39 -0600 |
parents | src/lua/src/loadlib.c@f9f4f1b99eed |
children | 44974c3e093b |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/lua/loadlib.c Sat Mar 03 11:07:39 2012 -0600 1.3 @@ -0,0 +1,666 @@ 1.4 +/* 1.5 +** $Id: loadlib.c,v 1.52.1.3 2008/08/06 13:29:28 roberto Exp $ 1.6 +** Dynamic library loader for Lua 1.7 +** See Copyright Notice in lua.h 1.8 +** 1.9 +** This module contains an implementation of loadlib for Unix systems 1.10 +** that have dlfcn, an implementation for Darwin (Mac OS X), an 1.11 +** implementation for Windows, and a stub for other systems. 1.12 +*/ 1.13 + 1.14 + 1.15 +#include <stdlib.h> 1.16 +#include <string.h> 1.17 + 1.18 + 1.19 +#define loadlib_c 1.20 +#define LUA_LIB 1.21 + 1.22 +#include "lua.h" 1.23 + 1.24 +#include "lauxlib.h" 1.25 +#include "lualib.h" 1.26 + 1.27 + 1.28 +/* prefix for open functions in C libraries */ 1.29 +#define LUA_POF "luaopen_" 1.30 + 1.31 +/* separator for open functions in C libraries */ 1.32 +#define LUA_OFSEP "_" 1.33 + 1.34 + 1.35 +#define LIBPREFIX "LOADLIB: " 1.36 + 1.37 +#define POF LUA_POF 1.38 +#define LIB_FAIL "open" 1.39 + 1.40 + 1.41 +/* error codes for ll_loadfunc */ 1.42 +#define ERRLIB 1 1.43 +#define ERRFUNC 2 1.44 + 1.45 +#define setprogdir(L) ((void)0) 1.46 + 1.47 + 1.48 +static void ll_unloadlib (void *lib); 1.49 +static void *ll_load (lua_State *L, const char *path); 1.50 +static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym); 1.51 + 1.52 + 1.53 + 1.54 +#if defined(LUA_DL_DLOPEN) 1.55 +/* 1.56 +** {======================================================================== 1.57 +** This is an implementation of loadlib based on the dlfcn interface. 1.58 +** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD, 1.59 +** NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least 1.60 +** as an emulation layer on top of native functions. 1.61 +** ========================================================================= 1.62 +*/ 1.63 + 1.64 +#include <dlfcn.h> 1.65 + 1.66 +static void ll_unloadlib (void *lib) { 1.67 + dlclose(lib); 1.68 +} 1.69 + 1.70 + 1.71 +static void *ll_load (lua_State *L, const char *path) { 1.72 + void *lib = dlopen(path, RTLD_NOW); 1.73 + if (lib == NULL) lua_pushstring(L, dlerror()); 1.74 + return lib; 1.75 +} 1.76 + 1.77 + 1.78 +static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { 1.79 + lua_CFunction f = (lua_CFunction)dlsym(lib, sym); 1.80 + if (f == NULL) lua_pushstring(L, dlerror()); 1.81 + return f; 1.82 +} 1.83 + 1.84 +/* }====================================================== */ 1.85 + 1.86 + 1.87 + 1.88 +#elif defined(LUA_DL_DLL) 1.89 +/* 1.90 +** {====================================================================== 1.91 +** This is an implementation of loadlib for Windows using native functions. 1.92 +** ======================================================================= 1.93 +*/ 1.94 + 1.95 +#include <windows.h> 1.96 + 1.97 + 1.98 +#undef setprogdir 1.99 + 1.100 +static void setprogdir (lua_State *L) { 1.101 + char buff[MAX_PATH + 1]; 1.102 + char *lb; 1.103 + DWORD nsize = sizeof(buff)/sizeof(char); 1.104 + DWORD n = GetModuleFileNameA(NULL, buff, nsize); 1.105 + if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL) 1.106 + luaL_error(L, "unable to get ModuleFileName"); 1.107 + else { 1.108 + *lb = '\0'; 1.109 + luaL_gsub(L, lua_tostring(L, -1), LUA_EXECDIR, buff); 1.110 + lua_remove(L, -2); /* remove original string */ 1.111 + } 1.112 +} 1.113 + 1.114 + 1.115 +static void pusherror (lua_State *L) { 1.116 + int error = GetLastError(); 1.117 + char buffer[128]; 1.118 + if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, 1.119 + NULL, error, 0, buffer, sizeof(buffer), NULL)) 1.120 + lua_pushstring(L, buffer); 1.121 + else 1.122 + lua_pushfstring(L, "system error %d\n", error); 1.123 +} 1.124 + 1.125 +static void ll_unloadlib (void *lib) { 1.126 + FreeLibrary((HINSTANCE)lib); 1.127 +} 1.128 + 1.129 + 1.130 +static void *ll_load (lua_State *L, const char *path) { 1.131 + HINSTANCE lib = LoadLibraryA(path); 1.132 + if (lib == NULL) pusherror(L); 1.133 + return lib; 1.134 +} 1.135 + 1.136 + 1.137 +static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { 1.138 + lua_CFunction f = (lua_CFunction)GetProcAddress((HINSTANCE)lib, sym); 1.139 + if (f == NULL) pusherror(L); 1.140 + return f; 1.141 +} 1.142 + 1.143 +/* }====================================================== */ 1.144 + 1.145 + 1.146 + 1.147 +#elif defined(LUA_DL_DYLD) 1.148 +/* 1.149 +** {====================================================================== 1.150 +** Native Mac OS X / Darwin Implementation 1.151 +** ======================================================================= 1.152 +*/ 1.153 + 1.154 +#include <mach-o/dyld.h> 1.155 + 1.156 + 1.157 +/* Mac appends a `_' before C function names */ 1.158 +#undef POF 1.159 +#define POF "_" LUA_POF 1.160 + 1.161 + 1.162 +static void pusherror (lua_State *L) { 1.163 + const char *err_str; 1.164 + const char *err_file; 1.165 + NSLinkEditErrors err; 1.166 + int err_num; 1.167 + NSLinkEditError(&err, &err_num, &err_file, &err_str); 1.168 + lua_pushstring(L, err_str); 1.169 +} 1.170 + 1.171 + 1.172 +static const char *errorfromcode (NSObjectFileImageReturnCode ret) { 1.173 + switch (ret) { 1.174 + case NSObjectFileImageInappropriateFile: 1.175 + return "file is not a bundle"; 1.176 + case NSObjectFileImageArch: 1.177 + return "library is for wrong CPU type"; 1.178 + case NSObjectFileImageFormat: 1.179 + return "bad format"; 1.180 + case NSObjectFileImageAccess: 1.181 + return "cannot access file"; 1.182 + case NSObjectFileImageFailure: 1.183 + default: 1.184 + return "unable to load library"; 1.185 + } 1.186 +} 1.187 + 1.188 + 1.189 +static void ll_unloadlib (void *lib) { 1.190 + NSUnLinkModule((NSModule)lib, NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES); 1.191 +} 1.192 + 1.193 + 1.194 +static void *ll_load (lua_State *L, const char *path) { 1.195 + NSObjectFileImage img; 1.196 + NSObjectFileImageReturnCode ret; 1.197 + /* this would be a rare case, but prevents crashing if it happens */ 1.198 + if(!_dyld_present()) { 1.199 + lua_pushliteral(L, "dyld not present"); 1.200 + return NULL; 1.201 + } 1.202 + ret = NSCreateObjectFileImageFromFile(path, &img); 1.203 + if (ret == NSObjectFileImageSuccess) { 1.204 + NSModule mod = NSLinkModule(img, path, NSLINKMODULE_OPTION_PRIVATE | 1.205 + NSLINKMODULE_OPTION_RETURN_ON_ERROR); 1.206 + NSDestroyObjectFileImage(img); 1.207 + if (mod == NULL) pusherror(L); 1.208 + return mod; 1.209 + } 1.210 + lua_pushstring(L, errorfromcode(ret)); 1.211 + return NULL; 1.212 +} 1.213 + 1.214 + 1.215 +static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { 1.216 + NSSymbol nss = NSLookupSymbolInModule((NSModule)lib, sym); 1.217 + if (nss == NULL) { 1.218 + lua_pushfstring(L, "symbol " LUA_QS " not found", sym); 1.219 + return NULL; 1.220 + } 1.221 + return (lua_CFunction)NSAddressOfSymbol(nss); 1.222 +} 1.223 + 1.224 +/* }====================================================== */ 1.225 + 1.226 + 1.227 + 1.228 +#else 1.229 +/* 1.230 +** {====================================================== 1.231 +** Fallback for other systems 1.232 +** ======================================================= 1.233 +*/ 1.234 + 1.235 +#undef LIB_FAIL 1.236 +#define LIB_FAIL "absent" 1.237 + 1.238 + 1.239 +#define DLMSG "dynamic libraries not enabled; check your Lua installation" 1.240 + 1.241 + 1.242 +static void ll_unloadlib (void *lib) { 1.243 + (void)lib; /* to avoid warnings */ 1.244 +} 1.245 + 1.246 + 1.247 +static void *ll_load (lua_State *L, const char *path) { 1.248 + (void)path; /* to avoid warnings */ 1.249 + lua_pushliteral(L, DLMSG); 1.250 + return NULL; 1.251 +} 1.252 + 1.253 + 1.254 +static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { 1.255 + (void)lib; (void)sym; /* to avoid warnings */ 1.256 + lua_pushliteral(L, DLMSG); 1.257 + return NULL; 1.258 +} 1.259 + 1.260 +/* }====================================================== */ 1.261 +#endif 1.262 + 1.263 + 1.264 + 1.265 +static void **ll_register (lua_State *L, const char *path) { 1.266 + void **plib; 1.267 + lua_pushfstring(L, "%s%s", LIBPREFIX, path); 1.268 + lua_gettable(L, LUA_REGISTRYINDEX); /* check library in registry? */ 1.269 + if (!lua_isnil(L, -1)) /* is there an entry? */ 1.270 + plib = (void **)lua_touserdata(L, -1); 1.271 + else { /* no entry yet; create one */ 1.272 + lua_pop(L, 1); 1.273 + plib = (void **)lua_newuserdata(L, sizeof(const void *)); 1.274 + *plib = NULL; 1.275 + luaL_getmetatable(L, "_LOADLIB"); 1.276 + lua_setmetatable(L, -2); 1.277 + lua_pushfstring(L, "%s%s", LIBPREFIX, path); 1.278 + lua_pushvalue(L, -2); 1.279 + lua_settable(L, LUA_REGISTRYINDEX); 1.280 + } 1.281 + return plib; 1.282 +} 1.283 + 1.284 + 1.285 +/* 1.286 +** __gc tag method: calls library's `ll_unloadlib' function with the lib 1.287 +** handle 1.288 +*/ 1.289 +static int gctm (lua_State *L) { 1.290 + void **lib = (void **)luaL_checkudata(L, 1, "_LOADLIB"); 1.291 + if (*lib) ll_unloadlib(*lib); 1.292 + *lib = NULL; /* mark library as closed */ 1.293 + return 0; 1.294 +} 1.295 + 1.296 + 1.297 +static int ll_loadfunc (lua_State *L, const char *path, const char *sym) { 1.298 + void **reg = ll_register(L, path); 1.299 + if (*reg == NULL) *reg = ll_load(L, path); 1.300 + if (*reg == NULL) 1.301 + return ERRLIB; /* unable to load library */ 1.302 + else { 1.303 + lua_CFunction f = ll_sym(L, *reg, sym); 1.304 + if (f == NULL) 1.305 + return ERRFUNC; /* unable to find function */ 1.306 + lua_pushcfunction(L, f); 1.307 + return 0; /* return function */ 1.308 + } 1.309 +} 1.310 + 1.311 + 1.312 +static int ll_loadlib (lua_State *L) { 1.313 + const char *path = luaL_checkstring(L, 1); 1.314 + const char *init = luaL_checkstring(L, 2); 1.315 + int stat = ll_loadfunc(L, path, init); 1.316 + if (stat == 0) /* no errors? */ 1.317 + return 1; /* return the loaded function */ 1.318 + else { /* error; error message is on stack top */ 1.319 + lua_pushnil(L); 1.320 + lua_insert(L, -2); 1.321 + lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init"); 1.322 + return 3; /* return nil, error message, and where */ 1.323 + } 1.324 +} 1.325 + 1.326 + 1.327 + 1.328 +/* 1.329 +** {====================================================== 1.330 +** 'require' function 1.331 +** ======================================================= 1.332 +*/ 1.333 + 1.334 + 1.335 +static int readable (const char *filename) { 1.336 + FILE *f = fopen(filename, "r"); /* try to open file */ 1.337 + if (f == NULL) return 0; /* open failed */ 1.338 + fclose(f); 1.339 + return 1; 1.340 +} 1.341 + 1.342 + 1.343 +static const char *pushnexttemplate (lua_State *L, const char *path) { 1.344 + const char *l; 1.345 + while (*path == *LUA_PATHSEP) path++; /* skip separators */ 1.346 + if (*path == '\0') return NULL; /* no more templates */ 1.347 + l = strchr(path, *LUA_PATHSEP); /* find next separator */ 1.348 + if (l == NULL) l = path + strlen(path); 1.349 + lua_pushlstring(L, path, l - path); /* template */ 1.350 + return l; 1.351 +} 1.352 + 1.353 + 1.354 +static const char *findfile (lua_State *L, const char *name, 1.355 + const char *pname) { 1.356 + const char *path; 1.357 + name = luaL_gsub(L, name, ".", LUA_DIRSEP); 1.358 + lua_getfield(L, LUA_ENVIRONINDEX, pname); 1.359 + path = lua_tostring(L, -1); 1.360 + if (path == NULL) 1.361 + luaL_error(L, LUA_QL("package.%s") " must be a string", pname); 1.362 + lua_pushliteral(L, ""); /* error accumulator */ 1.363 + while ((path = pushnexttemplate(L, path)) != NULL) { 1.364 + const char *filename; 1.365 + filename = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name); 1.366 + lua_remove(L, -2); /* remove path template */ 1.367 + if (readable(filename)) /* does file exist and is readable? */ 1.368 + return filename; /* return that file name */ 1.369 + lua_pushfstring(L, "\n\tno file " LUA_QS, filename); 1.370 + lua_remove(L, -2); /* remove file name */ 1.371 + lua_concat(L, 2); /* add entry to possible error message */ 1.372 + } 1.373 + return NULL; /* not found */ 1.374 +} 1.375 + 1.376 + 1.377 +static void loaderror (lua_State *L, const char *filename) { 1.378 + luaL_error(L, "error loading module " LUA_QS " from file " LUA_QS ":\n\t%s", 1.379 + lua_tostring(L, 1), filename, lua_tostring(L, -1)); 1.380 +} 1.381 + 1.382 + 1.383 +static int loader_Lua (lua_State *L) { 1.384 + const char *filename; 1.385 + const char *name = luaL_checkstring(L, 1); 1.386 + filename = findfile(L, name, "path"); 1.387 + if (filename == NULL) return 1; /* library not found in this path */ 1.388 + if (luaL_loadfile(L, filename) != 0) 1.389 + loaderror(L, filename); 1.390 + return 1; /* library loaded successfully */ 1.391 +} 1.392 + 1.393 + 1.394 +static const char *mkfuncname (lua_State *L, const char *modname) { 1.395 + const char *funcname; 1.396 + const char *mark = strchr(modname, *LUA_IGMARK); 1.397 + if (mark) modname = mark + 1; 1.398 + funcname = luaL_gsub(L, modname, ".", LUA_OFSEP); 1.399 + funcname = lua_pushfstring(L, POF"%s", funcname); 1.400 + lua_remove(L, -2); /* remove 'gsub' result */ 1.401 + return funcname; 1.402 +} 1.403 + 1.404 + 1.405 +static int loader_C (lua_State *L) { 1.406 + const char *funcname; 1.407 + const char *name = luaL_checkstring(L, 1); 1.408 + const char *filename = findfile(L, name, "cpath"); 1.409 + if (filename == NULL) return 1; /* library not found in this path */ 1.410 + funcname = mkfuncname(L, name); 1.411 + if (ll_loadfunc(L, filename, funcname) != 0) 1.412 + loaderror(L, filename); 1.413 + return 1; /* library loaded successfully */ 1.414 +} 1.415 + 1.416 + 1.417 +static int loader_Croot (lua_State *L) { 1.418 + const char *funcname; 1.419 + const char *filename; 1.420 + const char *name = luaL_checkstring(L, 1); 1.421 + const char *p = strchr(name, '.'); 1.422 + int stat; 1.423 + if (p == NULL) return 0; /* is root */ 1.424 + lua_pushlstring(L, name, p - name); 1.425 + filename = findfile(L, lua_tostring(L, -1), "cpath"); 1.426 + if (filename == NULL) return 1; /* root not found */ 1.427 + funcname = mkfuncname(L, name); 1.428 + if ((stat = ll_loadfunc(L, filename, funcname)) != 0) { 1.429 + if (stat != ERRFUNC) loaderror(L, filename); /* real error */ 1.430 + lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS, 1.431 + name, filename); 1.432 + return 1; /* function not found */ 1.433 + } 1.434 + return 1; 1.435 +} 1.436 + 1.437 + 1.438 +static int loader_preload (lua_State *L) { 1.439 + const char *name = luaL_checkstring(L, 1); 1.440 + lua_getfield(L, LUA_ENVIRONINDEX, "preload"); 1.441 + if (!lua_istable(L, -1)) 1.442 + luaL_error(L, LUA_QL("package.preload") " must be a table"); 1.443 + lua_getfield(L, -1, name); 1.444 + if (lua_isnil(L, -1)) /* not found? */ 1.445 + lua_pushfstring(L, "\n\tno field package.preload['%s']", name); 1.446 + return 1; 1.447 +} 1.448 + 1.449 + 1.450 +static const int sentinel_ = 0; 1.451 +#define sentinel ((void *)&sentinel_) 1.452 + 1.453 + 1.454 +static int ll_require (lua_State *L) { 1.455 + const char *name = luaL_checkstring(L, 1); 1.456 + int i; 1.457 + lua_settop(L, 1); /* _LOADED table will be at index 2 */ 1.458 + lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); 1.459 + lua_getfield(L, 2, name); 1.460 + if (lua_toboolean(L, -1)) { /* is it there? */ 1.461 + if (lua_touserdata(L, -1) == sentinel) /* check loops */ 1.462 + luaL_error(L, "loop or previous error loading module " LUA_QS, name); 1.463 + return 1; /* package is already loaded */ 1.464 + } 1.465 + /* else must load it; iterate over available loaders */ 1.466 + lua_getfield(L, LUA_ENVIRONINDEX, "loaders"); 1.467 + if (!lua_istable(L, -1)) 1.468 + luaL_error(L, LUA_QL("package.loaders") " must be a table"); 1.469 + lua_pushliteral(L, ""); /* error message accumulator */ 1.470 + for (i=1; ; i++) { 1.471 + lua_rawgeti(L, -2, i); /* get a loader */ 1.472 + if (lua_isnil(L, -1)) 1.473 + luaL_error(L, "module " LUA_QS " not found:%s", 1.474 + name, lua_tostring(L, -2)); 1.475 + lua_pushstring(L, name); 1.476 + lua_call(L, 1, 1); /* call it */ 1.477 + if (lua_isfunction(L, -1)) /* did it find module? */ 1.478 + break; /* module loaded successfully */ 1.479 + else if (lua_isstring(L, -1)) /* loader returned error message? */ 1.480 + lua_concat(L, 2); /* accumulate it */ 1.481 + else 1.482 + lua_pop(L, 1); 1.483 + } 1.484 + lua_pushlightuserdata(L, sentinel); 1.485 + lua_setfield(L, 2, name); /* _LOADED[name] = sentinel */ 1.486 + lua_pushstring(L, name); /* pass name as argument to module */ 1.487 + lua_call(L, 1, 1); /* run loaded module */ 1.488 + if (!lua_isnil(L, -1)) /* non-nil return? */ 1.489 + lua_setfield(L, 2, name); /* _LOADED[name] = returned value */ 1.490 + lua_getfield(L, 2, name); 1.491 + if (lua_touserdata(L, -1) == sentinel) { /* module did not set a value? */ 1.492 + lua_pushboolean(L, 1); /* use true as result */ 1.493 + lua_pushvalue(L, -1); /* extra copy to be returned */ 1.494 + lua_setfield(L, 2, name); /* _LOADED[name] = true */ 1.495 + } 1.496 + return 1; 1.497 +} 1.498 + 1.499 +/* }====================================================== */ 1.500 + 1.501 + 1.502 + 1.503 +/* 1.504 +** {====================================================== 1.505 +** 'module' function 1.506 +** ======================================================= 1.507 +*/ 1.508 + 1.509 + 1.510 +static void setfenv (lua_State *L) { 1.511 + lua_Debug ar; 1.512 + if (lua_getstack(L, 1, &ar) == 0 || 1.513 + lua_getinfo(L, "f", &ar) == 0 || /* get calling function */ 1.514 + lua_iscfunction(L, -1)) 1.515 + luaL_error(L, LUA_QL("module") " not called from a Lua function"); 1.516 + lua_pushvalue(L, -2); 1.517 + lua_setfenv(L, -2); 1.518 + lua_pop(L, 1); 1.519 +} 1.520 + 1.521 + 1.522 +static void dooptions (lua_State *L, int n) { 1.523 + int i; 1.524 + for (i = 2; i <= n; i++) { 1.525 + lua_pushvalue(L, i); /* get option (a function) */ 1.526 + lua_pushvalue(L, -2); /* module */ 1.527 + lua_call(L, 1, 0); 1.528 + } 1.529 +} 1.530 + 1.531 + 1.532 +static void modinit (lua_State *L, const char *modname) { 1.533 + const char *dot; 1.534 + lua_pushvalue(L, -1); 1.535 + lua_setfield(L, -2, "_M"); /* module._M = module */ 1.536 + lua_pushstring(L, modname); 1.537 + lua_setfield(L, -2, "_NAME"); 1.538 + dot = strrchr(modname, '.'); /* look for last dot in module name */ 1.539 + if (dot == NULL) dot = modname; 1.540 + else dot++; 1.541 + /* set _PACKAGE as package name (full module name minus last part) */ 1.542 + lua_pushlstring(L, modname, dot - modname); 1.543 + lua_setfield(L, -2, "_PACKAGE"); 1.544 +} 1.545 + 1.546 + 1.547 +static int ll_module (lua_State *L) { 1.548 + const char *modname = luaL_checkstring(L, 1); 1.549 + int loaded = lua_gettop(L) + 1; /* index of _LOADED table */ 1.550 + lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); 1.551 + lua_getfield(L, loaded, modname); /* get _LOADED[modname] */ 1.552 + if (!lua_istable(L, -1)) { /* not found? */ 1.553 + lua_pop(L, 1); /* remove previous result */ 1.554 + /* try global variable (and create one if it does not exist) */ 1.555 + if (luaL_findtable(L, LUA_GLOBALSINDEX, modname, 1) != NULL) 1.556 + return luaL_error(L, "name conflict for module " LUA_QS, modname); 1.557 + lua_pushvalue(L, -1); 1.558 + lua_setfield(L, loaded, modname); /* _LOADED[modname] = new table */ 1.559 + } 1.560 + /* check whether table already has a _NAME field */ 1.561 + lua_getfield(L, -1, "_NAME"); 1.562 + if (!lua_isnil(L, -1)) /* is table an initialized module? */ 1.563 + lua_pop(L, 1); 1.564 + else { /* no; initialize it */ 1.565 + lua_pop(L, 1); 1.566 + modinit(L, modname); 1.567 + } 1.568 + lua_pushvalue(L, -1); 1.569 + setfenv(L); 1.570 + dooptions(L, loaded - 1); 1.571 + return 0; 1.572 +} 1.573 + 1.574 + 1.575 +static int ll_seeall (lua_State *L) { 1.576 + luaL_checktype(L, 1, LUA_TTABLE); 1.577 + if (!lua_getmetatable(L, 1)) { 1.578 + lua_createtable(L, 0, 1); /* create new metatable */ 1.579 + lua_pushvalue(L, -1); 1.580 + lua_setmetatable(L, 1); 1.581 + } 1.582 + lua_pushvalue(L, LUA_GLOBALSINDEX); 1.583 + lua_setfield(L, -2, "__index"); /* mt.__index = _G */ 1.584 + return 0; 1.585 +} 1.586 + 1.587 + 1.588 +/* }====================================================== */ 1.589 + 1.590 + 1.591 + 1.592 +/* auxiliary mark (for internal use) */ 1.593 +#define AUXMARK "\1" 1.594 + 1.595 +static void setpath (lua_State *L, const char *fieldname, const char *envname, 1.596 + const char *def) { 1.597 + const char *path = getenv(envname); 1.598 + if (path == NULL) /* no environment variable? */ 1.599 + lua_pushstring(L, def); /* use default */ 1.600 + else { 1.601 + /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */ 1.602 + path = luaL_gsub(L, path, LUA_PATHSEP LUA_PATHSEP, 1.603 + LUA_PATHSEP AUXMARK LUA_PATHSEP); 1.604 + luaL_gsub(L, path, AUXMARK, def); 1.605 + lua_remove(L, -2); 1.606 + } 1.607 + setprogdir(L); 1.608 + lua_setfield(L, -2, fieldname); 1.609 +} 1.610 + 1.611 + 1.612 +static const luaL_Reg pk_funcs[] = { 1.613 + {"loadlib", ll_loadlib}, 1.614 + {"seeall", ll_seeall}, 1.615 + {NULL, NULL} 1.616 +}; 1.617 + 1.618 + 1.619 +static const luaL_Reg ll_funcs[] = { 1.620 + {"module", ll_module}, 1.621 + {"require", ll_require}, 1.622 + {NULL, NULL} 1.623 +}; 1.624 + 1.625 + 1.626 +static const lua_CFunction loaders[] = 1.627 + {loader_preload, loader_Lua, loader_C, loader_Croot, NULL}; 1.628 + 1.629 + 1.630 +LUALIB_API int luaopen_package (lua_State *L) { 1.631 + int i; 1.632 + /* create new type _LOADLIB */ 1.633 + luaL_newmetatable(L, "_LOADLIB"); 1.634 + lua_pushcfunction(L, gctm); 1.635 + lua_setfield(L, -2, "__gc"); 1.636 + /* create `package' table */ 1.637 + luaL_register(L, LUA_LOADLIBNAME, pk_funcs); 1.638 +#if defined(LUA_COMPAT_LOADLIB) 1.639 + lua_getfield(L, -1, "loadlib"); 1.640 + lua_setfield(L, LUA_GLOBALSINDEX, "loadlib"); 1.641 +#endif 1.642 + lua_pushvalue(L, -1); 1.643 + lua_replace(L, LUA_ENVIRONINDEX); 1.644 + /* create `loaders' table */ 1.645 + lua_createtable(L, 0, sizeof(loaders)/sizeof(loaders[0]) - 1); 1.646 + /* fill it with pre-defined loaders */ 1.647 + for (i=0; loaders[i] != NULL; i++) { 1.648 + lua_pushcfunction(L, loaders[i]); 1.649 + lua_rawseti(L, -2, i+1); 1.650 + } 1.651 + lua_setfield(L, -2, "loaders"); /* put it in field `loaders' */ 1.652 + setpath(L, "path", LUA_PATH, LUA_PATH_DEFAULT); /* set field `path' */ 1.653 + setpath(L, "cpath", LUA_CPATH, LUA_CPATH_DEFAULT); /* set field `cpath' */ 1.654 + /* store config information */ 1.655 + lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATHSEP "\n" LUA_PATH_MARK "\n" 1.656 + LUA_EXECDIR "\n" LUA_IGMARK); 1.657 + lua_setfield(L, -2, "config"); 1.658 + /* set field `loaded' */ 1.659 + luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 2); 1.660 + lua_setfield(L, -2, "loaded"); 1.661 + /* set field `preload' */ 1.662 + lua_newtable(L); 1.663 + lua_setfield(L, -2, "preload"); 1.664 + lua_pushvalue(L, LUA_GLOBALSINDEX); 1.665 + luaL_register(L, NULL, ll_funcs); /* open lib into global table */ 1.666 + lua_pop(L, 1); 1.667 + return 1; /* return 'package' table */ 1.668 +} 1.669 +