?login_element?

Subversion Repositories NedoOS

Rev

Blame | Last modification | View Log | Download

  1. /*
  2. ** $Id: loadlib.c,v 1.52.1.4 2009/09/09 13:17:16 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 Darwin (Mac OS X), an
  8. ** implementation for Windows, and a stub for other systems.
  9. */
  10.  
  11.  
  12. #include <stdlib.h>
  13. #include <string.h>
  14.  
  15.  
  16. #define loadlib_c
  17. #define LUA_LIB
  18.  
  19. #include "lua.h"
  20.  
  21. #include "lauxlib.h"
  22. #include "lualib.h"
  23.  
  24.  
  25. /* prefix for open functions in C libraries */
  26. #define LUA_POF         "luaopen_"
  27.  
  28. /* separator for open functions in C libraries */
  29. #define LUA_OFSEP       "_"
  30.  
  31.  
  32. #define LIBPREFIX       "LOADLIB: "
  33.  
  34. #define POF             LUA_POF
  35. #define LIB_FAIL        "open"
  36.  
  37.  
  38. /* error codes for ll_loadfunc */
  39. #define ERRLIB          1
  40. #define ERRFUNC         2
  41.  
  42. #define setprogdir(L)           ((void)0)
  43.  
  44.  
  45. static void ll_unloadlib (void *lib);
  46. static void *ll_load (lua_State *L, const char *path);
  47. static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym);
  48.  
  49.  
  50.  
  51. #if defined(LUA_DL_DLOPEN)
  52. /*
  53. ** {========================================================================
  54. ** This is an implementation of loadlib based on the dlfcn interface.
  55. ** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD,
  56. ** NetBSD, AIX 4.2, HPUX 11, and  probably most other Unix flavors, at least
  57. ** as an emulation layer on top of native functions.
  58. ** =========================================================================
  59. */
  60.  
  61. #include <dlfcn.h>
  62.  
  63. static void ll_unloadlib (void *lib) {
  64.   dlclose(lib);
  65. }
  66.  
  67.  
  68. static void *ll_load (lua_State *L, const char *path) {
  69.   void *lib = dlopen(path, RTLD_NOW);
  70.   if (lib == NULL) lua_pushstring(L, dlerror());
  71.   return lib;
  72. }
  73.  
  74.  
  75. static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
  76.   lua_CFunction f = (lua_CFunction)dlsym(lib, sym);
  77.   if (f == NULL) lua_pushstring(L, dlerror());
  78.   return f;
  79. }
  80.  
  81. /* }====================================================== */
  82.  
  83.  
  84.  
  85. #elif defined(LUA_DL_DLL)
  86. /*
  87. ** {======================================================================
  88. ** This is an implementation of loadlib for Windows using native functions.
  89. ** =======================================================================
  90. */
  91.  
  92. #include <windows.h>
  93.  
  94.  
  95. #undef setprogdir
  96.  
  97. static void setprogdir (lua_State *L) {
  98.   char buff[MAX_PATH + 1];
  99.   char *lb;
  100.   DWORD nsize = sizeof(buff)/sizeof(char);
  101.   DWORD n = GetModuleFileNameA(NULL, buff, nsize);
  102.   if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL)
  103.     luaL_error(L, "unable to get ModuleFileName");
  104.   else {
  105.     *lb = '\0';
  106.     luaL_gsub(L, lua_tostring(L, -1), LUA_EXECDIR, buff);
  107.     lua_remove(L, -2);  /* remove original string */
  108.   }
  109. }
  110.  
  111.  
  112. static void pusherror (lua_State *L) {
  113.   int error = GetLastError();
  114.   char buffer[128];
  115.   if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
  116.       NULL, error, 0, buffer, sizeof(buffer), NULL))
  117.     lua_pushstring(L, buffer);
  118.   else
  119.     lua_pushfstring(L, "system error %d\n", error);
  120. }
  121.  
  122. static void ll_unloadlib (void *lib) {
  123.   FreeLibrary((HINSTANCE)lib);
  124. }
  125.  
  126.  
  127. static void *ll_load (lua_State *L, const char *path) {
  128.   HINSTANCE lib = LoadLibraryA(path);
  129.   if (lib == NULL) pusherror(L);
  130.   return lib;
  131. }
  132.  
  133.  
  134. static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
  135.   lua_CFunction f = (lua_CFunction)GetProcAddress((HINSTANCE)lib, sym);
  136.   if (f == NULL) pusherror(L);
  137.   return f;
  138. }
  139.  
  140. /* }====================================================== */
  141.  
  142.  
  143.  
  144. #elif defined(LUA_DL_DYLD)
  145. /*
  146. ** {======================================================================
  147. ** Native Mac OS X / Darwin Implementation
  148. ** =======================================================================
  149. */
  150.  
  151. #include <mach-o/dyld.h>
  152.  
  153.  
  154. /* Mac appends a `_' before C function names */
  155. #undef POF
  156. #define POF     "_" LUA_POF
  157.  
  158.  
  159. static void pusherror (lua_State *L) {
  160.   const char *err_str;
  161.   const char *err_file;
  162.   NSLinkEditErrors err;
  163.   int err_num;
  164.   NSLinkEditError(&err, &err_num, &err_file, &err_str);
  165.   lua_pushstring(L, err_str);
  166. }
  167.  
  168.  
  169. static const char *errorfromcode (NSObjectFileImageReturnCode ret) {
  170.   switch (ret) {
  171.     case NSObjectFileImageInappropriateFile:
  172.       return "file is not a bundle";
  173.     case NSObjectFileImageArch:
  174.       return "library is for wrong CPU type";
  175.     case NSObjectFileImageFormat:
  176.       return "bad format";
  177.     case NSObjectFileImageAccess:
  178.       return "cannot access file";
  179.     case NSObjectFileImageFailure:
  180.     default:
  181.       return "unable to load library";
  182.   }
  183. }
  184.  
  185.  
  186. static void ll_unloadlib (void *lib) {
  187.   NSUnLinkModule((NSModule)lib, NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES);
  188. }
  189.  
  190.  
  191. static void *ll_load (lua_State *L, const char *path) {
  192.   NSObjectFileImage img;
  193.   NSObjectFileImageReturnCode ret;
  194.   /* this would be a rare case, but prevents crashing if it happens */
  195.   if(!_dyld_present()) {
  196.     lua_pushliteral(L, "dyld not present");
  197.     return NULL;
  198.   }
  199.   ret = NSCreateObjectFileImageFromFile(path, &img);
  200.   if (ret == NSObjectFileImageSuccess) {
  201.     NSModule mod = NSLinkModule(img, path, NSLINKMODULE_OPTION_PRIVATE |
  202.                        NSLINKMODULE_OPTION_RETURN_ON_ERROR);
  203.     NSDestroyObjectFileImage(img);
  204.     if (mod == NULL) pusherror(L);
  205.     return mod;
  206.   }
  207.   lua_pushstring(L, errorfromcode(ret));
  208.   return NULL;
  209. }
  210.  
  211.  
  212. static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
  213.   NSSymbol nss = NSLookupSymbolInModule((NSModule)lib, sym);
  214.   if (nss == NULL) {
  215.     lua_pushfstring(L, "symbol " LUA_QS " not found", sym);
  216.     return NULL;
  217.   }
  218.   return (lua_CFunction)NSAddressOfSymbol(nss);
  219. }
  220.  
  221. /* }====================================================== */
  222.  
  223.  
  224.  
  225. #else
  226. /*
  227. ** {======================================================
  228. ** Fallback for other systems
  229. ** =======================================================
  230. */
  231.  
  232. #undef LIB_FAIL
  233. #define LIB_FAIL        "absent"
  234.  
  235.  
  236. #define DLMSG   "dynamic libraries not enabled; check your Lua installation"
  237.  
  238.  
  239. static void ll_unloadlib (void *lib) {
  240.   (void)lib;  /* to avoid warnings */
  241. }
  242.  
  243.  
  244. static void *ll_load (lua_State *L, const char *path) {
  245.   (void)path;  /* to avoid warnings */
  246.   lua_pushliteral(L, DLMSG);
  247.   return NULL;
  248. }
  249.  
  250.  
  251. static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
  252.   (void)lib; (void)sym;  /* to avoid warnings */
  253.   lua_pushliteral(L, DLMSG);
  254.   return NULL;
  255. }
  256.  
  257. /* }====================================================== */
  258. #endif
  259.  
  260.  
  261.  
  262. static void **ll_register (lua_State *L, const char *path) {
  263.   void **plib;
  264.   lua_pushfstring(L, "%s%s", LIBPREFIX, path);
  265.   lua_gettable(L, LUA_REGISTRYINDEX);  /* check library in registry? */
  266.   if (!lua_isnil(L, -1))  /* is there an entry? */
  267.     plib = (void **)lua_touserdata(L, -1);
  268.   else {  /* no entry yet; create one */
  269.     lua_pop(L, 1);
  270.     plib = (void **)lua_newuserdata(L, sizeof(const void *));
  271.     *plib = NULL;
  272.     luaL_getmetatable(L, "_LOADLIB");
  273.     lua_setmetatable(L, -2);
  274.     lua_pushfstring(L, "%s%s", LIBPREFIX, path);
  275.     lua_pushvalue(L, -2);
  276.     lua_settable(L, LUA_REGISTRYINDEX);
  277.   }
  278.   return plib;
  279. }
  280.  
  281.  
  282. /*
  283. ** __gc tag method: calls library's `ll_unloadlib' function with the lib
  284. ** handle
  285. */
  286. static int gctm (lua_State *L) {
  287.   void **lib = (void **)luaL_checkudata(L, 1, "_LOADLIB");
  288.   if (*lib) ll_unloadlib(*lib);
  289.   *lib = NULL;  /* mark library as closed */
  290.   return 0;
  291. }
  292.  
  293.  
  294. static int ll_loadfunc (lua_State *L, const char *path, const char *sym) {
  295.   void **reg = ll_register(L, path);
  296.   if (*reg == NULL) *reg = ll_load(L, path);
  297.   if (*reg == NULL)
  298.     return ERRLIB;  /* unable to load library */
  299.   else {
  300.     lua_CFunction f = ll_sym(L, *reg, sym);
  301.     if (f == NULL)
  302.       return ERRFUNC;  /* unable to find function */
  303.     lua_pushcfunction(L, f);
  304.     return 0;  /* return function */
  305.   }
  306. }
  307.  
  308.  
  309. static int ll_loadlib (lua_State *L) {
  310.   const char *path = luaL_checkstring(L, 1);
  311.   const char *init = luaL_checkstring(L, 2);
  312.   int stat = ll_loadfunc(L, path, init);
  313.   if (stat == 0)  /* no errors? */
  314.     return 1;  /* return the loaded function */
  315.   else {  /* error; error message is on stack top */
  316.     lua_pushnil(L);
  317.     lua_insert(L, -2);
  318.     lua_pushstring(L, (stat == ERRLIB) ?  LIB_FAIL : "init");
  319.     return 3;  /* return nil, error message, and where */
  320.   }
  321. }
  322.  
  323.  
  324.  
  325. /*
  326. ** {======================================================
  327. ** 'require' function
  328. ** =======================================================
  329. */
  330.  
  331.  
  332. static int readable (const char *filename) {
  333.   FILE *f = fopen(filename, "r");  /* try to open file */
  334.   if (f == NULL) return 0;  /* open failed */
  335.   fclose(f);
  336.   return 1;
  337. }
  338.  
  339.  
  340. static const char *pushnexttemplate (lua_State *L, const char *path) {
  341.   const char *l;
  342.   while (*path == *LUA_PATHSEP) path++;  /* skip separators */
  343.   if (*path == '\0') return NULL;  /* no more templates */
  344.   l = strchr(path, *LUA_PATHSEP);  /* find next separator */
  345.   if (l == NULL) l = path + strlen(path);
  346.   lua_pushlstring(L, path, l - path);  /* template */
  347.   return l;
  348. }
  349.  
  350.  
  351. static const char *findfile (lua_State *L, const char *name,
  352.                                            const char *pname) {
  353.   const char *path;
  354.   name = luaL_gsub(L, name, ".", LUA_DIRSEP);
  355.   lua_getfield(L, LUA_ENVIRONINDEX, pname);
  356.   path = lua_tostring(L, -1);
  357.   if (path == NULL)
  358.     luaL_error(L, LUA_QL("package.%s") " must be a string", pname);
  359.   lua_pushliteral(L, "");  /* error accumulator */
  360.   while ((path = pushnexttemplate(L, path)) != NULL) {
  361.     const char *filename;
  362.     filename = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name);
  363.     lua_remove(L, -2);  /* remove path template */
  364.     if (readable(filename))  /* does file exist and is readable? */
  365.       return filename;  /* return that file name */
  366.     lua_pushfstring(L, "\n\tno file " LUA_QS, filename);
  367.     lua_remove(L, -2);  /* remove file name */
  368.     lua_concat(L, 2);  /* add entry to possible error message */
  369.   }
  370.   return NULL;  /* not found */
  371. }
  372.  
  373.  
  374. static void loaderror (lua_State *L, const char *filename) {
  375.   luaL_error(L, "error loading module " LUA_QS " from file " LUA_QS ":\n\t%s",
  376.                 lua_tostring(L, 1), filename, lua_tostring(L, -1));
  377. }
  378.  
  379.  
  380. static int loader_Lua (lua_State *L) {
  381.   const char *filename;
  382.   const char *name = luaL_checkstring(L, 1);
  383.   filename = findfile(L, name, "path");
  384.   if (filename == NULL) return 1;  /* library not found in this path */
  385.   if (luaL_loadfile(L, filename) != 0)
  386.     loaderror(L, filename);
  387.   return 1;  /* library loaded successfully */
  388. }
  389.  
  390.  
  391. static const char *mkfuncname (lua_State *L, const char *modname) {
  392.   const char *funcname;
  393.   const char *mark = strchr(modname, *LUA_IGMARK);
  394.   if (mark) modname = mark + 1;
  395.   funcname = luaL_gsub(L, modname, ".", LUA_OFSEP);
  396.   funcname = lua_pushfstring(L, POF"%s", funcname);
  397.   lua_remove(L, -2);  /* remove 'gsub' result */
  398.   return funcname;
  399. }
  400.  
  401.  
  402. static int loader_C (lua_State *L) {
  403.   const char *funcname;
  404.   const char *name = luaL_checkstring(L, 1);
  405.   const char *filename = findfile(L, name, "cpath");
  406.   if (filename == NULL) return 1;  /* library not found in this path */
  407.   funcname = mkfuncname(L, name);
  408.   if (ll_loadfunc(L, filename, funcname) != 0)
  409.     loaderror(L, filename);
  410.   return 1;  /* library loaded successfully */
  411. }
  412.  
  413.  
  414. static int loader_Croot (lua_State *L) {
  415.   const char *funcname;
  416.   const char *filename;
  417.   const char *name = luaL_checkstring(L, 1);
  418.   const char *p = strchr(name, '.');
  419.   int stat;
  420.   if (p == NULL) return 0;  /* is root */
  421.   lua_pushlstring(L, name, p - name);
  422.   filename = findfile(L, lua_tostring(L, -1), "cpath");
  423.   if (filename == NULL) return 1;  /* root not found */
  424.   funcname = mkfuncname(L, name);
  425.   if ((stat = ll_loadfunc(L, filename, funcname)) != 0) {
  426.     if (stat != ERRFUNC) loaderror(L, filename);  /* real error */
  427.     lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS,
  428.                        name, filename);
  429.     return 1;  /* function not found */
  430.   }
  431.   return 1;
  432. }
  433.  
  434.  
  435. static int loader_preload (lua_State *L) {
  436.   const char *name = luaL_checkstring(L, 1);
  437.   lua_getfield(L, LUA_ENVIRONINDEX, "preload");
  438.   if (!lua_istable(L, -1))
  439.     luaL_error(L, LUA_QL("package.preload") " must be a table");
  440.   lua_getfield(L, -1, name);
  441.   if (lua_isnil(L, -1))  /* not found? */
  442.     lua_pushfstring(L, "\n\tno field package.preload['%s']", name);
  443.   return 1;
  444. }
  445.  
  446.  
  447. static const int sentinel_ = 0;
  448. #define sentinel        ((void *)&sentinel_)
  449.  
  450.  
  451. static int ll_require (lua_State *L) {
  452.   const char *name = luaL_checkstring(L, 1);
  453.   int i;
  454.   lua_settop(L, 1);  /* _LOADED table will be at index 2 */
  455.   lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
  456.   lua_getfield(L, 2, name);
  457.   if (lua_toboolean(L, -1)) {  /* is it there? */
  458.     if (lua_touserdata(L, -1) == sentinel)  /* check loops */
  459.       luaL_error(L, "loop or previous error loading module " LUA_QS, name);
  460.     return 1;  /* package is already loaded */
  461.   }
  462.   /* else must load it; iterate over available loaders */
  463.   lua_getfield(L, LUA_ENVIRONINDEX, "loaders");
  464.   if (!lua_istable(L, -1))
  465.     luaL_error(L, LUA_QL("package.loaders") " must be a table");
  466.   lua_pushliteral(L, "");  /* error message accumulator */
  467.   for (i=1; ; i++) {
  468.     lua_rawgeti(L, -2, i);  /* get a loader */
  469.     if (lua_isnil(L, -1))
  470.       luaL_error(L, "module " LUA_QS " not found:%s",
  471.                     name, lua_tostring(L, -2));
  472.     lua_pushstring(L, name);
  473.     lua_call(L, 1, 1);  /* call it */
  474.     if (lua_isfunction(L, -1))  /* did it find module? */
  475.       break;  /* module loaded successfully */
  476.     else if (lua_isstring(L, -1))  /* loader returned error message? */
  477.       lua_concat(L, 2);  /* accumulate it */
  478.     else
  479.       lua_pop(L, 1);
  480.   }
  481.   lua_pushlightuserdata(L, sentinel);
  482.   lua_setfield(L, 2, name);  /* _LOADED[name] = sentinel */
  483.   lua_pushstring(L, name);  /* pass name as argument to module */
  484.   lua_call(L, 1, 1);  /* run loaded module */
  485.   if (!lua_isnil(L, -1))  /* non-nil return? */
  486.     lua_setfield(L, 2, name);  /* _LOADED[name] = returned value */
  487.   lua_getfield(L, 2, name);
  488.   if (lua_touserdata(L, -1) == sentinel) {   /* module did not set a value? */
  489.     lua_pushboolean(L, 1);  /* use true as result */
  490.     lua_pushvalue(L, -1);  /* extra copy to be returned */
  491.     lua_setfield(L, 2, name);  /* _LOADED[name] = true */
  492.   }
  493.   return 1;
  494. }
  495.  
  496. /* }====================================================== */
  497.  
  498.  
  499.  
  500. /*
  501. ** {======================================================
  502. ** 'module' function
  503. ** =======================================================
  504. */
  505.  
  506.  
  507. static void setfenv (lua_State *L) {
  508.   lua_Debug ar;
  509.   if (lua_getstack(L, 1, &ar) == 0 ||
  510.       lua_getinfo(L, "f", &ar) == 0 ||  /* get calling function */
  511.       lua_iscfunction(L, -1))
  512.     luaL_error(L, LUA_QL("module") " not called from a Lua function");
  513.   lua_pushvalue(L, -2);
  514.   lua_setfenv(L, -2);
  515.   lua_pop(L, 1);
  516. }
  517.  
  518.  
  519. static void dooptions (lua_State *L, int n) {
  520.   int i;
  521.   for (i = 2; i <= n; i++) {
  522.     lua_pushvalue(L, i);  /* get option (a function) */
  523.     lua_pushvalue(L, -2);  /* module */
  524.     lua_call(L, 1, 0);
  525.   }
  526. }
  527.  
  528.  
  529. static void modinit (lua_State *L, const char *modname) {
  530.   const char *dot;
  531.   lua_pushvalue(L, -1);
  532.   lua_setfield(L, -2, "_M");  /* module._M = module */
  533.   lua_pushstring(L, modname);
  534.   lua_setfield(L, -2, "_NAME");
  535.   dot = strrchr(modname, '.');  /* look for last dot in module name */
  536.   if (dot == NULL) dot = modname;
  537.   else dot++;
  538.   /* set _PACKAGE as package name (full module name minus last part) */
  539.   lua_pushlstring(L, modname, dot - modname);
  540.   lua_setfield(L, -2, "_PACKAGE");
  541. }
  542.  
  543.  
  544. static int ll_module (lua_State *L) {
  545.   const char *modname = luaL_checkstring(L, 1);
  546.   int loaded = lua_gettop(L) + 1;  /* index of _LOADED table */
  547.   lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
  548.   lua_getfield(L, loaded, modname);  /* get _LOADED[modname] */
  549.   if (!lua_istable(L, -1)) {  /* not found? */
  550.     lua_pop(L, 1);  /* remove previous result */
  551.     /* try global variable (and create one if it does not exist) */
  552.     if (luaL_findtable(L, LUA_GLOBALSINDEX, modname, 1) != NULL)
  553.       return luaL_error(L, "name conflict for module " LUA_QS, modname);
  554.     lua_pushvalue(L, -1);
  555.     lua_setfield(L, loaded, modname);  /* _LOADED[modname] = new table */
  556.   }
  557.   /* check whether table already has a _NAME field */
  558.   lua_getfield(L, -1, "_NAME");
  559.   if (!lua_isnil(L, -1))  /* is table an initialized module? */
  560.     lua_pop(L, 1);
  561.   else {  /* no; initialize it */
  562.     lua_pop(L, 1);
  563.     modinit(L, modname);
  564.   }
  565.   lua_pushvalue(L, -1);
  566.   setfenv(L);
  567.   dooptions(L, loaded - 1);
  568.   return 0;
  569. }
  570.  
  571.  
  572. static int ll_seeall (lua_State *L) {
  573.   luaL_checktype(L, 1, LUA_TTABLE);
  574.   if (!lua_getmetatable(L, 1)) {
  575.     lua_createtable(L, 0, 1); /* create new metatable */
  576.     lua_pushvalue(L, -1);
  577.     lua_setmetatable(L, 1);
  578.   }
  579.   lua_pushvalue(L, LUA_GLOBALSINDEX);
  580.   lua_setfield(L, -2, "__index");  /* mt.__index = _G */
  581.   return 0;
  582. }
  583.  
  584.  
  585. /* }====================================================== */
  586.  
  587.  
  588.  
  589. /* auxiliary mark (for internal use) */
  590. #define AUXMARK         "\1"
  591.  
  592. static void setpath (lua_State *L, const char *fieldname, const char *envname,
  593.                                    const char *def) {
  594.   const char *path = getenv(envname);
  595.   if (path == NULL)  /* no environment variable? */
  596.     lua_pushstring(L, def);  /* use default */
  597.   else {
  598.     /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */
  599.     path = luaL_gsub(L, path, LUA_PATHSEP LUA_PATHSEP,
  600.                               LUA_PATHSEP AUXMARK LUA_PATHSEP);
  601.     luaL_gsub(L, path, AUXMARK, def);
  602.     lua_remove(L, -2);
  603.   }
  604.   setprogdir(L);
  605.   lua_setfield(L, -2, fieldname);
  606. }
  607.  
  608.  
  609. static const luaL_Reg pk_funcs[] = {
  610.   {"loadlib", ll_loadlib},
  611.   {"seeall", ll_seeall},
  612.   {NULL, NULL}
  613. };
  614.  
  615.  
  616. static const luaL_Reg ll_funcs[] = {
  617.   {"module", ll_module},
  618.   {"require", ll_require},
  619.   {NULL, NULL}
  620. };
  621.  
  622.  
  623. static const lua_CFunction loaders[] =
  624.   {loader_preload, loader_Lua, loader_C, loader_Croot, NULL};
  625.  
  626.  
  627. LUALIB_API int luaopen_package (lua_State *L) {
  628.   int i;
  629.   /* create new type _LOADLIB */
  630.   luaL_newmetatable(L, "_LOADLIB");
  631.   lua_pushcfunction(L, gctm);
  632.   lua_setfield(L, -2, "__gc");
  633.   /* create `package' table */
  634.   luaL_register(L, LUA_LOADLIBNAME, pk_funcs);
  635. #if defined(LUA_COMPAT_LOADLIB)
  636.   lua_getfield(L, -1, "loadlib");
  637.   lua_setfield(L, LUA_GLOBALSINDEX, "loadlib");
  638. #endif
  639.   lua_pushvalue(L, -1);
  640.   lua_replace(L, LUA_ENVIRONINDEX);
  641.   /* create `loaders' table */
  642.   lua_createtable(L, sizeof(loaders)/sizeof(loaders[0]) - 1, 0);
  643.   /* fill it with pre-defined loaders */
  644.   for (i=0; loaders[i] != NULL; i++) {
  645.     lua_pushcfunction(L, loaders[i]);
  646.     lua_rawseti(L, -2, i+1);
  647.   }
  648.   lua_setfield(L, -2, "loaders");  /* put it in field `loaders' */
  649.   setpath(L, "path", LUA_PATH, LUA_PATH_DEFAULT);  /* set field `path' */
  650.   setpath(L, "cpath", LUA_CPATH, LUA_CPATH_DEFAULT); /* set field `cpath' */
  651.   /* store config information */
  652.   lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATHSEP "\n" LUA_PATH_MARK "\n"
  653.                      LUA_EXECDIR "\n" LUA_IGMARK);
  654.   lua_setfield(L, -2, "config");
  655.   /* set field `loaded' */
  656.   luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 2);
  657.   lua_setfield(L, -2, "loaded");
  658.   /* set field `preload' */
  659.   lua_newtable(L);
  660.   lua_setfield(L, -2, "preload");
  661.   lua_pushvalue(L, LUA_GLOBALSINDEX);
  662.   luaL_register(L, NULL, ll_funcs);  /* open lib into global table */
  663.   lua_pop(L, 1);
  664.   return 1;  /* return 'package' table */
  665. }
  666.  
  667.