Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2. ** $Id: loadlib.c,v 1.108 2011/12/12 16:34:03 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. #define LIBPREFIX       "LOADLIB: "
  96.  
  97. #define POF             LUA_POF
  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.  
  252. static void **ll_register (lua_State *L, const char *path) {
  253.   void **plib;
  254.   lua_pushfstring(L, "%s%s", LIBPREFIX, path);
  255.   lua_gettable(L, LUA_REGISTRYINDEX);  /* check library in registry? */
  256.   if (!lua_isnil(L, -1))  /* is there an entry? */
  257.     plib = (void **)lua_touserdata(L, -1);
  258.   else {  /* no entry yet; create one */
  259.     lua_pop(L, 1);  /* remove result from gettable */
  260.     plib = (void **)lua_newuserdata(L, sizeof(const void *));
  261.     *plib = NULL;
  262.     luaL_setmetatable(L, "_LOADLIB");
  263.     lua_pushfstring(L, "%s%s", LIBPREFIX, path);
  264.     lua_pushvalue(L, -2);
  265.     lua_settable(L, LUA_REGISTRYINDEX);
  266.   }
  267.   return plib;
  268. }
  269.  
  270.  
  271. /*
  272. ** __gc tag method: calls library's `ll_unloadlib' function with the lib
  273. ** handle
  274. */
  275. static int gctm (lua_State *L) {
  276.   void **lib = (void **)luaL_checkudata(L, 1, "_LOADLIB");
  277.   if (*lib) ll_unloadlib(*lib);
  278.   *lib = NULL;  /* mark library as closed */
  279.   return 0;
  280. }
  281.  
  282.  
  283. static int ll_loadfunc (lua_State *L, const char *path, const char *sym) {
  284.   void **reg = ll_register(L, path);
  285.   if (*reg == NULL) *reg = ll_load(L, path, *sym == '*');
  286.   if (*reg == NULL) return ERRLIB;  /* unable to load library */
  287.   if (*sym == '*') {  /* loading only library (no function)? */
  288.     lua_pushboolean(L, 1);  /* return 'true' */
  289.     return 0;  /* no errors */
  290.   }
  291.   else {
  292.     lua_CFunction f = ll_sym(L, *reg, sym);
  293.     if (f == NULL)
  294.       return ERRFUNC;  /* unable to find function */
  295.     lua_pushcfunction(L, f);  /* else create new function */
  296.     return 0;  /* no errors */
  297.   }
  298. }
  299.  
  300.  
  301. static int ll_loadlib (lua_State *L) {
  302.   const char *path = luaL_checkstring(L, 1);
  303.   const char *init = luaL_checkstring(L, 2);
  304.   int stat = ll_loadfunc(L, path, init);
  305.   if (stat == 0)  /* no errors? */
  306.     return 1;  /* return the loaded function */
  307.   else {  /* error; error message is on stack top */
  308.     lua_pushnil(L);
  309.     lua_insert(L, -2);
  310.     lua_pushstring(L, (stat == ERRLIB) ?  LIB_FAIL : "init");
  311.     return 3;  /* return nil, error message, and where */
  312.   }
  313. }
  314.  
  315.  
  316.  
  317. /*
  318. ** {======================================================
  319. ** 'require' function
  320. ** =======================================================
  321. */
  322.  
  323.  
  324. static int readable (const char *filename) {
  325.   FILE *f = fopen(filename, "r");  /* try to open file */
  326.   if (f == NULL) return 0;  /* open failed */
  327.   fclose(f);
  328.   return 1;
  329. }
  330.  
  331.  
  332. static const char *pushnexttemplate (lua_State *L, const char *path) {
  333.   const char *l;
  334.   while (*path == *LUA_PATH_SEP) path++;  /* skip separators */
  335.   if (*path == '\0') return NULL;  /* no more templates */
  336.   l = strchr(path, *LUA_PATH_SEP);  /* find next separator */
  337.   if (l == NULL) l = path + strlen(path);
  338.   lua_pushlstring(L, path, l - path);  /* template */
  339.   return l;
  340. }
  341.  
  342.  
  343. static const char *searchpath (lua_State *L, const char *name,
  344.                                              const char *path,
  345.                                              const char *sep,
  346.                                              const char *dirsep) {
  347.   luaL_Buffer msg;  /* to build error message */
  348.   luaL_buffinit(L, &msg);
  349.   if (*sep != '\0')  /* non-empty separator? */
  350.     name = luaL_gsub(L, name, sep, dirsep);  /* replace it by 'dirsep' */
  351.   while ((path = pushnexttemplate(L, path)) != NULL) {
  352.     const char *filename = luaL_gsub(L, lua_tostring(L, -1),
  353.                                      LUA_PATH_MARK, name);
  354.     lua_remove(L, -2);  /* remove path template */
  355.     if (readable(filename))  /* does file exist and is readable? */
  356.       return filename;  /* return that file name */
  357.     lua_pushfstring(L, "\n\tno file " LUA_QS, filename);
  358.     lua_remove(L, -2);  /* remove file name */
  359.     luaL_addvalue(&msg);  /* concatenate error msg. entry */
  360.   }
  361.   luaL_pushresult(&msg);  /* create error message */
  362.   return NULL;  /* not found */
  363. }
  364.  
  365.  
  366. static int ll_searchpath (lua_State *L) {
  367.   const char *f = searchpath(L, luaL_checkstring(L, 1),
  368.                                 luaL_checkstring(L, 2),
  369.                                 luaL_optstring(L, 3, "."),
  370.                                 luaL_optstring(L, 4, LUA_DIRSEP));
  371.   if (f != NULL) return 1;
  372.   else {  /* error message is on top of the stack */
  373.     lua_pushnil(L);
  374.     lua_insert(L, -2);
  375.     return 2;  /* return nil + error message */
  376.   }
  377. }
  378.  
  379.  
  380. static const char *findfile (lua_State *L, const char *name,
  381.                                            const char *pname,
  382.                                            const char *dirsep) {
  383.   const char *path;
  384.   lua_getfield(L, lua_upvalueindex(1), pname);
  385.   path = lua_tostring(L, -1);
  386.   if (path == NULL)
  387.     luaL_error(L, LUA_QL("package.%s") " must be a string", pname);
  388.   return searchpath(L, name, path, ".", dirsep);
  389. }
  390.  
  391.  
  392. static int checkload (lua_State *L, int stat, const char *filename) {
  393.   if (stat) {  /* module loaded successfully? */
  394.     lua_pushstring(L, filename);  /* will be 2nd argument to module */
  395.     return 2;  /* return open function and file name */
  396.   }
  397.   else
  398.     return luaL_error(L, "error loading module " LUA_QS
  399.                          " from file " LUA_QS ":\n\t%s",
  400.                           lua_tostring(L, 1), filename, lua_tostring(L, -1));
  401. }
  402.  
  403.  
  404. static int searcher_Lua (lua_State *L) {
  405.   const char *filename;
  406.   const char *name = luaL_checkstring(L, 1);
  407.   filename = findfile(L, name, "path", LUA_LSUBSEP);
  408.   if (filename == NULL) return 1;  /* module not found in this path */
  409.   return checkload(L, (luaL_loadfile(L, filename) == LUA_OK), filename);
  410. }
  411.  
  412.  
  413. static int loadfunc (lua_State *L, const char *filename, const char *modname) {
  414.   const char *funcname;
  415.   const char *mark;
  416.   modname = luaL_gsub(L, modname, ".", LUA_OFSEP);
  417.   mark = strchr(modname, *LUA_IGMARK);
  418.   if (mark) {
  419.     int stat;
  420.     funcname = lua_pushlstring(L, modname, mark - modname);
  421.     funcname = lua_pushfstring(L, POF"%s", funcname);
  422.     stat = ll_loadfunc(L, filename, funcname);
  423.     if (stat != ERRFUNC) return stat;
  424.     modname = mark + 1;  /* else go ahead and try old-style name */
  425.   }
  426.   funcname = lua_pushfstring(L, POF"%s", modname);
  427.   return ll_loadfunc(L, filename, funcname);
  428. }
  429.  
  430.  
  431. static int searcher_C (lua_State *L) {
  432.   const char *name = luaL_checkstring(L, 1);
  433.   const char *filename = findfile(L, name, "cpath", LUA_CSUBSEP);
  434.   if (filename == NULL) return 1;  /* module not found in this path */
  435.   return checkload(L, (loadfunc(L, filename, name) == 0), filename);
  436. }
  437.  
  438.  
  439. static int searcher_Croot (lua_State *L) {
  440.   const char *filename;
  441.   const char *name = luaL_checkstring(L, 1);
  442.   const char *p = strchr(name, '.');
  443.   int stat;
  444.   if (p == NULL) return 0;  /* is root */
  445.   lua_pushlstring(L, name, p - name);
  446.   filename = findfile(L, lua_tostring(L, -1), "cpath", LUA_CSUBSEP);
  447.   if (filename == NULL) return 1;  /* root not found */
  448.   if ((stat = loadfunc(L, filename, name)) != 0) {
  449.     if (stat != ERRFUNC)
  450.       return checkload(L, 0, filename);  /* real error */
  451.     else {  /* open function not found */
  452.       lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS,
  453.                          name, filename);
  454.       return 1;
  455.     }
  456.   }
  457.   lua_pushstring(L, filename);  /* will be 2nd argument to module */
  458.   return 2;
  459. }
  460.  
  461.  
  462. static int searcher_preload (lua_State *L) {
  463.   const char *name = luaL_checkstring(L, 1);
  464.   lua_getfield(L, LUA_REGISTRYINDEX, "_PRELOAD");
  465.   lua_getfield(L, -1, name);
  466.   if (lua_isnil(L, -1))  /* not found? */
  467.     lua_pushfstring(L, "\n\tno field package.preload['%s']", name);
  468.   return 1;
  469. }
  470.  
  471.  
  472. static void findloader (lua_State *L, const char *name) {
  473.   int i;
  474.   luaL_Buffer msg;  /* to build error message */
  475.   luaL_buffinit(L, &msg);
  476.   lua_getfield(L, lua_upvalueindex(1), "searchers");  /* will be at index 3 */
  477.   if (!lua_istable(L, 3))
  478.     luaL_error(L, LUA_QL("package.searchers") " must be a table");
  479.   /*  iterate over available seachers to find a loader */
  480.   for (i = 1; ; i++) {
  481.     lua_rawgeti(L, 3, i);  /* get a seacher */
  482.     if (lua_isnil(L, -1)) {  /* no more searchers? */
  483.       lua_pop(L, 1);  /* remove nil */
  484.       luaL_pushresult(&msg);  /* create error message */
  485.       luaL_error(L, "module " LUA_QS " not found:%s",
  486.                     name, lua_tostring(L, -1));
  487.     }
  488.     lua_pushstring(L, name);
  489.     lua_call(L, 1, 2);  /* call it */
  490.     if (lua_isfunction(L, -2))  /* did it find a loader? */
  491.       return;  /* module loader found */
  492.     else if (lua_isstring(L, -2)) {  /* searcher returned error message? */
  493.       lua_pop(L, 1);  /* remove extra return */
  494.       luaL_addvalue(&msg);  /* concatenate error message */
  495.     }
  496.     else
  497.       lua_pop(L, 2);  /* remove both returns */
  498.   }
  499. }
  500.  
  501.  
  502. static int ll_require (lua_State *L) {
  503.   const char *name = luaL_checkstring(L, 1);
  504.   lua_settop(L, 1);  /* _LOADED table will be at index 2 */
  505.   lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
  506.   lua_getfield(L, 2, name);  /* _LOADED[name] */
  507.   if (lua_toboolean(L, -1))  /* is it there? */
  508.     return 1;  /* package is already loaded */
  509.   /* else must load package */
  510.   lua_pop(L, 1);  /* remove 'getfield' result */
  511.   findloader(L, name);
  512.   lua_pushstring(L, name);  /* pass name as argument to module loader */
  513.   lua_insert(L, -2);  /* name is 1st argument (before search data) */
  514.   lua_call(L, 2, 1);  /* run loader to load module */
  515.   if (!lua_isnil(L, -1))  /* non-nil return? */
  516.     lua_setfield(L, 2, name);  /* _LOADED[name] = returned value */
  517.   lua_getfield(L, 2, name);
  518.   if (lua_isnil(L, -1)) {   /* module did not set a value? */
  519.     lua_pushboolean(L, 1);  /* use true as result */
  520.     lua_pushvalue(L, -1);  /* extra copy to be returned */
  521.     lua_setfield(L, 2, name);  /* _LOADED[name] = true */
  522.   }
  523.   return 1;
  524. }
  525.  
  526. /* }====================================================== */
  527.  
  528.  
  529.  
  530. /*
  531. ** {======================================================
  532. ** 'module' function
  533. ** =======================================================
  534. */
  535. #if defined(LUA_COMPAT_MODULE)
  536.  
  537. /*
  538. ** changes the environment variable of calling function
  539. */
  540. static void set_env (lua_State *L) {
  541.   lua_Debug ar;
  542.   if (lua_getstack(L, 1, &ar) == 0 ||
  543.       lua_getinfo(L, "f", &ar) == 0 ||  /* get calling function */
  544.       lua_iscfunction(L, -1))
  545.     luaL_error(L, LUA_QL("module") " not called from a Lua function");
  546.   lua_pushvalue(L, -2);  /* copy new environment table to top */
  547.   lua_setupvalue(L, -2, 1);
  548.   lua_pop(L, 1);  /* remove function */
  549. }
  550.  
  551.  
  552. static void dooptions (lua_State *L, int n) {
  553.   int i;
  554.   for (i = 2; i <= n; i++) {
  555.     if (lua_isfunction(L, i)) {  /* avoid 'calling' extra info. */
  556.       lua_pushvalue(L, i);  /* get option (a function) */
  557.       lua_pushvalue(L, -2);  /* module */
  558.       lua_call(L, 1, 0);
  559.     }
  560.   }
  561. }
  562.  
  563.  
  564. static void modinit (lua_State *L, const char *modname) {
  565.   const char *dot;
  566.   lua_pushvalue(L, -1);
  567.   lua_setfield(L, -2, "_M");  /* module._M = module */
  568.   lua_pushstring(L, modname);
  569.   lua_setfield(L, -2, "_NAME");
  570.   dot = strrchr(modname, '.');  /* look for last dot in module name */
  571.   if (dot == NULL) dot = modname;
  572.   else dot++;
  573.   /* set _PACKAGE as package name (full module name minus last part) */
  574.   lua_pushlstring(L, modname, dot - modname);
  575.   lua_setfield(L, -2, "_PACKAGE");
  576. }
  577.  
  578.  
  579. static int ll_module (lua_State *L) {
  580.   const char *modname = luaL_checkstring(L, 1);
  581.   int lastarg = lua_gettop(L);  /* last parameter */
  582.   luaL_pushmodule(L, modname, 1);  /* get/create module table */
  583.   /* check whether table already has a _NAME field */
  584.   lua_getfield(L, -1, "_NAME");
  585.   if (!lua_isnil(L, -1))  /* is table an initialized module? */
  586.     lua_pop(L, 1);
  587.   else {  /* no; initialize it */
  588.     lua_pop(L, 1);
  589.     modinit(L, modname);
  590.   }
  591.   lua_pushvalue(L, -1);
  592.   set_env(L);
  593.   dooptions(L, lastarg);
  594.   return 1;
  595. }
  596.  
  597.  
  598. static int ll_seeall (lua_State *L) {
  599.   luaL_checktype(L, 1, LUA_TTABLE);
  600.   if (!lua_getmetatable(L, 1)) {
  601.     lua_createtable(L, 0, 1); /* create new metatable */
  602.     lua_pushvalue(L, -1);
  603.     lua_setmetatable(L, 1);
  604.   }
  605.   lua_pushglobaltable(L);
  606.   lua_setfield(L, -2, "__index");  /* mt.__index = _G */
  607.   return 0;
  608. }
  609.  
  610. #endif
  611. /* }====================================================== */
  612.  
  613.  
  614.  
  615. /* auxiliary mark (for internal use) */
  616. #define AUXMARK         "\1"
  617.  
  618.  
  619. /*
  620. ** return registry.LUA_NOENV as a boolean
  621. */
  622. static int noenv (lua_State *L) {
  623.   int b;
  624.   lua_getfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");
  625.   b = lua_toboolean(L, -1);
  626.   lua_pop(L, 1);  /* remove value */
  627.   return b;
  628. }
  629.  
  630.  
  631. static void setpath (lua_State *L, const char *fieldname, const char *envname1,
  632.                                    const char *envname2, const char *def) {
  633.   const char *path = getenv(envname1);
  634.   if (path == NULL)  /* no environment variable? */
  635.     path = getenv(envname2);  /* try alternative name */
  636.   if (path == NULL || noenv(L))  /* no environment variable? */
  637.     lua_pushstring(L, def);  /* use default */
  638.   else {
  639.     /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */
  640.     path = luaL_gsub(L, path, LUA_PATH_SEP LUA_PATH_SEP,
  641.                               LUA_PATH_SEP AUXMARK LUA_PATH_SEP);
  642.     luaL_gsub(L, path, AUXMARK, def);
  643.     lua_remove(L, -2);
  644.   }
  645.   setprogdir(L);
  646.   lua_setfield(L, -2, fieldname);
  647. }
  648.  
  649.  
  650. static const luaL_Reg pk_funcs[] = {
  651.   {"loadlib", ll_loadlib},
  652.   {"searchpath", ll_searchpath},
  653. #if defined(LUA_COMPAT_MODULE)
  654.   {"seeall", ll_seeall},
  655. #endif
  656.   {NULL, NULL}
  657. };
  658.  
  659.  
  660. static const luaL_Reg ll_funcs[] = {
  661. #if defined(LUA_COMPAT_MODULE)
  662.   {"module", ll_module},
  663. #endif
  664.   {"require", ll_require},
  665.   {NULL, NULL}
  666. };
  667.  
  668.  
  669. static const lua_CFunction searchers[] =
  670.   {searcher_preload, searcher_Lua, searcher_C, searcher_Croot, NULL};
  671.  
  672.  
  673. LUAMOD_API int luaopen_package (lua_State *L) {
  674.   int i;
  675.   /* create new type _LOADLIB */
  676.   luaL_newmetatable(L, "_LOADLIB");
  677.   lua_pushcfunction(L, gctm);
  678.   lua_setfield(L, -2, "__gc");
  679.   /* create `package' table */
  680.   luaL_newlib(L, pk_funcs);
  681.   /* create 'searchers' table */
  682.   lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0);
  683.   /* fill it with pre-defined searchers */
  684.   for (i=0; searchers[i] != NULL; i++) {
  685.     lua_pushvalue(L, -2);  /* set 'package' as upvalue for all searchers */
  686.     lua_pushcclosure(L, searchers[i], 1);
  687.     lua_rawseti(L, -2, i+1);
  688.   }
  689. #if defined(LUA_COMPAT_LOADERS)
  690.   lua_pushvalue(L, -1);  /* make a copy of 'searchers' table */
  691.   lua_setfield(L, -3, "loaders");  /* put it in field `loaders' */
  692. #endif
  693.   lua_setfield(L, -2, "searchers");  /* put it in field 'searchers' */
  694.   /* set field 'path' */
  695.   setpath(L, "path", LUA_PATHVERSION, LUA_PATH, LUA_PATH_DEFAULT);
  696.   /* set field 'cpath' */
  697.   setpath(L, "cpath", LUA_CPATHVERSION, LUA_CPATH, LUA_CPATH_DEFAULT);
  698.   /* store config information */
  699.   lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATH_SEP "\n" LUA_PATH_MARK "\n"
  700.                      LUA_EXEC_DIR "\n" LUA_IGMARK "\n");
  701.   lua_setfield(L, -2, "config");
  702.   /* set field `loaded' */
  703.   luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED");
  704.   lua_setfield(L, -2, "loaded");
  705.   /* set field `preload' */
  706.   luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD");
  707.   lua_setfield(L, -2, "preload");
  708.   lua_pushglobaltable(L);
  709.   lua_pushvalue(L, -2);  /* set 'package' as upvalue for next lib */
  710.   luaL_setfuncs(L, ll_funcs, 1);  /* open lib into global table */
  711.   lua_pop(L, 1);  /* pop global table */
  712.   return 1;  /* return 'package' table */
  713. }
  714.  
  715.