LCOV - code coverage report
Current view: top level - src - loadlib.c Coverage Total Hit
Test: Lua 5.2.4 Lines: 81.2 % 276 224
Test Date: 2024-04-28 10:23:12
Legend: Lines: hit not hit

            Line data    Source code
       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)
      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            0 : static void ll_unloadlib (void *lib) {
     130            0 :   dlclose(lib);
     131            0 : }
     132              : 
     133              : 
     134            2 : static void *ll_load (lua_State *L, const char *path, int seeglb) {
     135            2 :   void *lib = dlopen(path, RTLD_NOW | (seeglb ? RTLD_GLOBAL : RTLD_LOCAL));
     136            2 :   if (lib == NULL) lua_pushstring(L, dlerror());
     137            2 :   return lib;
     138              : }
     139              : 
     140              : 
     141            0 : static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
     142            0 :   lua_CFunction f = (lua_CFunction)dlsym(lib, sym);
     143            0 :   if (f == NULL) lua_pushstring(L, dlerror());
     144            0 :   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            2 : static void *ll_checkclib (lua_State *L, const char *path) {
     252              :   void *plib;
     253            2 :   lua_getfield(L, LUA_REGISTRYINDEX, CLIBS);
     254            2 :   lua_getfield(L, -1, path);
     255            2 :   plib = lua_touserdata(L, -1);  /* plib = CLIBS[path] */
     256            2 :   lua_pop(L, 2);  /* pop CLIBS table and 'plib' */
     257            2 :   return plib;
     258              : }
     259              : 
     260              : 
     261            0 : static void ll_addtoclib (lua_State *L, const char *path, void *plib) {
     262            0 :   lua_getfield(L, LUA_REGISTRYINDEX, CLIBS);
     263            0 :   lua_pushlightuserdata(L, plib);
     264            0 :   lua_pushvalue(L, -1);
     265            0 :   lua_setfield(L, -3, path);  /* CLIBS[path] = plib */
     266            0 :   lua_rawseti(L, -2, luaL_len(L, -2) + 1);  /* CLIBS[#CLIBS + 1] = plib */
     267            0 :   lua_pop(L, 1);  /* pop CLIBS table */
     268            0 : }
     269              : 
     270              : 
     271              : /*
     272              : ** __gc tag method for CLIBS table: calls 'll_unloadlib' for all lib
     273              : ** handles in list CLIBS
     274              : */
     275           77 : static int gctm (lua_State *L) {
     276           77 :   int n = luaL_len(L, 1);
     277           77 :   for (; n >= 1; n--) {  /* for each handle, in reverse order */
     278            0 :     lua_rawgeti(L, 1, n);  /* get handle CLIBS[n] */
     279            0 :     ll_unloadlib(lua_touserdata(L, -1));
     280            0 :     lua_pop(L, 1);  /* pop handle */
     281              :   }
     282           77 :   return 0;
     283              : }
     284              : 
     285              : 
     286            2 : static int ll_loadfunc (lua_State *L, const char *path, const char *sym) {
     287            2 :   void *reg = ll_checkclib(L, path);  /* check loaded C libraries */
     288            2 :   if (reg == NULL) {  /* must load library? */
     289            2 :     reg = ll_load(L, path, *sym == '*');
     290            2 :     if (reg == NULL) return ERRLIB;  /* unable to load library */
     291            0 :     ll_addtoclib(L, path, reg);
     292              :   }
     293            0 :   if (*sym == '*') {  /* loading only library (no function)? */
     294            0 :     lua_pushboolean(L, 1);  /* return 'true' */
     295            0 :     return 0;  /* no errors */
     296              :   }
     297              :   else {
     298            0 :     lua_CFunction f = ll_sym(L, reg, sym);
     299            0 :     if (f == NULL)
     300            0 :       return ERRFUNC;  /* unable to find function */
     301            0 :     lua_pushcfunction(L, f);  /* else create new function */
     302            0 :     return 0;  /* no errors */
     303              :   }
     304              : }
     305              : 
     306              : 
     307            2 : static int ll_loadlib (lua_State *L) {
     308            2 :   const char *path = luaL_checkstring(L, 1);
     309            2 :   const char *init = luaL_checkstring(L, 2);
     310            2 :   int stat = ll_loadfunc(L, path, init);
     311            2 :   if (stat == 0)  /* no errors? */
     312            0 :     return 1;  /* return the loaded function */
     313              :   else {  /* error; error message is on stack top */
     314            2 :     lua_pushnil(L);
     315            2 :     lua_insert(L, -2);
     316            2 :     lua_pushstring(L, (stat == ERRLIB) ?  LIB_FAIL : "init");
     317            2 :     return 3;  /* return nil, error message, and where */
     318              :   }
     319              : }
     320              : 
     321              : 
     322              : 
     323              : /*
     324              : ** {======================================================
     325              : ** 'require' function
     326              : ** =======================================================
     327              : */
     328              : 
     329              : 
     330         1231 : static int readable (const char *filename) {
     331         1231 :   FILE *f = fopen(filename, "r");  /* try to open file */
     332         1231 :   if (f == NULL) return 0;  /* open failed */
     333          100 :   fclose(f);
     334          100 :   return 1;
     335              : }
     336              : 
     337              : 
     338         1367 : static const char *pushnexttemplate (lua_State *L, const char *path) {
     339              :   const char *l;
     340         2497 :   while (*path == *LUA_PATH_SEP) path++;  /* skip separators */
     341         1367 :   if (*path == '\0') return NULL;  /* no more templates */
     342         1231 :   l = strchr(path, *LUA_PATH_SEP);  /* find next separator */
     343         1231 :   if (l == NULL) l = path + strlen(path);
     344         1231 :   lua_pushlstring(L, path, l - path);  /* template */
     345         1231 :   return l;
     346              : }
     347              : 
     348              : 
     349          236 : 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          236 :   luaL_buffinit(L, &msg);
     355          236 :   if (*sep != '\0')  /* non-empty separator? */
     356          236 :     name = luaL_gsub(L, name, sep, dirsep);  /* replace it by 'dirsep' */
     357         1367 :   while ((path = pushnexttemplate(L, path)) != NULL) {
     358         1231 :     const char *filename = luaL_gsub(L, lua_tostring(L, -1),
     359              :                                      LUA_PATH_MARK, name);
     360         1231 :     lua_remove(L, -2);  /* remove path template */
     361         1231 :     if (readable(filename))  /* does file exist and is readable? */
     362          100 :       return filename;  /* return that file name */
     363         1131 :     lua_pushfstring(L, "\n\tno file " LUA_QS, filename);
     364         1131 :     lua_remove(L, -2);  /* remove file name */
     365         1131 :     luaL_addvalue(&msg);  /* concatenate error msg. entry */
     366              :   }
     367          136 :   luaL_pushresult(&msg);  /* create error message */
     368          136 :   return NULL;  /* not found */
     369              : }
     370              : 
     371              : 
     372            3 : static int ll_searchpath (lua_State *L) {
     373            3 :   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            3 :   if (f != NULL) return 1;
     378              :   else {  /* error message is on top of the stack */
     379            2 :     lua_pushnil(L);
     380            2 :     lua_insert(L, -2);
     381            2 :     return 2;  /* return nil + error message */
     382              :   }
     383              : }
     384              : 
     385              : 
     386          233 : static const char *findfile (lua_State *L, const char *name,
     387              :                                            const char *pname,
     388              :                                            const char *dirsep) {
     389              :   const char *path;
     390          233 :   lua_getfield(L, lua_upvalueindex(1), pname);
     391          233 :   path = lua_tostring(L, -1);
     392          233 :   if (path == NULL)
     393            0 :     luaL_error(L, LUA_QL("package.%s") " must be a string", pname);
     394          233 :   return searchpath(L, name, path, ".", dirsep);
     395              : }
     396              : 
     397              : 
     398           99 : static int checkload (lua_State *L, int stat, const char *filename) {
     399           99 :   if (stat) {  /* module loaded successfully? */
     400           98 :     lua_pushstring(L, filename);  /* will be 2nd argument to module */
     401           98 :     return 2;  /* return open function and file name */
     402              :   }
     403              :   else
     404            1 :     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          144 : static int searcher_Lua (lua_State *L) {
     411              :   const char *filename;
     412          144 :   const char *name = luaL_checkstring(L, 1);
     413          144 :   filename = findfile(L, name, "path", LUA_LSUBSEP);
     414          144 :   if (filename == NULL) return 1;  /* module not found in this path */
     415           99 :   return checkload(L, (luaL_loadfile(L, filename) == LUA_OK), filename);
     416              : }
     417              : 
     418              : 
     419            0 : static int loadfunc (lua_State *L, const char *filename, const char *modname) {
     420              :   const char *funcname;
     421              :   const char *mark;
     422            0 :   modname = luaL_gsub(L, modname, ".", LUA_OFSEP);
     423            0 :   mark = strchr(modname, *LUA_IGMARK);
     424            0 :   if (mark) {
     425              :     int stat;
     426            0 :     funcname = lua_pushlstring(L, modname, mark - modname);
     427            0 :     funcname = lua_pushfstring(L, LUA_POF"%s", funcname);
     428            0 :     stat = ll_loadfunc(L, filename, funcname);
     429            0 :     if (stat != ERRFUNC) return stat;
     430            0 :     modname = mark + 1;  /* else go ahead and try old-style name */
     431              :   }
     432            0 :   funcname = lua_pushfstring(L, LUA_POF"%s", modname);
     433            0 :   return ll_loadfunc(L, filename, funcname);
     434              : }
     435              : 
     436              : 
     437           45 : static int searcher_C (lua_State *L) {
     438           45 :   const char *name = luaL_checkstring(L, 1);
     439           45 :   const char *filename = findfile(L, name, "cpath", LUA_CSUBSEP);
     440           45 :   if (filename == NULL) return 1;  /* module not found in this path */
     441            0 :   return checkload(L, (loadfunc(L, filename, name) == 0), filename);
     442              : }
     443              : 
     444              : 
     445           45 : static int searcher_Croot (lua_State *L) {
     446              :   const char *filename;
     447           45 :   const char *name = luaL_checkstring(L, 1);
     448           45 :   const char *p = strchr(name, '.');
     449              :   int stat;
     450           45 :   if (p == NULL) return 0;  /* is root */
     451           44 :   lua_pushlstring(L, name, p - name);
     452           44 :   filename = findfile(L, lua_tostring(L, -1), "cpath", LUA_CSUBSEP);
     453           44 :   if (filename == NULL) return 1;  /* root not found */
     454            0 :   if ((stat = loadfunc(L, filename, name)) != 0) {
     455            0 :     if (stat != ERRFUNC)
     456            0 :       return checkload(L, 0, filename);  /* real error */
     457              :     else {  /* open function not found */
     458            0 :       lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS,
     459              :                          name, filename);
     460            0 :       return 1;
     461              :     }
     462              :   }
     463            0 :   lua_pushstring(L, filename);  /* will be 2nd argument to module */
     464            0 :   return 2;
     465              : }
     466              : 
     467              : 
     468          145 : static int searcher_preload (lua_State *L) {
     469          145 :   const char *name = luaL_checkstring(L, 1);
     470          145 :   lua_getfield(L, LUA_REGISTRYINDEX, "_PRELOAD");
     471          145 :   lua_getfield(L, -1, name);
     472          145 :   if (lua_isnil(L, -1))  /* not found? */
     473          144 :     lua_pushfstring(L, "\n\tno field package.preload['%s']", name);
     474          145 :   return 1;
     475              : }
     476              : 
     477              : 
     478          145 : static void findloader (lua_State *L, const char *name) {
     479              :   int i;
     480              :   luaL_Buffer msg;  /* to build error message */
     481          145 :   luaL_buffinit(L, &msg);
     482          145 :   lua_getfield(L, lua_upvalueindex(1), "searchers");  /* will be at index 3 */
     483          145 :   if (!lua_istable(L, 3))
     484            0 :     luaL_error(L, LUA_QL("package.searchers") " must be a table");
     485              :   /*  iterate over available searchers to find a loader */
     486          424 :   for (i = 1; ; i++) {
     487          424 :     lua_rawgeti(L, 3, i);  /* get a searcher */
     488          424 :     if (lua_isnil(L, -1)) {  /* no more searchers? */
     489           45 :       lua_pop(L, 1);  /* remove nil */
     490           45 :       luaL_pushresult(&msg);  /* create error message */
     491           45 :       luaL_error(L, "module " LUA_QS " not found:%s",
     492              :                     name, lua_tostring(L, -1));
     493              :     }
     494          379 :     lua_pushstring(L, name);
     495          379 :     lua_call(L, 1, 2);  /* call it */
     496          378 :     if (lua_isfunction(L, -2))  /* did it find a loader? */
     497           99 :       return;  /* module loader found */
     498          279 :     else if (lua_isstring(L, -2)) {  /* searcher returned error message? */
     499          278 :       lua_pop(L, 1);  /* remove extra return */
     500          278 :       luaL_addvalue(&msg);  /* concatenate error message */
     501              :     }
     502              :     else
     503            1 :       lua_pop(L, 2);  /* remove both returns */
     504              :   }
     505              : }
     506              : 
     507              : 
     508          167 : static int ll_require (lua_State *L) {
     509          167 :   const char *name = luaL_checkstring(L, 1);
     510          167 :   lua_settop(L, 1);  /* _LOADED table will be at index 2 */
     511          167 :   lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
     512          167 :   lua_getfield(L, 2, name);  /* _LOADED[name] */
     513          167 :   if (lua_toboolean(L, -1))  /* is it there? */
     514           22 :     return 1;  /* package is already loaded */
     515              :   /* else must load package */
     516          145 :   lua_pop(L, 1);  /* remove 'getfield' result */
     517          145 :   findloader(L, name);
     518           99 :   lua_pushstring(L, name);  /* pass name as argument to module loader */
     519           99 :   lua_insert(L, -2);  /* name is 1st argument (before search data) */
     520           99 :   lua_call(L, 2, 1);  /* run loader to load module */
     521           99 :   if (!lua_isnil(L, -1))  /* non-nil return? */
     522           53 :     lua_setfield(L, 2, name);  /* _LOADED[name] = returned value */
     523           99 :   lua_getfield(L, 2, name);
     524           99 :   if (lua_isnil(L, -1)) {   /* module did not set a value? */
     525           46 :     lua_pushboolean(L, 1);  /* use true as result */
     526           46 :     lua_pushvalue(L, -1);  /* extra copy to be returned */
     527           46 :     lua_setfield(L, 2, name);  /* _LOADED[name] = true */
     528              :   }
     529           99 :   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            2 : static void set_env (lua_State *L) {
     547              :   lua_Debug ar;
     548            4 :   if (lua_getstack(L, 1, &ar) == 0 ||
     549            4 :       lua_getinfo(L, "f", &ar) == 0 ||  /* get calling function */
     550            2 :       lua_iscfunction(L, -1))
     551            0 :     luaL_error(L, LUA_QL("module") " not called from a Lua function");
     552            2 :   lua_pushvalue(L, -2);  /* copy new environment table to top */
     553            2 :   lua_setupvalue(L, -2, 1);
     554            2 :   lua_pop(L, 1);  /* remove function */
     555            2 : }
     556              : 
     557              : 
     558            2 : static void dooptions (lua_State *L, int n) {
     559              :   int i;
     560            3 :   for (i = 2; i <= n; i++) {
     561            1 :     if (lua_isfunction(L, i)) {  /* avoid 'calling' extra info. */
     562            1 :       lua_pushvalue(L, i);  /* get option (a function) */
     563            1 :       lua_pushvalue(L, -2);  /* module */
     564            1 :       lua_call(L, 1, 0);
     565              :     }
     566              :   }
     567            2 : }
     568              : 
     569              : 
     570            2 : static void modinit (lua_State *L, const char *modname) {
     571              :   const char *dot;
     572            2 :   lua_pushvalue(L, -1);
     573            2 :   lua_setfield(L, -2, "_M");  /* module._M = module */
     574            2 :   lua_pushstring(L, modname);
     575            2 :   lua_setfield(L, -2, "_NAME");
     576            2 :   dot = strrchr(modname, '.');  /* look for last dot in module name */
     577            2 :   if (dot == NULL) dot = modname;
     578            0 :   else dot++;
     579              :   /* set _PACKAGE as package name (full module name minus last part) */
     580            2 :   lua_pushlstring(L, modname, dot - modname);
     581            2 :   lua_setfield(L, -2, "_PACKAGE");
     582            2 : }
     583              : 
     584              : 
     585            2 : static int ll_module (lua_State *L) {
     586            2 :   const char *modname = luaL_checkstring(L, 1);
     587            2 :   int lastarg = lua_gettop(L);  /* last parameter */
     588            2 :   luaL_pushmodule(L, modname, 1);  /* get/create module table */
     589              :   /* check whether table already has a _NAME field */
     590            2 :   lua_getfield(L, -1, "_NAME");
     591            2 :   if (!lua_isnil(L, -1))  /* is table an initialized module? */
     592            0 :     lua_pop(L, 1);
     593              :   else {  /* no; initialize it */
     594            2 :     lua_pop(L, 1);
     595            2 :     modinit(L, modname);
     596              :   }
     597            2 :   lua_pushvalue(L, -1);
     598            2 :   set_env(L);
     599            2 :   dooptions(L, lastarg);
     600            2 :   return 1;
     601              : }
     602              : 
     603              : 
     604            2 : static int ll_seeall (lua_State *L) {
     605            2 :   luaL_checktype(L, 1, LUA_TTABLE);
     606            2 :   if (!lua_getmetatable(L, 1)) {
     607            2 :     lua_createtable(L, 0, 1); /* create new metatable */
     608            2 :     lua_pushvalue(L, -1);
     609            2 :     lua_setmetatable(L, 1);
     610              :   }
     611            2 :   lua_pushglobaltable(L);
     612            2 :   lua_setfield(L, -2, "__index");  /* mt.__index = _G */
     613            2 :   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          172 : static int noenv (lua_State *L) {
     629              :   int b;
     630          172 :   lua_getfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");
     631          172 :   b = lua_toboolean(L, -1);
     632          172 :   lua_pop(L, 1);  /* remove value */
     633          172 :   return b;
     634              : }
     635              : 
     636              : 
     637          172 : static void setpath (lua_State *L, const char *fieldname, const char *envname1,
     638              :                                    const char *envname2, const char *def) {
     639          172 :   const char *path = getenv(envname1);
     640          172 :   if (path == NULL)  /* no environment variable? */
     641          172 :     path = getenv(envname2);  /* try alternative name */
     642          172 :   if (path == NULL || noenv(L))  /* no environment variable? */
     643            2 :     lua_pushstring(L, def);  /* use default */
     644              :   else {
     645              :     /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */
     646          170 :     path = luaL_gsub(L, path, LUA_PATH_SEP LUA_PATH_SEP,
     647              :                               LUA_PATH_SEP AUXMARK LUA_PATH_SEP);
     648          170 :     luaL_gsub(L, path, AUXMARK, def);
     649          170 :     lua_remove(L, -2);
     650              :   }
     651              :   setprogdir(L);
     652          172 :   lua_setfield(L, -2, fieldname);
     653          172 : }
     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           86 : 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           86 :   lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0);
     681              :   /* fill it with pre-defined searchers */
     682          430 :   for (i=0; searchers[i] != NULL; i++) {
     683          344 :     lua_pushvalue(L, -2);  /* set 'package' as upvalue for all searchers */
     684          344 :     lua_pushcclosure(L, searchers[i], 1);
     685          344 :     lua_rawseti(L, -2, i+1);
     686              :   }
     687           86 : }
     688              : 
     689              : 
     690           86 : LUAMOD_API int luaopen_package (lua_State *L) {
     691              :   /* create table CLIBS to keep track of loaded C libraries */
     692           86 :   luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS);
     693           86 :   lua_createtable(L, 0, 1);  /* metatable for CLIBS */
     694           86 :   lua_pushcfunction(L, gctm);
     695           86 :   lua_setfield(L, -2, "__gc");  /* set finalizer for CLIBS table */
     696           86 :   lua_setmetatable(L, -2);
     697              :   /* create `package' table */
     698           86 :   luaL_newlib(L, pk_funcs);
     699           86 :   createsearcherstable(L);
     700              : #if defined(LUA_COMPAT_LOADERS)
     701           86 :   lua_pushvalue(L, -1);  /* make a copy of 'searchers' table */
     702           86 :   lua_setfield(L, -3, "loaders");  /* put it in field `loaders' */
     703              : #endif
     704           86 :   lua_setfield(L, -2, "searchers");  /* put it in field 'searchers' */
     705              :   /* set field 'path' */
     706           86 :   setpath(L, "path", LUA_PATHVERSION, LUA_PATH, LUA_PATH_DEFAULT);
     707              :   /* set field 'cpath' */
     708           86 :   setpath(L, "cpath", LUA_CPATHVERSION, LUA_CPATH, LUA_CPATH_DEFAULT);
     709              :   /* store config information */
     710           86 :   lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATH_SEP "\n" LUA_PATH_MARK "\n"
     711              :                      LUA_EXEC_DIR "\n" LUA_IGMARK "\n");
     712           86 :   lua_setfield(L, -2, "config");
     713              :   /* set field `loaded' */
     714           86 :   luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED");
     715           86 :   lua_setfield(L, -2, "loaded");
     716              :   /* set field `preload' */
     717           86 :   luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD");
     718           86 :   lua_setfield(L, -2, "preload");
     719           86 :   lua_pushglobaltable(L);
     720           86 :   lua_pushvalue(L, -2);  /* set 'package' as upvalue for next lib */
     721           86 :   luaL_setfuncs(L, ll_funcs, 1);  /* open lib into global table */
     722           86 :   lua_pop(L, 1);  /* pop global table */
     723           86 :   return 1;  /* return 'package' table */
     724              : }
     725              : 
        

Generated by: LCOV version 2.0-1