?login_element?

Subversion Repositories NedoOS

Rev

Blame | Last modification | View Log | Download

  1. /*
  2. ** $Id: loadlib.c,v 1.130.1.1 2017/04/19 17:20:42 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. #define loadlib_c
  12. #define LUA_LIB
  13.  
  14. #include "lprefix.h"
  15.  
  16.  
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20.  
  21. #include "lua.h"
  22.  
  23. #include "lauxlib.h"
  24. #include "lualib.h"
  25.  
  26.  
  27. /*
  28. ** LUA_IGMARK is a mark to ignore all before it when building the
  29. ** luaopen_ function name.
  30. */
  31. #if !defined (LUA_IGMARK)
  32. #define LUA_IGMARK              "-"
  33. #endif
  34.  
  35.  
  36. /*
  37. ** LUA_CSUBSEP is the character that replaces dots in submodule names
  38. ** when searching for a C loader.
  39. ** LUA_LSUBSEP is the character that replaces dots in submodule names
  40. ** when searching for a Lua loader.
  41. */
  42. #if !defined(LUA_CSUBSEP)
  43. #define LUA_CSUBSEP             LUA_DIRSEP
  44. #endif
  45.  
  46. #if !defined(LUA_LSUBSEP)
  47. #define LUA_LSUBSEP             LUA_DIRSEP
  48. #endif
  49.  
  50.  
  51. /* prefix for open functions in C libraries */
  52. #define LUA_POF         "luaopen_"
  53.  
  54. /* separator for open functions in C libraries */
  55. #define LUA_OFSEP       "_"
  56.  
  57.  
  58. /*
  59. ** unique key for table in the registry that keeps handles
  60. ** for all loaded C libraries
  61. */
  62. static const int CLIBS = 0;
  63.  
  64. #define LIB_FAIL        "open"
  65.  
  66.  
  67. #define setprogdir(L)           ((void)0)
  68.  
  69.  
  70. /*
  71. ** system-dependent functions
  72. */
  73.  
  74. /*
  75. ** unload library 'lib'
  76. */
  77. static void lsys_unloadlib (void *lib);
  78.  
  79. /*
  80. ** load C library in file 'path'. If 'seeglb', load with all names in
  81. ** the library global.
  82. ** Returns the library; in case of error, returns NULL plus an
  83. ** error string in the stack.
  84. */
  85. static void *lsys_load (lua_State *L, const char *path, int seeglb);
  86.  
  87. /*
  88. ** Try to find a function named 'sym' in library 'lib'.
  89. ** Returns the function; in case of error, returns NULL plus an
  90. ** error string in the stack.
  91. */
  92. static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym);
  93.  
  94.  
  95.  
  96.  
  97. #if defined(LUA_USE_DLOPEN)     /* { */
  98. /*
  99. ** {========================================================================
  100. ** This is an implementation of loadlib based on the dlfcn interface.
  101. ** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD,
  102. ** NetBSD, AIX 4.2, HPUX 11, and  probably most other Unix flavors, at least
  103. ** as an emulation layer on top of native functions.
  104. ** =========================================================================
  105. */
  106.  
  107. #include <dlfcn.h>
  108.  
  109. /*
  110. ** Macro to convert pointer-to-void* to pointer-to-function. This cast
  111. ** is undefined according to ISO C, but POSIX assumes that it works.
  112. ** (The '__extension__' in gnu compilers is only to avoid warnings.)
  113. */
  114. #if defined(__GNUC__)
  115. #define cast_func(p) (__extension__ (lua_CFunction)(p))
  116. #else
  117. #define cast_func(p) ((lua_CFunction)(p))
  118. #endif
  119.  
  120.  
  121. static void lsys_unloadlib (void *lib) {
  122.   dlclose(lib);
  123. }
  124.  
  125.  
  126. static void *lsys_load (lua_State *L, const char *path, int seeglb) {
  127.   void *lib = dlopen(path, RTLD_NOW | (seeglb ? RTLD_GLOBAL : RTLD_LOCAL));
  128.   if (lib == NULL) lua_pushstring(L, dlerror());
  129.   return lib;
  130. }
  131.  
  132.  
  133. static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) {
  134.   lua_CFunction f = cast_func(dlsym(lib, sym));
  135.   if (f == NULL) lua_pushstring(L, dlerror());
  136.   return f;
  137. }
  138.  
  139. /* }====================================================== */
  140.  
  141.  
  142.  
  143. #elif defined(LUA_DL_DLL)       /* }{ */
  144. /*
  145. ** {======================================================================
  146. ** This is an implementation of loadlib for Windows using native functions.
  147. ** =======================================================================
  148. */
  149.  
  150. #include <windows.h>
  151.  
  152.  
  153. /*
  154. ** optional flags for LoadLibraryEx
  155. */
  156. #if !defined(LUA_LLE_FLAGS)
  157. #define LUA_LLE_FLAGS   0
  158. #endif
  159.  
  160.  
  161. #undef setprogdir
  162.  
  163.  
  164. /*
  165. ** Replace in the path (on the top of the stack) any occurrence
  166. ** of LUA_EXEC_DIR with the executable's path.
  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);  /* get exec. name */
  173.   if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL)
  174.     luaL_error(L, "unable to get ModuleFileName");
  175.   else {
  176.     *lb = '\0';  /* cut name on the last '\\' to get the path */
  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.  
  184.  
  185. static void pusherror (lua_State *L) {
  186.   int error = GetLastError();
  187.   char buffer[128];
  188.   if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
  189.       NULL, error, 0, buffer, sizeof(buffer)/sizeof(char), NULL))
  190.     lua_pushstring(L, buffer);
  191.   else
  192.     lua_pushfstring(L, "system error %d\n", error);
  193. }
  194.  
  195. static void lsys_unloadlib (void *lib) {
  196.   FreeLibrary((HMODULE)lib);
  197. }
  198.  
  199.  
  200. static void *lsys_load (lua_State *L, const char *path, int seeglb) {
  201.   HMODULE lib = LoadLibraryExA(path, NULL, LUA_LLE_FLAGS);
  202.   (void)(seeglb);  /* not used: symbols are 'global' by default */
  203.   if (lib == NULL) pusherror(L);
  204.   return lib;
  205. }
  206.  
  207.  
  208. static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) {
  209.   lua_CFunction f = (lua_CFunction)GetProcAddress((HMODULE)lib, sym);
  210.   if (f == NULL) pusherror(L);
  211.   return f;
  212. }
  213.  
  214. /* }====================================================== */
  215.  
  216.  
  217. #else                           /* }{ */
  218. /*
  219. ** {======================================================
  220. ** Fallback for other systems
  221. ** =======================================================
  222. */
  223.  
  224. #undef LIB_FAIL
  225. #define LIB_FAIL        "absent"
  226.  
  227.  
  228. #define DLMSG   "dynamic libraries not enabled; check your Lua installation"
  229.  
  230.  
  231. static void lsys_unloadlib (void *lib) {
  232.   (void)(lib);  /* not used */
  233. }
  234.  
  235.  
  236. static void *lsys_load (lua_State *L, const char *path, int seeglb) {
  237.   (void)(path); (void)(seeglb);  /* not used */
  238.   lua_pushliteral(L, DLMSG);
  239.   return NULL;
  240. }
  241.  
  242.  
  243. static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) {
  244.   (void)(lib); (void)(sym);  /* not used */
  245.   lua_pushliteral(L, DLMSG);
  246.   return NULL;
  247. }
  248.  
  249. /* }====================================================== */
  250. #endif                          /* } */
  251.  
  252.  
  253. /*
  254. ** {==================================================================
  255. ** Set Paths
  256. ** ===================================================================
  257. */
  258.  
  259. /*
  260. ** LUA_PATH_VAR and LUA_CPATH_VAR are the names of the environment
  261. ** variables that Lua check to set its paths.
  262. */
  263. #if !defined(LUA_PATH_VAR)
  264. #define LUA_PATH_VAR    "LUA_PATH"
  265. #endif
  266.  
  267. #if !defined(LUA_CPATH_VAR)
  268. #define LUA_CPATH_VAR   "LUA_CPATH"
  269. #endif
  270.  
  271.  
  272. #define AUXMARK         "\1"    /* auxiliary mark */
  273.  
  274.  
  275. /*
  276. ** return registry.LUA_NOENV as a boolean
  277. */
  278. static int noenv (lua_State *L) {
  279.   int b;
  280.   lua_getfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");
  281.   b = lua_toboolean(L, -1);
  282.   lua_pop(L, 1);  /* remove value */
  283.   return b;
  284. }
  285.  
  286.  
  287. /*
  288. ** Set a path
  289. */
  290. static void setpath (lua_State *L, const char *fieldname,
  291.                                    const char *envname,
  292.                                    const char *dft) {
  293.   const char *nver = lua_pushfstring(L, "%s%s", envname, LUA_VERSUFFIX);
  294.   const char *path = getenv(nver);  /* use versioned name */
  295.   if (path == NULL)  /* no environment variable? */
  296.     path = getenv(envname);  /* try unversioned name */
  297.   if (path == NULL || noenv(L))  /* no environment variable? */
  298.     lua_pushstring(L, dft);  /* use default */
  299.   else {
  300.     /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */
  301.     path = luaL_gsub(L, path, LUA_PATH_SEP LUA_PATH_SEP,
  302.                               LUA_PATH_SEP AUXMARK LUA_PATH_SEP);
  303.     luaL_gsub(L, path, AUXMARK, dft);
  304.     lua_remove(L, -2); /* remove result from 1st 'gsub' */
  305.   }
  306.   setprogdir(L);
  307.   lua_setfield(L, -3, fieldname);  /* package[fieldname] = path value */
  308.   lua_pop(L, 1);  /* pop versioned variable name */
  309. }
  310.  
  311. /* }================================================================== */
  312.  
  313.  
  314. /*
  315. ** return registry.CLIBS[path]
  316. */
  317. static void *checkclib (lua_State *L, const char *path) {
  318.   void *plib;
  319.   lua_rawgetp(L, LUA_REGISTRYINDEX, &CLIBS);
  320.   lua_getfield(L, -1, path);
  321.   plib = lua_touserdata(L, -1);  /* plib = CLIBS[path] */
  322.   lua_pop(L, 2);  /* pop CLIBS table and 'plib' */
  323.   return plib;
  324. }
  325.  
  326.  
  327. /*
  328. ** registry.CLIBS[path] = plib        -- for queries
  329. ** registry.CLIBS[#CLIBS + 1] = plib  -- also keep a list of all libraries
  330. */
  331. static void addtoclib (lua_State *L, const char *path, void *plib) {
  332.   lua_rawgetp(L, LUA_REGISTRYINDEX, &CLIBS);
  333.   lua_pushlightuserdata(L, plib);
  334.   lua_pushvalue(L, -1);
  335.   lua_setfield(L, -3, path);  /* CLIBS[path] = plib */
  336.   lua_rawseti(L, -2, luaL_len(L, -2) + 1);  /* CLIBS[#CLIBS + 1] = plib */
  337.   lua_pop(L, 1);  /* pop CLIBS table */
  338. }
  339.  
  340.  
  341. /*
  342. ** __gc tag method for CLIBS table: calls 'lsys_unloadlib' for all lib
  343. ** handles in list CLIBS
  344. */
  345. static int gctm (lua_State *L) {
  346.   lua_Integer n = luaL_len(L, 1);
  347.   for (; n >= 1; n--) {  /* for each handle, in reverse order */
  348.     lua_rawgeti(L, 1, n);  /* get handle CLIBS[n] */
  349.     lsys_unloadlib(lua_touserdata(L, -1));
  350.     lua_pop(L, 1);  /* pop handle */
  351.   }
  352.   return 0;
  353. }
  354.  
  355.  
  356.  
  357. /* error codes for 'lookforfunc' */
  358. #define ERRLIB          1
  359. #define ERRFUNC         2
  360.  
  361. /*
  362. ** Look for a C function named 'sym' in a dynamically loaded library
  363. ** 'path'.
  364. ** First, check whether the library is already loaded; if not, try
  365. ** to load it.
  366. ** Then, if 'sym' is '*', return true (as library has been loaded).
  367. ** Otherwise, look for symbol 'sym' in the library and push a
  368. ** C function with that symbol.
  369. ** Return 0 and 'true' or a function in the stack; in case of
  370. ** errors, return an error code and an error message in the stack.
  371. */
  372. static int lookforfunc (lua_State *L, const char *path, const char *sym) {
  373.   void *reg = checkclib(L, path);  /* check loaded C libraries */
  374.   if (reg == NULL) {  /* must load library? */
  375.     reg = lsys_load(L, path, *sym == '*');  /* global symbols if 'sym'=='*' */
  376.     if (reg == NULL) return ERRLIB;  /* unable to load library */
  377.     addtoclib(L, path, reg);
  378.   }
  379.   if (*sym == '*') {  /* loading only library (no function)? */
  380.     lua_pushboolean(L, 1);  /* return 'true' */
  381.     return 0;  /* no errors */
  382.   }
  383.   else {
  384.     lua_CFunction f = lsys_sym(L, reg, sym);
  385.     if (f == NULL)
  386.       return ERRFUNC;  /* unable to find function */
  387.     lua_pushcfunction(L, f);  /* else create new function */
  388.     return 0;  /* no errors */
  389.   }
  390. }
  391.  
  392.  
  393. static int ll_loadlib (lua_State *L) {
  394.   const char *path = luaL_checkstring(L, 1);
  395.   const char *init = luaL_checkstring(L, 2);
  396.   int stat = lookforfunc(L, path, init);
  397.   if (stat == 0)  /* no errors? */
  398.     return 1;  /* return the loaded function */
  399.   else {  /* error; error message is on stack top */
  400.     lua_pushnil(L);
  401.     lua_insert(L, -2);
  402.     lua_pushstring(L, (stat == ERRLIB) ?  LIB_FAIL : "init");
  403.     return 3;  /* return nil, error message, and where */
  404.   }
  405. }
  406.  
  407.  
  408.  
  409. /*
  410. ** {======================================================
  411. ** 'require' function
  412. ** =======================================================
  413. */
  414.  
  415.  
  416. static int readable (const char *filename) {
  417.   FILE *f = fopen(filename, "r");  /* try to open file */
  418.   if (f == NULL) return 0;  /* open failed */
  419.   fclose(f);
  420.   return 1;
  421. }
  422.  
  423.  
  424. static const char *pushnexttemplate (lua_State *L, const char *path) {
  425.   const char *l;
  426.   while (*path == *LUA_PATH_SEP) path++;  /* skip separators */
  427.   if (*path == '\0') return NULL;  /* no more templates */
  428.   l = strchr(path, *LUA_PATH_SEP);  /* find next separator */
  429.   if (l == NULL) l = path + strlen(path);
  430.   lua_pushlstring(L, path, l - path);  /* template */
  431.   return l;
  432. }
  433.  
  434.  
  435. static const char *searchpath (lua_State *L, const char *name,
  436.                                              const char *path,
  437.                                              const char *sep,
  438.                                              const char *dirsep) {
  439.   luaL_Buffer msg;  /* to build error message */
  440.   luaL_buffinit(L, &msg);
  441.   if (*sep != '\0')  /* non-empty separator? */
  442.     name = luaL_gsub(L, name, sep, dirsep);  /* replace it by 'dirsep' */
  443.   while ((path = pushnexttemplate(L, path)) != NULL) {
  444.     const char *filename = luaL_gsub(L, lua_tostring(L, -1),
  445.                                      LUA_PATH_MARK, name);
  446.     lua_remove(L, -2);  /* remove path template */
  447.     if (readable(filename))  /* does file exist and is readable? */
  448.       return filename;  /* return that file name */
  449.     lua_pushfstring(L, "\n\tno file '%s'", filename);
  450.     lua_remove(L, -2);  /* remove file name */
  451.     luaL_addvalue(&msg);  /* concatenate error msg. entry */
  452.   }
  453.   luaL_pushresult(&msg);  /* create error message */
  454.   return NULL;  /* not found */
  455. }
  456.  
  457.  
  458. static int ll_searchpath (lua_State *L) {
  459.   const char *f = searchpath(L, luaL_checkstring(L, 1),
  460.                                 luaL_checkstring(L, 2),
  461.                                 luaL_optstring(L, 3, "."),
  462.                                 luaL_optstring(L, 4, LUA_DIRSEP));
  463.   if (f != NULL) return 1;
  464.   else {  /* error message is on top of the stack */
  465.     lua_pushnil(L);
  466.     lua_insert(L, -2);
  467.     return 2;  /* return nil + error message */
  468.   }
  469. }
  470.  
  471.  
  472. static const char *findfile (lua_State *L, const char *name,
  473.                                            const char *pname,
  474.                                            const char *dirsep) {
  475.   const char *path;
  476.   lua_getfield(L, lua_upvalueindex(1), pname);
  477.   path = lua_tostring(L, -1);
  478.   if (path == NULL)
  479.     luaL_error(L, "'package.%s' must be a string", pname);
  480.   return searchpath(L, name, path, ".", dirsep);
  481. }
  482.  
  483.  
  484. static int checkload (lua_State *L, int stat, const char *filename) {
  485.   if (stat) {  /* module loaded successfully? */
  486.     lua_pushstring(L, filename);  /* will be 2nd argument to module */
  487.     return 2;  /* return open function and file name */
  488.   }
  489.   else
  490.     return luaL_error(L, "error loading module '%s' from file '%s':\n\t%s",
  491.                           lua_tostring(L, 1), filename, lua_tostring(L, -1));
  492. }
  493.  
  494.  
  495. static int searcher_Lua (lua_State *L) {
  496.   const char *filename;
  497.   const char *name = luaL_checkstring(L, 1);
  498.   filename = findfile(L, name, "path", LUA_LSUBSEP);
  499.   if (filename == NULL) return 1;  /* module not found in this path */
  500.   return checkload(L, (luaL_loadfile(L, filename) == LUA_OK), filename);
  501. }
  502.  
  503.  
  504. /*
  505. ** Try to find a load function for module 'modname' at file 'filename'.
  506. ** First, change '.' to '_' in 'modname'; then, if 'modname' has
  507. ** the form X-Y (that is, it has an "ignore mark"), build a function
  508. ** name "luaopen_X" and look for it. (For compatibility, if that
  509. ** fails, it also tries "luaopen_Y".) If there is no ignore mark,
  510. ** look for a function named "luaopen_modname".
  511. */
  512. static int loadfunc (lua_State *L, const char *filename, const char *modname) {
  513.   const char *openfunc;
  514.   const char *mark;
  515.   modname = luaL_gsub(L, modname, ".", LUA_OFSEP);
  516.   mark = strchr(modname, *LUA_IGMARK);
  517.   if (mark) {
  518.     int stat;
  519.     openfunc = lua_pushlstring(L, modname, mark - modname);
  520.     openfunc = lua_pushfstring(L, LUA_POF"%s", openfunc);
  521.     stat = lookforfunc(L, filename, openfunc);
  522.     if (stat != ERRFUNC) return stat;
  523.     modname = mark + 1;  /* else go ahead and try old-style name */
  524.   }
  525.   openfunc = lua_pushfstring(L, LUA_POF"%s", modname);
  526.   return lookforfunc(L, filename, openfunc);
  527. }
  528.  
  529.  
  530. static int searcher_C (lua_State *L) {
  531.   const char *name = luaL_checkstring(L, 1);
  532.   const char *filename = findfile(L, name, "cpath", LUA_CSUBSEP);
  533.   if (filename == NULL) return 1;  /* module not found in this path */
  534.   return checkload(L, (loadfunc(L, filename, name) == 0), filename);
  535. }
  536.  
  537.  
  538. static int searcher_Croot (lua_State *L) {
  539.   const char *filename;
  540.   const char *name = luaL_checkstring(L, 1);
  541.   const char *p = strchr(name, '.');
  542.   int stat;
  543.   if (p == NULL) return 0;  /* is root */
  544.   lua_pushlstring(L, name, p - name);
  545.   filename = findfile(L, lua_tostring(L, -1), "cpath", LUA_CSUBSEP);
  546.   if (filename == NULL) return 1;  /* root not found */
  547.   if ((stat = loadfunc(L, filename, name)) != 0) {
  548.     if (stat != ERRFUNC)
  549.       return checkload(L, 0, filename);  /* real error */
  550.     else {  /* open function not found */
  551.       lua_pushfstring(L, "\n\tno module '%s' in file '%s'", name, filename);
  552.       return 1;
  553.     }
  554.   }
  555.   lua_pushstring(L, filename);  /* will be 2nd argument to module */
  556.   return 2;
  557. }
  558.  
  559.  
  560. static int searcher_preload (lua_State *L) {
  561.   const char *name = luaL_checkstring(L, 1);
  562.   lua_getfield(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE);
  563.   if (lua_getfield(L, -1, name) == LUA_TNIL)  /* not found? */
  564.     lua_pushfstring(L, "\n\tno field package.preload['%s']", name);
  565.   return 1;
  566. }
  567.  
  568.  
  569. static void findloader (lua_State *L, const char *name) {
  570.   int i;
  571.   luaL_Buffer msg;  /* to build error message */
  572.   luaL_buffinit(L, &msg);
  573.   /* push 'package.searchers' to index 3 in the stack */
  574.   if (lua_getfield(L, lua_upvalueindex(1), "searchers") != LUA_TTABLE)
  575.     luaL_error(L, "'package.searchers' must be a table");
  576.   /*  iterate over available searchers to find a loader */
  577.   for (i = 1; ; i++) {
  578.     if (lua_rawgeti(L, 3, i) == LUA_TNIL) {  /* no more searchers? */
  579.       lua_pop(L, 1);  /* remove nil */
  580.       luaL_pushresult(&msg);  /* create error message */
  581.       luaL_error(L, "module '%s' not found:%s", name, lua_tostring(L, -1));
  582.     }
  583.     lua_pushstring(L, name);
  584.     lua_call(L, 1, 2);  /* call it */
  585.     if (lua_isfunction(L, -2))  /* did it find a loader? */
  586.       return;  /* module loader found */
  587.     else if (lua_isstring(L, -2)) {  /* searcher returned error message? */
  588.       lua_pop(L, 1);  /* remove extra return */
  589.       luaL_addvalue(&msg);  /* concatenate error message */
  590.     }
  591.     else
  592.       lua_pop(L, 2);  /* remove both returns */
  593.   }
  594. }
  595.  
  596.  
  597. static int ll_require (lua_State *L) {
  598.   const char *name = luaL_checkstring(L, 1);
  599.   lua_settop(L, 1);  /* LOADED table will be at index 2 */
  600.   lua_getfield(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE);
  601.   lua_getfield(L, 2, name);  /* LOADED[name] */
  602.   if (lua_toboolean(L, -1))  /* is it there? */
  603.     return 1;  /* package is already loaded */
  604.   /* else must load package */
  605.   lua_pop(L, 1);  /* remove 'getfield' result */
  606.   findloader(L, name);
  607.   lua_pushstring(L, name);  /* pass name as argument to module loader */
  608.   lua_insert(L, -2);  /* name is 1st argument (before search data) */
  609.   lua_call(L, 2, 1);  /* run loader to load module */
  610.   if (!lua_isnil(L, -1))  /* non-nil return? */
  611.     lua_setfield(L, 2, name);  /* LOADED[name] = returned value */
  612.   if (lua_getfield(L, 2, name) == LUA_TNIL) {   /* module set no value? */
  613.     lua_pushboolean(L, 1);  /* use true as result */
  614.     lua_pushvalue(L, -1);  /* extra copy to be returned */
  615.     lua_setfield(L, 2, name);  /* LOADED[name] = true */
  616.   }
  617.   return 1;
  618. }
  619.  
  620. /* }====================================================== */
  621.  
  622.  
  623.  
  624. /*
  625. ** {======================================================
  626. ** 'module' function
  627. ** =======================================================
  628. */
  629. #if defined(LUA_COMPAT_MODULE)
  630.  
  631. /*
  632. ** changes the environment variable of calling function
  633. */
  634. static void set_env (lua_State *L) {
  635.   lua_Debug ar;
  636.   if (lua_getstack(L, 1, &ar) == 0 ||
  637.       lua_getinfo(L, "f", &ar) == 0 ||  /* get calling function */
  638.       lua_iscfunction(L, -1))
  639.     luaL_error(L, "'module' not called from a Lua function");
  640.   lua_pushvalue(L, -2);  /* copy new environment table to top */
  641.   lua_setupvalue(L, -2, 1);
  642.   lua_pop(L, 1);  /* remove function */
  643. }
  644.  
  645.  
  646. static void dooptions (lua_State *L, int n) {
  647.   int i;
  648.   for (i = 2; i <= n; i++) {
  649.     if (lua_isfunction(L, i)) {  /* avoid 'calling' extra info. */
  650.       lua_pushvalue(L, i);  /* get option (a function) */
  651.       lua_pushvalue(L, -2);  /* module */
  652.       lua_call(L, 1, 0);
  653.     }
  654.   }
  655. }
  656.  
  657.  
  658. static void modinit (lua_State *L, const char *modname) {
  659.   const char *dot;
  660.   lua_pushvalue(L, -1);
  661.   lua_setfield(L, -2, "_M");  /* module._M = module */
  662.   lua_pushstring(L, modname);
  663.   lua_setfield(L, -2, "_NAME");
  664.   dot = strrchr(modname, '.');  /* look for last dot in module name */
  665.   if (dot == NULL) dot = modname;
  666.   else dot++;
  667.   /* set _PACKAGE as package name (full module name minus last part) */
  668.   lua_pushlstring(L, modname, dot - modname);
  669.   lua_setfield(L, -2, "_PACKAGE");
  670. }
  671.  
  672.  
  673. static int ll_module (lua_State *L) {
  674.   const char *modname = luaL_checkstring(L, 1);
  675.   int lastarg = lua_gettop(L);  /* last parameter */
  676.   luaL_pushmodule(L, modname, 1);  /* get/create module table */
  677.   /* check whether table already has a _NAME field */
  678.   if (lua_getfield(L, -1, "_NAME") != LUA_TNIL)
  679.     lua_pop(L, 1);  /* table is an initialized module */
  680.   else {  /* no; initialize it */
  681.     lua_pop(L, 1);
  682.     modinit(L, modname);
  683.   }
  684.   lua_pushvalue(L, -1);
  685.   set_env(L);
  686.   dooptions(L, lastarg);
  687.   return 1;
  688. }
  689.  
  690.  
  691. static int ll_seeall (lua_State *L) {
  692.   luaL_checktype(L, 1, LUA_TTABLE);
  693.   if (!lua_getmetatable(L, 1)) {
  694.     lua_createtable(L, 0, 1); /* create new metatable */
  695.     lua_pushvalue(L, -1);
  696.     lua_setmetatable(L, 1);
  697.   }
  698.   lua_pushglobaltable(L);
  699.   lua_setfield(L, -2, "__index");  /* mt.__index = _G */
  700.   return 0;
  701. }
  702.  
  703. #endif
  704. /* }====================================================== */
  705.  
  706.  
  707.  
  708. static const luaL_Reg pk_funcs[] = {
  709.   {"loadlib", ll_loadlib},
  710.   {"searchpath", ll_searchpath},
  711. #if defined(LUA_COMPAT_MODULE)
  712.   {"seeall", ll_seeall},
  713. #endif
  714.   /* placeholders */
  715.   {"preload", NULL},
  716.   {"cpath", NULL},
  717.   {"path", NULL},
  718.   {"searchers", NULL},
  719.   {"loaded", NULL},
  720.   {NULL, NULL}
  721. };
  722.  
  723.  
  724. static const luaL_Reg ll_funcs[] = {
  725. #if defined(LUA_COMPAT_MODULE)
  726.   {"module", ll_module},
  727. #endif
  728.   {"require", ll_require},
  729.   {NULL, NULL}
  730. };
  731.  
  732.  
  733. static void createsearcherstable (lua_State *L) {
  734.   static const lua_CFunction searchers[] =
  735.     {searcher_preload, searcher_Lua, searcher_C, searcher_Croot, NULL};
  736.   int i;
  737.   /* create 'searchers' table */
  738.   lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0);
  739.   /* fill it with predefined searchers */
  740.   for (i=0; searchers[i] != NULL; i++) {
  741.     lua_pushvalue(L, -2);  /* set 'package' as upvalue for all searchers */
  742.     lua_pushcclosure(L, searchers[i], 1);
  743.     lua_rawseti(L, -2, i+1);
  744.   }
  745. #if defined(LUA_COMPAT_LOADERS)
  746.   lua_pushvalue(L, -1);  /* make a copy of 'searchers' table */
  747.   lua_setfield(L, -3, "loaders");  /* put it in field 'loaders' */
  748. #endif
  749.   lua_setfield(L, -2, "searchers");  /* put it in field 'searchers' */
  750. }
  751.  
  752.  
  753. /*
  754. ** create table CLIBS to keep track of loaded C libraries,
  755. ** setting a finalizer to close all libraries when closing state.
  756. */
  757. static void createclibstable (lua_State *L) {
  758.   lua_newtable(L);  /* create CLIBS table */
  759.   lua_createtable(L, 0, 1);  /* create metatable for CLIBS */
  760.   lua_pushcfunction(L, gctm);
  761.   lua_setfield(L, -2, "__gc");  /* set finalizer for CLIBS table */
  762.   lua_setmetatable(L, -2);
  763.   lua_rawsetp(L, LUA_REGISTRYINDEX, &CLIBS);  /* set CLIBS table in registry */
  764. }
  765.  
  766.  
  767. LUAMOD_API int luaopen_package (lua_State *L) {
  768.   createclibstable(L);
  769.   luaL_newlib(L, pk_funcs);  /* create 'package' table */
  770.   createsearcherstable(L);
  771.   /* set paths */
  772.   setpath(L, "path", LUA_PATH_VAR, LUA_PATH_DEFAULT);
  773.   setpath(L, "cpath", LUA_CPATH_VAR, LUA_CPATH_DEFAULT);
  774.   /* store config information */
  775.   lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATH_SEP "\n" LUA_PATH_MARK "\n"
  776.                      LUA_EXEC_DIR "\n" LUA_IGMARK "\n");
  777.   lua_setfield(L, -2, "config");
  778.   /* set field 'loaded' */
  779.   luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE);
  780.   lua_setfield(L, -2, "loaded");
  781.   /* set field 'preload' */
  782.   luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE);
  783.   lua_setfield(L, -2, "preload");
  784.   lua_pushglobaltable(L);
  785.   lua_pushvalue(L, -2);  /* set 'package' as upvalue for next lib */
  786.   luaL_setfuncs(L, ll_funcs, 1);  /* open lib into global table */
  787.   lua_pop(L, 1);  /* pop global table */
  788.   return 1;  /* return 'package' table */
  789. }
  790.  
  791.