Home | History | Annotate | Download | only in src
      1 /*
      2 ** $Id: loadlib.c,v 1.111.1.1 2013/04/12 18:48:47 roberto Exp $
      3 ** Dynamic library loader for Lua
      4 ** See Copyright Notice in lua.h
      5 **
      6 ** This module contains an implementation of loadlib for Unix systems
      7 ** that have dlfcn, an implementation for Windows, and a stub for other
      8 ** systems.
      9 */
     10 
     11 
     12 /*
     13 ** if needed, includes windows header before everything else
     14 */
     15 #if defined(_WIN32) && !defined(UEFI_C_SOURCE) && !defined(_DOS_WATCOM)
     16 #include <windows.h>
     17 #endif
     18 
     19 
     20 #include <stdlib.h>
     21 #include <string.h>
     22 
     23 
     24 #define loadlib_c
     25 #define LUA_LIB
     26 
     27 #include "lua.h"
     28 
     29 #include "lauxlib.h"
     30 #include "lualib.h"
     31 
     32 
     33 /*
     34 ** LUA_PATH and LUA_CPATH are the names of the environment
     35 ** variables that Lua check to set its paths.
     36 */
     37 #if !defined(LUA_PATH)
     38 #define LUA_PATH    "LUA_PATH"
     39 #endif
     40 
     41 #if !defined(LUA_CPATH)
     42 #define LUA_CPATH   "LUA_CPATH"
     43 #endif
     44 
     45 #define LUA_PATHSUFFIX      "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR
     46 
     47 #define LUA_PATHVERSION     LUA_PATH LUA_PATHSUFFIX
     48 #define LUA_CPATHVERSION    LUA_CPATH LUA_PATHSUFFIX
     49 
     50 /*
     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
     53 ** template.
     54 ** LUA_EXEC_DIR in a Windows path is replaced by the executable's
     55 ** directory.
     56 ** LUA_IGMARK is a mark to ignore all before it when building the
     57 ** luaopen_ function name.
     58 */
     59 #if !defined (LUA_PATH_SEP)
     60 #define LUA_PATH_SEP        ";"
     61 #endif
     62 #if !defined (LUA_PATH_MARK)
     63 #define LUA_PATH_MARK       "?"
     64 #endif
     65 #if !defined (LUA_EXEC_DIR)
     66 #define LUA_EXEC_DIR        "!"
     67 #endif
     68 #if !defined (LUA_IGMARK)
     69 #define LUA_IGMARK      "-"
     70 #endif
     71 
     72 
     73 /*
     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.
     78 */
     79 #if !defined(LUA_CSUBSEP)
     80 #define LUA_CSUBSEP     LUA_DIRSEP
     81 #endif
     82 
     83 #if !defined(LUA_LSUBSEP)
     84 #define LUA_LSUBSEP     LUA_DIRSEP
     85 #endif
     86 
     87 
     88 /* prefix for open functions in C libraries */
     89 #define LUA_POF     "luaopen_"
     90 
     91 /* separator for open functions in C libraries */
     92 #define LUA_OFSEP   "_"
     93 
     94 
     95 /* table (in the registry) that keeps handles for all loaded C libraries */
     96 #define CLIBS       "_CLIBS"
     97 
     98 #define LIB_FAIL    "open"
     99 
    100 
    101 /* error codes for ll_loadfunc */
    102 #define ERRLIB      1
    103 #define ERRFUNC     2
    104 
    105 #define setprogdir(L)       ((void)0)
    106 
    107 
    108 /*
    109 ** system-dependent functions
    110 */
    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);
    114 
    115 
    116 
    117 #if defined(LUA_USE_DLOPEN)
    118 /*
    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 ** =========================================================================
    125 */
    126 
    127 #include <dlfcn.h>
    128 
    129 static void ll_unloadlib (void *lib) {
    130   dlclose(lib);
    131 }
    132 
    133 
    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());
    137   return lib;
    138 }
    139 
    140 
    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());
    144   return f;
    145 }
    146 
    147 /* }====================================================== */
    148 
    149 
    150 
    151 #elif defined(LUA_DL_DLL)
    152 /*
    153 ** {======================================================================
    154 ** This is an implementation of loadlib for Windows using native functions.
    155 ** =======================================================================
    156 */
    157 
    158 #undef setprogdir
    159 
    160 /*
    161 ** optional flags for LoadLibraryEx
    162 */
    163 #if !defined(LUA_LLE_FLAGS)
    164 #define LUA_LLE_FLAGS   0
    165 #endif
    166 
    167 
    168 static void setprogdir (lua_State *L) {
    169   char buff[MAX_PATH + 1];
    170   char *lb;
    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");
    175   else {
    176     *lb = '\0';
    177     luaL_gsub(L, lua_tostring(L, -1), LUA_EXEC_DIR, buff);
    178     lua_remove(L, -2);  /* remove original string */
    179   }
    180 }
    181 
    182 
    183 static void pusherror (lua_State *L) {
    184   int error = GetLastError();
    185   char buffer[128];
    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);
    189   else
    190     lua_pushfstring(L, "system error %d\n", error);
    191 }
    192 
    193 static void ll_unloadlib (void *lib) {
    194   FreeLibrary((HMODULE)lib);
    195 }
    196 
    197 
    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);
    202   return lib;
    203 }
    204 
    205 
    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);
    209   return f;
    210 }
    211 
    212 /* }====================================================== */
    213 
    214 
    215 #else
    216 /*
    217 ** {======================================================
    218 ** Fallback for other systems
    219 ** =======================================================
    220 */
    221 
    222 #undef LIB_FAIL
    223 #define LIB_FAIL    "absent"
    224 
    225 
    226 #define DLMSG   "dynamic libraries not enabled; check your Lua installation"
    227 
    228 
    229 static void ll_unloadlib (void *lib) {
    230   (void)(lib);  /* not used */
    231 }
    232 
    233 
    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);
    237   return NULL;
    238 }
    239 
    240 
    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);
    244   return NULL;
    245 }
    246 
    247 /* }====================================================== */
    248 #endif
    249 
    250 
    251 static void *ll_checkclib (lua_State *L, const char *path) {
    252   void *plib;
    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' */
    257   return plib;
    258 }
    259 
    260 
    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 */
    268 }
    269 
    270 
    271 /*
    272 ** __gc tag method for CLIBS table: calls 'll_unloadlib' for all lib
    273 ** handles in list CLIBS
    274 */
    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 */
    281   }
    282   return 0;
    283 }
    284 
    285 
    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);
    292   }
    293   if (*sym == '*') {  /* loading only library (no function)? */
    294     lua_pushboolean(L, 1);  /* return 'true' */
    295     return 0;  /* no errors */
    296   }
    297   else {
    298     lua_CFunction f = ll_sym(L, reg, sym);
    299     if (f == NULL)
    300       return ERRFUNC;  /* unable to find function */
    301     lua_pushcfunction(L, f);  /* else create new function */
    302     return 0;  /* no errors */
    303   }
    304 }
    305 
    306 
    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 */
    314     lua_pushnil(L);
    315     lua_insert(L, -2);
    316     lua_pushstring(L, (stat == ERRLIB) ?  LIB_FAIL : "init");
    317     return 3;  /* return nil, error message, and where */
    318   }
    319 }
    320 
    321 
    322 
    323 /*
    324 ** {======================================================
    325 ** 'require' function
    326 ** =======================================================
    327 */
    328 
    329 
    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 */
    333   fclose(f);
    334   return 1;
    335 }
    336 
    337 
    338 static const char *pushnexttemplate (lua_State *L, const char *path) {
    339   const char *l;
    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 */
    345   return l;
    346 }
    347 
    348 
    349 static const char *searchpath (lua_State *L, const char *name,
    350                                              const char *path,
    351                                              const char *sep,
    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 */
    366   }
    367   luaL_pushresult(&msg);  /* create error message */
    368   return NULL;  /* not found */
    369 }
    370 
    371 
    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 */
    379     lua_pushnil(L);
    380     lua_insert(L, -2);
    381     return 2;  /* return nil + error message */
    382   }
    383 }
    384 
    385 
    386 static const char *findfile (lua_State *L, const char *name,
    387                                            const char *pname,
    388                                            const char *dirsep) {
    389   const char *path;
    390   lua_getfield(L, lua_upvalueindex(1), pname);
    391   path = lua_tostring(L, -1);
    392   if (path == NULL)
    393     luaL_error(L, LUA_QL("package.%s") " must be a string", pname);
    394   return searchpath(L, name, path, ".", dirsep);
    395 }
    396 
    397 
    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 */
    402   }
    403   else
    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));
    407 }
    408 
    409 
    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);
    416 }
    417 
    418 
    419 static int loadfunc (lua_State *L, const char *filename, const char *modname) {
    420   const char *funcname;
    421   const char *mark;
    422   modname = luaL_gsub(L, modname, ".", LUA_OFSEP);
    423   mark = strchr(modname, *LUA_IGMARK);
    424   if (mark) {
    425     int stat;
    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 */
    431   }
    432   funcname = lua_pushfstring(L, LUA_POF"%s", modname);
    433   return ll_loadfunc(L, filename, funcname);
    434 }
    435 
    436 
    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);
    442 }
    443 
    444 
    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, '.');
    449   int stat;
    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) {
    455     if (stat != ERRFUNC)
    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,
    459                          name, filename);
    460       return 1;
    461     }
    462   }
    463   lua_pushstring(L, filename);  /* will be 2nd argument to module */
    464   return 2;
    465 }
    466 
    467 
    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);
    474   return 1;
    475 }
    476 
    477 
    478 static void findloader (lua_State *L, const char *name) {
    479   int i;
    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 */
    486   for (i = 1; ; i++) {
    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));
    493     }
    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 */
    501     }
    502     else
    503       lua_pop(L, 2);  /* remove both returns */
    504   }
    505 }
    506 
    507 
    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 */
    517   findloader(L, name);
    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 */
    528   }
    529   return 1;
    530 }
    531 
    532 /* }====================================================== */
    533 
    534 
    535 
    536 /*
    537 ** {======================================================
    538 ** 'module' function
    539 ** =======================================================
    540 */
    541 #if defined(LUA_COMPAT_MODULE)
    542 
    543 /*
    544 ** changes the environment variable of calling function
    545 */
    546 static void set_env (lua_State *L) {
    547   lua_Debug ar;
    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 */
    555 }
    556 
    557 
    558 static void dooptions (lua_State *L, int n) {
    559   int i;
    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 */
    564       lua_call(L, 1, 0);
    565     }
    566   }
    567 }
    568 
    569 
    570 static void modinit (lua_State *L, const char *modname) {
    571   const char *dot;
    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;
    578   else dot++;
    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");
    582 }
    583 
    584 
    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? */
    592     lua_pop(L, 1);
    593   else {  /* no; initialize it */
    594     lua_pop(L, 1);
    595     modinit(L, modname);
    596   }
    597   lua_pushvalue(L, -1);
    598   set_env(L);
    599   dooptions(L, lastarg);
    600   return 1;
    601 }
    602 
    603 
    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);
    610   }
    611   lua_pushglobaltable(L);
    612   lua_setfield(L, -2, "__index");  /* mt.__index = _G */
    613   return 0;
    614 }
    615 
    616 #endif
    617 /* }====================================================== */
    618 
    619 
    620 
    621 /* auxiliary mark (for internal use) */
    622 #define AUXMARK     "\1"
    623 
    624 
    625 /*
    626 ** return registry.LUA_NOENV as a boolean
    627 */
    628 static int noenv (lua_State *L) {
    629   int b;
    630   lua_getfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");
    631   b = lua_toboolean(L, -1);
    632   lua_pop(L, 1);  /* remove value */
    633   return b;
    634 }
    635 
    636 
    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 */
    644   else {
    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);
    649     lua_remove(L, -2);
    650   }
    651   setprogdir(L);
    652   lua_setfield(L, -2, fieldname);
    653 }
    654 
    655 
    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},
    661 #endif
    662   {NULL, NULL}
    663 };
    664 
    665 
    666 static const luaL_Reg ll_funcs[] = {
    667 #if defined(LUA_COMPAT_MODULE)
    668   {"module", ll_module},
    669 #endif
    670   {"require", ll_require},
    671   {NULL, NULL}
    672 };
    673 
    674 
    675 static void createsearcherstable (lua_State *L) {
    676   static const lua_CFunction searchers[] =
    677     {searcher_preload, searcher_Lua, searcher_C, searcher_Croot, NULL};
    678   int i;
    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);
    686   }
    687 }
    688 
    689 
    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' */
    703 #endif
    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 */
    724 }
    725 
    726