ljx

FORK: LuaJIT with native 5.2 and 5.3 support
git clone https://git.neptards.moe/neptards/ljx.git
Log | Files | Refs | README

lib_package.c (20128B)


      1 /*
      2 ** Package library.
      3 ** Copyright (C) 2005-2016 Mike Pall. See Copyright Notice in luajit.h
      4 **
      5 ** Lua 5.2 port
      6 ** Copyright (C) 2014 Karel Tuma. See Copyright Notice in luajit.h
      7 **
      8 ** Major portions taken verbatim or adapted from the Lua 5.2 interpreter.
      9 ** Copyright (C) 1994-2014 Lua.org, PUC-Rio. See Copyright Notice in lua.h
     10 */
     11 
     12 #define lib_package_c
     13 #define LUA_LIB
     14 
     15 #include "lua.h"
     16 #include "lauxlib.h"
     17 #include "lualib.h"
     18 
     19 #include "lj_obj.h"
     20 #include "lj_err.h"
     21 #include "lj_lib.h"
     22 
     23 /* ------------------------------------------------------------------------ */
     24 #define LUA_PATHSUFFIX		"_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR
     25 #define LUA_PATHVERSION		LUA_PATH LUA_PATHSUFFIX
     26 #define LUA_CPATHVERSION	LUA_CPATH LUA_PATHSUFFIX
     27 #define CLIBS		"_CLIBS"
     28 #if !defined(LUA_CSUBSEP)
     29 #define LUA_CSUBSEP		LUA_DIRSEP
     30 #endif
     31 
     32 #if !defined(LUA_LSUBSEP)
     33 #define LUA_LSUBSEP		LUA_DIRSEP
     34 #endif
     35 
     36 
     37 
     38 /* Error codes for ll_loadfunc. */
     39 #define PACKAGE_ERR_LIB		1
     40 #define PACKAGE_ERR_FUNC	2
     41 #define PACKAGE_ERR_LOAD	3
     42 
     43 /* Redefined in platform specific part. */
     44 #define PACKAGE_LIB_FAIL	"open"
     45 #define setprogdir(L)		((void)0)
     46 
     47 /* Symbol name prefixes. */
     48 #define SYMPREFIX_CF		"luaopen_%s"
     49 #define SYMPREFIX_BC		"luaJIT_BC_%s"
     50 
     51 #if LJ_TARGET_DLOPEN
     52 
     53 #include <dlfcn.h>
     54 
     55 static void ll_unloadlib(void *lib)
     56 {
     57   dlclose(lib);
     58 }
     59 
     60 static void *ll_load(lua_State *L, const char *path, int gl)
     61 {
     62   void *lib = dlopen(path, RTLD_NOW | (gl ? RTLD_GLOBAL : RTLD_LOCAL));
     63   if (lib == NULL) lua_pushstring(L, dlerror());
     64   return lib;
     65 }
     66 
     67 static lua_CFunction ll_sym(lua_State *L, void *lib, const char *sym)
     68 {
     69   lua_CFunction f = (lua_CFunction)dlsym(lib, sym);
     70   if (f == NULL) lua_pushstring(L, dlerror());
     71   return f;
     72 }
     73 
     74 static const char *ll_bcsym(void *lib, const char *sym)
     75 {
     76 #if defined(RTLD_DEFAULT)
     77   if (lib == NULL) lib = RTLD_DEFAULT;
     78 #elif LJ_TARGET_OSX || LJ_TARGET_BSD
     79   if (lib == NULL) lib = (void *)(intptr_t)-2;
     80 #endif
     81   return (const char *)dlsym(lib, sym);
     82 }
     83 
     84 #elif LJ_TARGET_WINDOWS
     85 
     86 #define WIN32_LEAN_AND_MEAN
     87 #include <windows.h>
     88 
     89 #ifndef GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
     90 #define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS  4
     91 #define GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT  2
     92 BOOL WINAPI GetModuleHandleExA(DWORD, LPCSTR, HMODULE*);
     93 #endif
     94 
     95 #undef setprogdir
     96 
     97 static void setprogdir(lua_State *L)
     98 {
     99   char buff[MAX_PATH + 1];
    100   char *lb;
    101   DWORD nsize = sizeof(buff);
    102   DWORD n = GetModuleFileNameA(NULL, buff, nsize);
    103   if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL) {
    104     luaL_error(L, "unable to get ModuleFileName");
    105   } else {
    106     *lb = '\0';
    107     luaL_gsub(L, lua_tostring(L, -1), LUA_EXECDIR, buff);
    108     lua_remove(L, -2);  /* remove original string */
    109   }
    110 }
    111 
    112 static void pusherror(lua_State *L)
    113 {
    114   DWORD error = GetLastError();
    115 #if LJ_TARGET_XBOXONE
    116   wchar_t wbuffer[128];
    117   char buffer[128*2];
    118   if (FormatMessageW(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
    119       NULL, error, 0, wbuffer, sizeof(wbuffer)/sizeof(wchar_t), NULL) &&
    120       WideCharToMultiByte(CP_ACP, 0, wbuffer, 128, buffer, 128*2, NULL, NULL))
    121 #else
    122   char buffer[128];
    123   if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
    124       NULL, error, 0, buffer, sizeof(buffer), NULL))
    125 #endif
    126     lua_pushstring(L, buffer);
    127   else
    128     lua_pushfstring(L, "system error %d\n", error);
    129 }
    130 
    131 static void ll_unloadlib(void *lib)
    132 {
    133   FreeLibrary((HINSTANCE)lib);
    134 }
    135 
    136 static void *ll_load(lua_State *L, const char *path, int gl)
    137 {
    138   HINSTANCE lib = LoadLibraryExA(path, NULL, 0);
    139   if (lib == NULL) pusherror(L);
    140   UNUSED(gl);
    141   return lib;
    142 }
    143 
    144 static lua_CFunction ll_sym(lua_State *L, void *lib, const char *sym)
    145 {
    146   lua_CFunction f = (lua_CFunction)GetProcAddress((HINSTANCE)lib, sym);
    147   if (f == NULL) pusherror(L);
    148   return f;
    149 }
    150 
    151 static const char *ll_bcsym(void *lib, const char *sym)
    152 {
    153   if (lib) {
    154     return (const char *)GetProcAddress((HINSTANCE)lib, sym);
    155   } else {
    156     HINSTANCE h = GetModuleHandleA(NULL);
    157     const char *p = (const char *)GetProcAddress(h, sym);
    158     if (p == NULL && GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS|GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
    159 					(const char *)ll_bcsym, &h))
    160       p = (const char *)GetProcAddress(h, sym);
    161     return p;
    162   }
    163 }
    164 
    165 #else
    166 
    167 #undef PACKAGE_LIB_FAIL
    168 #define PACKAGE_LIB_FAIL	"absent"
    169 
    170 #define DLMSG	"dynamic libraries not enabled; no support for target OS"
    171 
    172 static void ll_unloadlib(void *lib)
    173 {
    174   UNUSED(lib);
    175 }
    176 
    177 static void *ll_load(lua_State *L, const char *path, int gl)
    178 {
    179   UNUSED(path); UNUSED(gl);
    180   lua_pushliteral(L, DLMSG);
    181   return NULL;
    182 }
    183 
    184 static lua_CFunction ll_sym(lua_State *L, void *lib, const char *sym)
    185 {
    186   UNUSED(lib); UNUSED(sym);
    187   lua_pushliteral(L, DLMSG);
    188   return NULL;
    189 }
    190 
    191 static const char *ll_bcsym(void *lib, const char *sym)
    192 {
    193   UNUSED(lib); UNUSED(sym);
    194   return NULL;
    195 }
    196 
    197 #endif
    198 
    199 /* ------------------------------------------------------------------------ */
    200 
    201 static void *ll_checkclib (lua_State *L, const char *path) {
    202   void *plib;
    203   lua_getfield(L, LUA_REGISTRYINDEX, CLIBS);
    204   lua_getfield(L, -1, path);
    205   plib = lua_touserdata(L, -1);  /* plib = CLIBS[path] */
    206   lua_pop(L, 2);  /* pop CLIBS table and 'plib' */
    207   return plib;
    208 }
    209 
    210 
    211 static void ll_addtoclib (lua_State *L, const char *path, void *plib) {
    212   lua_getfield(L, LUA_REGISTRYINDEX, CLIBS);
    213   lua_pushlightuserdata(L, plib);
    214   lua_pushvalue(L, -1);
    215   lua_setfield(L, -3, path);  /* CLIBS[path] = plib */
    216   lua_rawseti(L, -2, luaL_len(L, -2) + 1);  /* CLIBS[#CLIBS + 1] = plib */
    217   lua_pop(L, 1);  /* pop CLIBS table */
    218 }
    219 
    220 
    221 static const char *mksymname(lua_State *L, const char *modname,
    222 			     const char *prefix)
    223 {
    224   const char *funcname;
    225   const char *mark = strchr(modname, *LUA_IGMARK);
    226   if (mark) modname = mark + 1;
    227   funcname = luaL_gsub(L, modname, ".", "_");
    228   funcname = lua_pushfstring(L, prefix, funcname);
    229   lua_remove(L, -2);  /* remove 'gsub' result */
    230   return funcname;
    231 }
    232 
    233 static int ll_loadfunc(lua_State *L, const char *path, const char *name, int r)
    234 {
    235   void *reg = ll_checkclib(L, path);  /* check loaded C libraries */
    236   if (reg == NULL) {  /* must load library? */
    237     reg = ll_load(L, path, *name == '*');
    238     if (reg == NULL) return PACKAGE_ERR_LIB;
    239     ll_addtoclib(L, path, reg);
    240   }
    241   if (*name == '*') {  /* loading only library (no function)? */
    242     lua_pushboolean(L, 1);  /* return 'true' */
    243     return 0;  /* no errors */
    244   }
    245   else {
    246     const char *sym = r ? name : mksymname(L, name, SYMPREFIX_CF);
    247     lua_CFunction f = ll_sym(L, reg, sym);
    248     if (f) {
    249       lua_pushcfunction(L, f);
    250       return 0;
    251     }
    252     if (!r) {
    253       const char *bcdata = ll_bcsym(reg, mksymname(L, name, SYMPREFIX_BC));
    254       lua_pop(L, 1);
    255       if (bcdata) {
    256 	if (luaL_loadbuffer(L, bcdata, LJ_MAX_BUF, name) != 0)
    257 	  return PACKAGE_ERR_LOAD;
    258 	return 0;
    259       }
    260     }
    261     return PACKAGE_ERR_FUNC;  /* Unable to find function. */
    262   }
    263 }
    264 
    265 static int lj_cf_package_loadlib(lua_State *L)
    266 {
    267   const char *path = luaL_checkstring(L, 1);
    268   const char *init = luaL_checkstring(L, 2);
    269   int st = ll_loadfunc(L, path, init, 1);
    270   if (st == 0) {  /* no errors? */
    271     return 1;  /* return the loaded function */
    272   } else {  /* error; error message is on stack top */
    273     lua_pushnil(L);
    274     lua_insert(L, -2);
    275     lua_pushstring(L, (st == PACKAGE_ERR_LIB) ?  PACKAGE_LIB_FAIL : "init");
    276     return 3;  /* return nil, error message, and where */
    277   }
    278 }
    279 
    280 /* ------------------------------------------------------------------------ */
    281 
    282 static int readable(const char *filename)
    283 {
    284   FILE *f = fopen(filename, "r");  /* try to open file */
    285   if (f == NULL) return 0;  /* open failed */
    286   fclose(f);
    287   return 1;
    288 }
    289 
    290 static const char *pushnexttemplate(lua_State *L, const char *path)
    291 {
    292   const char *l;
    293   while (*path == *LUA_PATHSEP) path++;  /* skip separators */
    294   if (*path == '\0') return NULL;  /* no more templates */
    295   l = strchr(path, *LUA_PATHSEP);  /* find next separator */
    296   if (l == NULL) l = path + strlen(path);
    297   lua_pushlstring(L, path, (size_t)(l - path));  /* template */
    298   return l;
    299 }
    300 
    301 static const char *searchpath (lua_State *L, const char *name,
    302 			       const char *path, const char *sep,
    303 			       const char *dirsep)
    304 {
    305   luaL_Buffer msg;  /* to build error message */
    306   luaL_buffinit(L, &msg);
    307   if (*sep != '\0')  /* non-empty separator? */
    308     name = luaL_gsub(L, name, sep, dirsep);  /* replace it by 'dirsep' */
    309   while ((path = pushnexttemplate(L, path)) != NULL) {
    310     const char *filename = luaL_gsub(L, lua_tostring(L, -1),
    311 				     LUA_PATH_MARK, name);
    312     lua_remove(L, -2);  /* remove path template */
    313     if (readable(filename))  /* does file exist and is readable? */
    314       return filename;  /* return that file name */
    315     lua_pushfstring(L, "\n\tno file " LUA_QS, filename);
    316     lua_remove(L, -2);  /* remove file name */
    317     luaL_addvalue(&msg);  /* concatenate error msg. entry */
    318   }
    319   luaL_pushresult(&msg);  /* create error message */
    320   return NULL;  /* not found */
    321 }
    322 
    323 static int lj_cf_package_searchpath(lua_State *L)
    324 {
    325   const char *f = searchpath(L, luaL_checkstring(L, 1),
    326 				luaL_checkstring(L, 2),
    327 				luaL_optstring(L, 3, "."),
    328 				luaL_optstring(L, 4, LUA_DIRSEP));
    329   if (f != NULL) {
    330     return 1;
    331   } else {  /* error message is on top of the stack */
    332     lua_pushnil(L);
    333     lua_insert(L, -2);
    334     return 2;  /* return nil + error message */
    335   }
    336 }
    337 
    338 static const char *findfile(lua_State *L, const char *name,
    339 			    const char *pname, const char *dirsep)
    340 {
    341   const char *path;
    342   lua_getfield(L, lua_upvalueindex(1), pname);  /* will be at index 3 */
    343   path = lua_tostring(L, -1);
    344   if (path == NULL)
    345     luaL_error(L, LUA_QL("package.%s") " must be a string", pname);
    346   return searchpath(L, name, path, ".", dirsep);
    347 }
    348 
    349 static int checkload (lua_State *L, int stat, const char *filename) {
    350   if (stat) {  /* module loaded successfully? */
    351     lua_pushstring(L, filename);  /* will be 2nd argument to module */
    352     return 2;  /* return open function and file name */
    353   }
    354   else
    355     return luaL_error(L, "error loading module " LUA_QS
    356                          " from file " LUA_QS ":\n\t%s",
    357                           lua_tostring(L, 1), filename, lua_tostring(L, -1));
    358 }
    359 
    360 static int lj_cf_package_loader_lua(lua_State *L)
    361 {
    362   const char *filename;
    363   const char *name = luaL_checkstring(L, 1);
    364   filename = findfile(L, name, "path", LUA_LSUBSEP);
    365   if (filename == NULL) return 1;  /* module not found in this path */
    366   return checkload(L, (luaL_loadfile(L, filename) == LUA_OK), filename);
    367 }
    368 
    369 static int lj_cf_package_loader_c(lua_State *L)
    370 {
    371   const char *name = luaL_checkstring(L, 1);
    372   const char *filename = findfile(L, name, "cpath", LUA_CSUBSEP);
    373   if (filename == NULL) return 1;  /* library not found in this path */
    374   return checkload(L, (ll_loadfunc(L, filename, name, 0) == 0), filename);
    375 }
    376 
    377 static int lj_cf_package_loader_croot(lua_State *L)
    378 {
    379   const char *filename;
    380   const char *name = luaL_checkstring(L, 1);
    381   const char *p = strchr(name, '.');
    382   int st;
    383   if (p == NULL) return 0;  /* is root */
    384   lua_pushlstring(L, name, (size_t)(p - name));
    385   filename = findfile(L, lua_tostring(L, -1), "cpath", LUA_CSUBSEP);
    386   if (filename == NULL) return 1;  /* root not found */
    387   if ((st = ll_loadfunc(L, filename, name, 0)) != 0) {
    388     if (st != PACKAGE_ERR_FUNC)
    389       return checkload(L, 0, filename);  /* real error */
    390     lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS,
    391 		    name, filename);
    392     return 1;  /* function not found */
    393   }
    394   lua_pushstring(L, filename);  /* will be 2nd argument to module */
    395   return 2;
    396 }
    397 
    398 static int lj_cf_package_loader_preload(lua_State *L)
    399 {
    400   const char *name = luaL_checkstring(L, 1);
    401   lua_getfield(L, LUA_REGISTRYINDEX, "_PRELOAD");
    402   lua_getfield(L, -1, name);
    403   if (lua_isnil(L, -1)) {  /* Not found? */
    404     const char *bcname = mksymname(L, name, SYMPREFIX_BC);
    405     const char *bcdata = ll_bcsym(NULL, bcname);
    406     if (bcdata == NULL || luaL_loadbuffer(L, bcdata, LJ_MAX_BUF, name) != 0)
    407       lua_pushfstring(L, "\n\tno field package.preload['%s']", name);
    408   }
    409   return 1;
    410 }
    411 
    412 /* ------------------------------------------------------------------------ */
    413 static void findloader (lua_State *L, const char *name) {
    414   int i;
    415   luaL_Buffer msg;  /* to build error message */
    416   luaL_buffinit(L, &msg);
    417   lua_getfield(L, lua_upvalueindex(1), "searchers");  /* will be at index 3 */
    418   if (!lua_istable(L, 3))
    419     luaL_error(L, LUA_QL("package.searchers") " must be a table");
    420   /*  iterate over available searchers to find a loader */
    421   for (i = 1; ; i++) {
    422     lua_rawgeti(L, 3, i);  /* get a searcher */
    423     if (lua_isnil(L, -1)) {  /* no more searchers? */
    424       lua_pop(L, 1);  /* remove nil */
    425       luaL_pushresult(&msg);  /* create error message */
    426       luaL_error(L, "module " LUA_QS " not found:%s",
    427                     name, lua_tostring(L, -1));
    428     }
    429     lua_pushstring(L, name);
    430     lua_call(L, 1, 2);  /* call it */
    431     if (lua_isfunction(L, -2))  /* did it find a loader? */
    432       return;  /* module loader found */
    433     else if (lua_isstring(L, -2)) {  /* searcher returned error message? */
    434       lua_pop(L, 1);  /* remove extra return */
    435       luaL_addvalue(&msg);  /* concatenate error message */
    436     }
    437     else
    438       lua_pop(L, 2);  /* remove both returns */
    439   }
    440 }
    441 
    442 
    443 
    444 static int lj_cf_package_require(lua_State *L)
    445 {
    446   const char *name = luaL_checkstring(L, 1);
    447   lua_settop(L, 1);  /* _LOADED table will be at index 2 */
    448   lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
    449   lua_getfield(L, 2, name);
    450   if (lua_toboolean(L, -1))  /* is it there? */
    451     return 1;  /* package is already loaded */
    452   /* else must load package */
    453   lua_pop(L, 1);  /* remove 'getfield' result */
    454   findloader(L, name);
    455   lua_pushstring(L, name);  /* pass name as argument to module loader */
    456   lua_insert(L, -2);  /* name is 1st argument (before search data) */
    457   lua_call(L, 2, 1);  /* run loader to load module */
    458   if (!lua_isnil(L, -1))  /* non-nil return? */
    459     lua_setfield(L, 2, name);  /* _LOADED[name] = returned value */
    460   lua_getfield(L, 2, name);
    461   if (lua_isnil(L, -1)) {   /* module did not set a value? */
    462     lua_pushboolean(L, 1);  /* use true as result */
    463     lua_pushvalue(L, -1);  /* extra copy to be returned */
    464     lua_setfield(L, 2, name);  /* _LOADED[name] = true */
    465   }
    466   lj_lib_checkfpu(L);
    467   return 1;
    468 }
    469 
    470 /* ------------------------------------------------------------------------ */
    471 
    472 static void setfenv(lua_State *L)
    473 {
    474   lua_Debug ar;
    475   if (lua_getstack(L, 1, &ar) == 0 ||
    476       lua_getinfo(L, "f", &ar) == 0 ||  /* get calling function */
    477       lua_iscfunction(L, -1))
    478     luaL_error(L, LUA_QL("module") " not called from a Lua function");
    479   lua_pushvalue(L, -2);
    480   lua_setfenv(L, -2);
    481   lua_pop(L, 1);
    482 }
    483 
    484 static void dooptions(lua_State *L, int n)
    485 {
    486   int i;
    487   for (i = 2; i <= n; i++) {
    488     if (lua_isfunction(L, i)) {  /* avoid 'calling' extra info. */
    489       lua_pushvalue(L, i);  /* get option (a function) */
    490       lua_pushvalue(L, -2);  /* module */
    491       lua_call(L, 1, 0);
    492     }
    493   }
    494 }
    495 
    496 static void modinit(lua_State *L, const char *modname)
    497 {
    498   const char *dot;
    499   lua_pushvalue(L, -1);
    500   lua_setfield(L, -2, "_M");  /* module._M = module */
    501   lua_pushstring(L, modname);
    502   lua_setfield(L, -2, "_NAME");
    503   dot = strrchr(modname, '.');  /* look for last dot in module name */
    504   if (dot == NULL) dot = modname; else dot++;
    505   /* set _PACKAGE as package name (full module name minus last part) */
    506   lua_pushlstring(L, modname, (size_t)(dot - modname));
    507   lua_setfield(L, -2, "_PACKAGE");
    508 }
    509 
    510 static int lj_cf_package_module(lua_State *L)
    511 {
    512   const char *modname = luaL_checkstring(L, 1);
    513   int lastarg = lua_gettop(L);  /* index of _LOADED table */
    514   luaL_pushmodule(L, modname, 1);  /* get/create module table */
    515   /* check whether table already has a _NAME field */
    516   lua_getfield(L, -1, "_NAME");
    517   if (!lua_isnil(L, -1)) {  /* is table an initialized module? */
    518     lua_pop(L, 1);
    519   } else {  /* no; initialize it */
    520     lua_pop(L, 1);
    521     modinit(L, modname);
    522   }
    523   lua_pushvalue(L, -1);
    524   setfenv(L);
    525   dooptions(L, lastarg);
    526   return 0;
    527 }
    528 
    529 static int lj_cf_package_seeall(lua_State *L)
    530 {
    531   luaL_checktype(L, 1, LUA_TTABLE);
    532   if (!lua_getmetatable(L, 1)) {
    533     lua_createtable(L, 0, 1); /* create new metatable */
    534     lua_pushvalue(L, -1);
    535     lua_setmetatable(L, 1);
    536   }
    537   lua_pushvalue(L, LUA_GLOBALSINDEX);
    538   lua_setfield(L, -2, "__index");  /* mt.__index = _G */
    539   return 0;
    540 }
    541 
    542 /*
    543 ** __gc tag method for CLIBS table: calls 'll_unloadlib' for all lib
    544 ** handles in list CLIBS
    545 */
    546 static int gctm (lua_State *L) {
    547   int n = luaL_len(L, 1);
    548   for (; n >= 1; n--) {  /* for each handle, in reverse order */
    549     lua_rawgeti(L, 1, n);  /* get handle CLIBS[n] */
    550     ll_unloadlib(lua_touserdata(L, -1));
    551     lua_pop(L, 1);  /* pop handle */
    552   }
    553   return 0;
    554 }
    555 
    556 
    557 /* ------------------------------------------------------------------------ */
    558 
    559 #define AUXMARK		"\1"
    560 
    561 static void setpath(lua_State *L, const char *fieldname, const char *envname1,
    562                     const char *envname2,
    563 		    const char *def, int noenv)
    564 {
    565   const char *path =
    566 #if LJ_TARGET_CONSOLE
    567   NULL;
    568   UNUSED(envname1); UNUSED(envname2);
    569 #else
    570   getenv(envname1);
    571   if (path == NULL)  /* no environment variable? */
    572     path = getenv(envname2);  /* try alternative name */
    573 #endif
    574   if (path == NULL || noenv)  /* no environment variable? */
    575     lua_pushstring(L, def);  /* use default */
    576   else {
    577     /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */
    578     path = luaL_gsub(L, path, LUA_PATHSEP LUA_PATHSEP,
    579                               LUA_PATHSEP AUXMARK LUA_PATHSEP);
    580     luaL_gsub(L, path, AUXMARK, def);
    581     lua_remove(L, -2);
    582   }
    583   setprogdir(L);
    584   lua_setfield(L, -2, fieldname);
    585 }
    586 
    587 static const luaL_Reg package_lib[] = {
    588   { "loadlib",	lj_cf_package_loadlib },
    589   { "searchpath",  lj_cf_package_searchpath },
    590   { "seeall",	lj_cf_package_seeall },
    591   { NULL, NULL }
    592 };
    593 
    594 static const luaL_Reg package_global[] = {
    595   { "module",	lj_cf_package_module },
    596   { "require",	lj_cf_package_require },
    597   { NULL, NULL }
    598 };
    599 
    600 static void createsearcherstable (lua_State *L) {
    601   static const lua_CFunction searchers[] =
    602   {
    603     lj_cf_package_loader_preload,
    604     lj_cf_package_loader_lua,
    605     lj_cf_package_loader_c,
    606     lj_cf_package_loader_croot,
    607     NULL
    608   };
    609   int i;
    610   /* create 'searchers' table */
    611   lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0);
    612   /* fill it with pre-defined searchers */
    613   for (i=0; searchers[i] != NULL; i++) {
    614     lua_pushvalue(L, -2);  /* set 'package' as upvalue for all searchers */
    615     lua_pushcclosure(L, searchers[i], 1);
    616     lua_rawseti(L, -2, i+1);
    617   }
    618 }
    619 
    620 LUALIB_API int luaopen_package(lua_State *L)
    621 {
    622   int noenv;
    623   /* create table CLIBS to keep track of loaded C libraries */
    624   luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS);
    625   lua_createtable(L, 0, 1);  /* metatable for CLIBS */
    626   lua_pushcfunction(L, gctm);
    627   lua_setfield(L, -2, "__gc");  /* set finalizer for CLIBS table */
    628   lua_setmetatable(L, -2);
    629   /* create `package' table */
    630   luaL_newlib(L, package_lib);
    631   createsearcherstable(L);
    632   lua_pushvalue(L, -1);  /* make a copy of 'searchers' table */
    633   lua_setfield(L, -3, "loaders");  /* put it in field `loaders' */
    634   lua_setfield(L, -2, "searchers");  /* put it in field 'searchers' */
    635   /* check for noenv */
    636   lua_getfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");
    637   noenv = lua_toboolean(L, -1);
    638   lua_pop(L, 1);
    639   /* set field 'path' */
    640   setpath(L, "path", LUA_PATHVERSION, LUA_PATH, LUA_PATH_DEFAULT, noenv);
    641   /* set field 'cpath' */
    642   setpath(L, "cpath", LUA_CPATHVERSION, LUA_CPATH, LUA_CPATH_DEFAULT, noenv);
    643   /* store config information */
    644   lua_pushliteral(L, LUA_PATH_CONFIG);
    645   lua_setfield(L, -2, "config");
    646   /* set field `loaded' */
    647   luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED");
    648   lua_setfield(L, -2, "loaded");
    649   /* set field `preload' */
    650   luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD");
    651   lua_setfield(L, -2, "preload");
    652   lua_pushglobaltable(L);
    653   lua_pushvalue(L, -2);  /* set 'package' as upvalue for next lib */
    654   luaL_setfuncs(L, package_global, 1);  /* open lib into global table */
    655   lua_pop(L, 1);  /* pop global table */
    656   return 1;  /* return 'package' table */
    657 }
    658