You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

736 lines
21 KiB

  1. /*
  2. ** $Id: loadlib.c,v 1.111 2012/05/30 12:33:44 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. #if defined HAVE_CONFIG_H // LOL BEGIN
  11. # include "config.h"
  12. #endif // LOL END
  13. /*
  14. ** if needed, includes windows header before everything else
  15. */
  16. // LOL BEGIN
  17. //#if defined(_WIN32)
  18. #if defined(_WIN32) && !defined(_XBOX)
  19. // LOL END
  20. #include <windows.h>
  21. #endif
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #define loadlib_c
  25. #define LUA_LIB
  26. #include "lua.h"
  27. #include "lauxlib.h"
  28. #include "lualib.h"
  29. /*
  30. ** LUA_PATH and LUA_CPATH are the names of the environment
  31. ** variables that Lua check to set its paths.
  32. */
  33. #if !defined(LUA_PATH)
  34. #define LUA_PATH "LUA_PATH"
  35. #endif
  36. #if !defined(LUA_CPATH)
  37. #define LUA_CPATH "LUA_CPATH"
  38. #endif
  39. #define LUA_PATHSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR
  40. #define LUA_PATHVERSION LUA_PATH LUA_PATHSUFFIX
  41. #define LUA_CPATHVERSION LUA_CPATH LUA_PATHSUFFIX
  42. /*
  43. ** LUA_PATH_SEP is the character that separates templates in a path.
  44. ** LUA_PATH_MARK is the string that marks the substitution points in a
  45. ** template.
  46. ** LUA_EXEC_DIR in a Windows path is replaced by the executable's
  47. ** directory.
  48. ** LUA_IGMARK is a mark to ignore all before it when building the
  49. ** luaopen_ function name.
  50. */
  51. #if !defined (LUA_PATH_SEP)
  52. #define LUA_PATH_SEP ";"
  53. #endif
  54. #if !defined (LUA_PATH_MARK)
  55. #define LUA_PATH_MARK "?"
  56. #endif
  57. #if !defined (LUA_EXEC_DIR)
  58. #define LUA_EXEC_DIR "!"
  59. #endif
  60. #if !defined (LUA_IGMARK)
  61. #define LUA_IGMARK "-"
  62. #endif
  63. /*
  64. ** LUA_CSUBSEP is the character that replaces dots in submodule names
  65. ** when searching for a C loader.
  66. ** LUA_LSUBSEP is the character that replaces dots in submodule names
  67. ** when searching for a Lua loader.
  68. */
  69. #if !defined(LUA_CSUBSEP)
  70. #define LUA_CSUBSEP LUA_DIRSEP
  71. #endif
  72. #if !defined(LUA_LSUBSEP)
  73. #define LUA_LSUBSEP LUA_DIRSEP
  74. #endif
  75. /* prefix for open functions in C libraries */
  76. #define LUA_POF "luaopen_"
  77. /* separator for open functions in C libraries */
  78. #define LUA_OFSEP "_"
  79. /* table (in the registry) that keeps handles for all loaded C libraries */
  80. #define CLIBS "_CLIBS"
  81. #define LIB_FAIL "open"
  82. /* error codes for ll_loadfunc */
  83. #define ERRLIB 1
  84. #define ERRFUNC 2
  85. #define setprogdir(L) ((void)0)
  86. /*
  87. ** system-dependent functions
  88. */
  89. static void ll_unloadlib (void *lib);
  90. static void *ll_load (lua_State *L, const char *path, int seeglb);
  91. static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym);
  92. #if defined(LUA_USE_DLOPEN)
  93. /*
  94. ** {========================================================================
  95. ** This is an implementation of loadlib based on the dlfcn interface.
  96. ** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD,
  97. ** NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least
  98. ** as an emulation layer on top of native functions.
  99. ** =========================================================================
  100. */
  101. #include <dlfcn.h>
  102. static void ll_unloadlib (void *lib) {
  103. dlclose(lib);
  104. }
  105. static void *ll_load (lua_State *L, const char *path, int seeglb) {
  106. void *lib = dlopen(path, RTLD_NOW | (seeglb ? RTLD_GLOBAL : RTLD_LOCAL));
  107. if (lib == NULL) lua_pushstring(L, dlerror());
  108. return lib;
  109. }
  110. static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
  111. lua_CFunction f = (lua_CFunction)dlsym(lib, sym);
  112. if (f == NULL) lua_pushstring(L, dlerror());
  113. return f;
  114. }
  115. /* }====================================================== */
  116. #elif defined(LUA_DL_DLL)
  117. /*
  118. ** {======================================================================
  119. ** This is an implementation of loadlib for Windows using native functions.
  120. ** =======================================================================
  121. */
  122. #undef setprogdir
  123. /*
  124. ** optional flags for LoadLibraryEx
  125. */
  126. #if !defined(LUA_LLE_FLAGS)
  127. #define LUA_LLE_FLAGS 0
  128. #endif
  129. static void setprogdir (lua_State *L) {
  130. char buff[MAX_PATH + 1];
  131. char *lb;
  132. DWORD nsize = sizeof(buff)/sizeof(char);
  133. DWORD n = GetModuleFileNameA(NULL, buff, nsize);
  134. if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL)
  135. luaL_error(L, "unable to get ModuleFileName");
  136. else {
  137. *lb = '\0';
  138. luaL_gsub(L, lua_tostring(L, -1), LUA_EXEC_DIR, buff);
  139. lua_remove(L, -2); /* remove original string */
  140. }
  141. }
  142. static void pusherror (lua_State *L) {
  143. int error = GetLastError();
  144. char buffer[128];
  145. if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
  146. NULL, error, 0, buffer, sizeof(buffer)/sizeof(char), NULL))
  147. lua_pushstring(L, buffer);
  148. else
  149. lua_pushfstring(L, "system error %d\n", error);
  150. }
  151. static void ll_unloadlib (void *lib) {
  152. FreeLibrary((HMODULE)lib);
  153. }
  154. static void *ll_load (lua_State *L, const char *path, int seeglb) {
  155. HMODULE lib = LoadLibraryExA(path, NULL, LUA_LLE_FLAGS);
  156. (void)(seeglb); /* not used: symbols are 'global' by default */
  157. if (lib == NULL) pusherror(L);
  158. return lib;
  159. }
  160. static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
  161. lua_CFunction f = (lua_CFunction)GetProcAddress((HMODULE)lib, sym);
  162. if (f == NULL) pusherror(L);
  163. return f;
  164. }
  165. /* }====================================================== */
  166. #else
  167. /*
  168. ** {======================================================
  169. ** Fallback for other systems
  170. ** =======================================================
  171. */
  172. #undef LIB_FAIL
  173. #define LIB_FAIL "absent"
  174. #define DLMSG "dynamic libraries not enabled; check your Lua installation"
  175. static void ll_unloadlib (void *lib) {
  176. (void)(lib); /* not used */
  177. }
  178. static void *ll_load (lua_State *L, const char *path, int seeglb) {
  179. (void)(path); (void)(seeglb); /* not used */
  180. lua_pushliteral(L, DLMSG);
  181. return NULL;
  182. }
  183. static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
  184. (void)(lib); (void)(sym); /* not used */
  185. lua_pushliteral(L, DLMSG);
  186. return NULL;
  187. }
  188. /* }====================================================== */
  189. #endif
  190. static void *ll_checkclib (lua_State *L, const char *path) {
  191. void *plib;
  192. lua_getfield(L, LUA_REGISTRYINDEX, CLIBS);
  193. lua_getfield(L, -1, path);
  194. plib = lua_touserdata(L, -1); /* plib = CLIBS[path] */
  195. lua_pop(L, 2); /* pop CLIBS table and 'plib' */
  196. return plib;
  197. }
  198. static void ll_addtoclib (lua_State *L, const char *path, void *plib) {
  199. lua_getfield(L, LUA_REGISTRYINDEX, CLIBS);
  200. lua_pushlightuserdata(L, plib);
  201. lua_pushvalue(L, -1);
  202. lua_setfield(L, -3, path); /* CLIBS[path] = plib */
  203. lua_rawseti(L, -2, luaL_len(L, -2) + 1); /* CLIBS[#CLIBS + 1] = plib */
  204. lua_pop(L, 1); /* pop CLIBS table */
  205. }
  206. /*
  207. ** __gc tag method for CLIBS table: calls 'll_unloadlib' for all lib
  208. ** handles in list CLIBS
  209. */
  210. static int gctm (lua_State *L) {
  211. int n = luaL_len(L, 1);
  212. for (; n >= 1; n--) { /* for each handle, in reverse order */
  213. lua_rawgeti(L, 1, n); /* get handle CLIBS[n] */
  214. ll_unloadlib(lua_touserdata(L, -1));
  215. lua_pop(L, 1); /* pop handle */
  216. }
  217. return 0;
  218. }
  219. static int ll_loadfunc (lua_State *L, const char *path, const char *sym) {
  220. void *reg = ll_checkclib(L, path); /* check loaded C libraries */
  221. if (reg == NULL) { /* must load library? */
  222. reg = ll_load(L, path, *sym == '*');
  223. if (reg == NULL) return ERRLIB; /* unable to load library */
  224. ll_addtoclib(L, path, reg);
  225. }
  226. if (*sym == '*') { /* loading only library (no function)? */
  227. lua_pushboolean(L, 1); /* return 'true' */
  228. return 0; /* no errors */
  229. }
  230. else {
  231. lua_CFunction f = ll_sym(L, reg, sym);
  232. if (f == NULL)
  233. return ERRFUNC; /* unable to find function */
  234. lua_pushcfunction(L, f); /* else create new function */
  235. return 0; /* no errors */
  236. }
  237. }
  238. static int ll_loadlib (lua_State *L) {
  239. const char *path = luaL_checkstring(L, 1);
  240. const char *init = luaL_checkstring(L, 2);
  241. int stat = ll_loadfunc(L, path, init);
  242. if (stat == 0) /* no errors? */
  243. return 1; /* return the loaded function */
  244. else { /* error; error message is on stack top */
  245. lua_pushnil(L);
  246. lua_insert(L, -2);
  247. lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init");
  248. return 3; /* return nil, error message, and where */
  249. }
  250. }
  251. /*
  252. ** {======================================================
  253. ** 'require' function
  254. ** =======================================================
  255. */
  256. static int readable (const char *filename) {
  257. FILE *f = fopen(filename, "r"); /* try to open file */
  258. if (f == NULL) return 0; /* open failed */
  259. fclose(f);
  260. return 1;
  261. }
  262. static const char *pushnexttemplate (lua_State *L, const char *path) {
  263. const char *l;
  264. while (*path == *LUA_PATH_SEP) path++; /* skip separators */
  265. if (*path == '\0') return NULL; /* no more templates */
  266. l = strchr(path, *LUA_PATH_SEP); /* find next separator */
  267. if (l == NULL) l = path + strlen(path);
  268. lua_pushlstring(L, path, l - path); /* template */
  269. return l;
  270. }
  271. static const char *searchpath (lua_State *L, const char *name,
  272. const char *path,
  273. const char *sep,
  274. const char *dirsep) {
  275. luaL_Buffer msg; /* to build error message */
  276. luaL_buffinit(L, &msg);
  277. if (*sep != '\0') /* non-empty separator? */
  278. name = luaL_gsub(L, name, sep, dirsep); /* replace it by 'dirsep' */
  279. while ((path = pushnexttemplate(L, path)) != NULL) {
  280. const char *filename = luaL_gsub(L, lua_tostring(L, -1),
  281. LUA_PATH_MARK, name);
  282. lua_remove(L, -2); /* remove path template */
  283. if (readable(filename)) /* does file exist and is readable? */
  284. return filename; /* return that file name */
  285. lua_pushfstring(L, "\n\tno file " LUA_QS, filename);
  286. lua_remove(L, -2); /* remove file name */
  287. luaL_addvalue(&msg); /* concatenate error msg. entry */
  288. }
  289. luaL_pushresult(&msg); /* create error message */
  290. return NULL; /* not found */
  291. }
  292. static int ll_searchpath (lua_State *L) {
  293. const char *f = searchpath(L, luaL_checkstring(L, 1),
  294. luaL_checkstring(L, 2),
  295. luaL_optstring(L, 3, "."),
  296. luaL_optstring(L, 4, LUA_DIRSEP));
  297. if (f != NULL) return 1;
  298. else { /* error message is on top of the stack */
  299. lua_pushnil(L);
  300. lua_insert(L, -2);
  301. return 2; /* return nil + error message */
  302. }
  303. }
  304. static const char *findfile (lua_State *L, const char *name,
  305. const char *pname,
  306. const char *dirsep) {
  307. const char *path;
  308. lua_getfield(L, lua_upvalueindex(1), pname);
  309. path = lua_tostring(L, -1);
  310. if (path == NULL)
  311. luaL_error(L, LUA_QL("package.%s") " must be a string", pname);
  312. return searchpath(L, name, path, ".", dirsep);
  313. }
  314. static int checkload (lua_State *L, int stat, const char *filename) {
  315. if (stat) { /* module loaded successfully? */
  316. lua_pushstring(L, filename); /* will be 2nd argument to module */
  317. return 2; /* return open function and file name */
  318. }
  319. else
  320. return luaL_error(L, "error loading module " LUA_QS
  321. " from file " LUA_QS ":\n\t%s",
  322. lua_tostring(L, 1), filename, lua_tostring(L, -1));
  323. }
  324. static int searcher_Lua (lua_State *L) {
  325. const char *filename;
  326. const char *name = luaL_checkstring(L, 1);
  327. filename = findfile(L, name, "path", LUA_LSUBSEP);
  328. if (filename == NULL) return 1; /* module not found in this path */
  329. return checkload(L, (luaL_loadfile(L, filename) == LUA_OK), filename);
  330. }
  331. static int loadfunc (lua_State *L, const char *filename, const char *modname) {
  332. const char *funcname;
  333. const char *mark;
  334. modname = luaL_gsub(L, modname, ".", LUA_OFSEP);
  335. mark = strchr(modname, *LUA_IGMARK);
  336. if (mark) {
  337. int stat;
  338. funcname = lua_pushlstring(L, modname, mark - modname);
  339. funcname = lua_pushfstring(L, LUA_POF"%s", funcname);
  340. stat = ll_loadfunc(L, filename, funcname);
  341. if (stat != ERRFUNC) return stat;
  342. modname = mark + 1; /* else go ahead and try old-style name */
  343. }
  344. funcname = lua_pushfstring(L, LUA_POF"%s", modname);
  345. return ll_loadfunc(L, filename, funcname);
  346. }
  347. static int searcher_C (lua_State *L) {
  348. const char *name = luaL_checkstring(L, 1);
  349. const char *filename = findfile(L, name, "cpath", LUA_CSUBSEP);
  350. if (filename == NULL) return 1; /* module not found in this path */
  351. return checkload(L, (loadfunc(L, filename, name) == 0), filename);
  352. }
  353. static int searcher_Croot (lua_State *L) {
  354. const char *filename;
  355. const char *name = luaL_checkstring(L, 1);
  356. const char *p = strchr(name, '.');
  357. int stat;
  358. if (p == NULL) return 0; /* is root */
  359. lua_pushlstring(L, name, p - name);
  360. filename = findfile(L, lua_tostring(L, -1), "cpath", LUA_CSUBSEP);
  361. if (filename == NULL) return 1; /* root not found */
  362. if ((stat = loadfunc(L, filename, name)) != 0) {
  363. if (stat != ERRFUNC)
  364. return checkload(L, 0, filename); /* real error */
  365. else { /* open function not found */
  366. lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS,
  367. name, filename);
  368. return 1;
  369. }
  370. }
  371. lua_pushstring(L, filename); /* will be 2nd argument to module */
  372. return 2;
  373. }
  374. static int searcher_preload (lua_State *L) {
  375. const char *name = luaL_checkstring(L, 1);
  376. lua_getfield(L, LUA_REGISTRYINDEX, "_PRELOAD");
  377. lua_getfield(L, -1, name);
  378. if (lua_isnil(L, -1)) /* not found? */
  379. lua_pushfstring(L, "\n\tno field package.preload['%s']", name);
  380. return 1;
  381. }
  382. static void findloader (lua_State *L, const char *name) {
  383. int i;
  384. luaL_Buffer msg; /* to build error message */
  385. luaL_buffinit(L, &msg);
  386. lua_getfield(L, lua_upvalueindex(1), "searchers"); /* will be at index 3 */
  387. if (!lua_istable(L, 3))
  388. luaL_error(L, LUA_QL("package.searchers") " must be a table");
  389. /* iterate over available searchers to find a loader */
  390. for (i = 1; ; i++) {
  391. lua_rawgeti(L, 3, i); /* get a searcher */
  392. if (lua_isnil(L, -1)) { /* no more searchers? */
  393. lua_pop(L, 1); /* remove nil */
  394. luaL_pushresult(&msg); /* create error message */
  395. luaL_error(L, "module " LUA_QS " not found:%s",
  396. name, lua_tostring(L, -1));
  397. }
  398. lua_pushstring(L, name);
  399. lua_call(L, 1, 2); /* call it */
  400. if (lua_isfunction(L, -2)) /* did it find a loader? */
  401. return; /* module loader found */
  402. else if (lua_isstring(L, -2)) { /* searcher returned error message? */
  403. lua_pop(L, 1); /* remove extra return */
  404. luaL_addvalue(&msg); /* concatenate error message */
  405. }
  406. else
  407. lua_pop(L, 2); /* remove both returns */
  408. }
  409. }
  410. static int ll_require (lua_State *L) {
  411. const char *name = luaL_checkstring(L, 1);
  412. lua_settop(L, 1); /* _LOADED table will be at index 2 */
  413. lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
  414. lua_getfield(L, 2, name); /* _LOADED[name] */
  415. if (lua_toboolean(L, -1)) /* is it there? */
  416. return 1; /* package is already loaded */
  417. /* else must load package */
  418. lua_pop(L, 1); /* remove 'getfield' result */
  419. findloader(L, name);
  420. lua_pushstring(L, name); /* pass name as argument to module loader */
  421. lua_insert(L, -2); /* name is 1st argument (before search data) */
  422. lua_call(L, 2, 1); /* run loader to load module */
  423. if (!lua_isnil(L, -1)) /* non-nil return? */
  424. lua_setfield(L, 2, name); /* _LOADED[name] = returned value */
  425. lua_getfield(L, 2, name);
  426. if (lua_isnil(L, -1)) { /* module did not set a value? */
  427. lua_pushboolean(L, 1); /* use true as result */
  428. lua_pushvalue(L, -1); /* extra copy to be returned */
  429. lua_setfield(L, 2, name); /* _LOADED[name] = true */
  430. }
  431. return 1;
  432. }
  433. /* }====================================================== */
  434. /*
  435. ** {======================================================
  436. ** 'module' function
  437. ** =======================================================
  438. */
  439. #if defined(LUA_COMPAT_MODULE)
  440. /*
  441. ** changes the environment variable of calling function
  442. */
  443. static void set_env (lua_State *L) {
  444. lua_Debug ar;
  445. if (lua_getstack(L, 1, &ar) == 0 ||
  446. lua_getinfo(L, "f", &ar) == 0 || /* get calling function */
  447. lua_iscfunction(L, -1))
  448. luaL_error(L, LUA_QL("module") " not called from a Lua function");
  449. lua_pushvalue(L, -2); /* copy new environment table to top */
  450. lua_setupvalue(L, -2, 1);
  451. lua_pop(L, 1); /* remove function */
  452. }
  453. static void dooptions (lua_State *L, int n) {
  454. int i;
  455. for (i = 2; i <= n; i++) {
  456. if (lua_isfunction(L, i)) { /* avoid 'calling' extra info. */
  457. lua_pushvalue(L, i); /* get option (a function) */
  458. lua_pushvalue(L, -2); /* module */
  459. lua_call(L, 1, 0);
  460. }
  461. }
  462. }
  463. static void modinit (lua_State *L, const char *modname) {
  464. const char *dot;
  465. lua_pushvalue(L, -1);
  466. lua_setfield(L, -2, "_M"); /* module._M = module */
  467. lua_pushstring(L, modname);
  468. lua_setfield(L, -2, "_NAME");
  469. dot = strrchr(modname, '.'); /* look for last dot in module name */
  470. if (dot == NULL) dot = modname;
  471. else dot++;
  472. /* set _PACKAGE as package name (full module name minus last part) */
  473. lua_pushlstring(L, modname, dot - modname);
  474. lua_setfield(L, -2, "_PACKAGE");
  475. }
  476. static int ll_module (lua_State *L) {
  477. const char *modname = luaL_checkstring(L, 1);
  478. int lastarg = lua_gettop(L); /* last parameter */
  479. luaL_pushmodule(L, modname, 1); /* get/create module table */
  480. /* check whether table already has a _NAME field */
  481. lua_getfield(L, -1, "_NAME");
  482. if (!lua_isnil(L, -1)) /* is table an initialized module? */
  483. lua_pop(L, 1);
  484. else { /* no; initialize it */
  485. lua_pop(L, 1);
  486. modinit(L, modname);
  487. }
  488. lua_pushvalue(L, -1);
  489. set_env(L);
  490. dooptions(L, lastarg);
  491. return 1;
  492. }
  493. static int ll_seeall (lua_State *L) {
  494. luaL_checktype(L, 1, LUA_TTABLE);
  495. if (!lua_getmetatable(L, 1)) {
  496. lua_createtable(L, 0, 1); /* create new metatable */
  497. lua_pushvalue(L, -1);
  498. lua_setmetatable(L, 1);
  499. }
  500. lua_pushglobaltable(L);
  501. lua_setfield(L, -2, "__index"); /* mt.__index = _G */
  502. return 0;
  503. }
  504. #endif
  505. /* }====================================================== */
  506. /* auxiliary mark (for internal use) */
  507. #define AUXMARK "\1"
  508. /*
  509. ** return registry.LUA_NOENV as a boolean
  510. */
  511. static int noenv (lua_State *L) {
  512. int b;
  513. lua_getfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");
  514. b = lua_toboolean(L, -1);
  515. lua_pop(L, 1); /* remove value */
  516. return b;
  517. }
  518. static void setpath (lua_State *L, const char *fieldname, const char *envname1,
  519. const char *envname2, const char *def) {
  520. #if HAVE_GETENV // LOL BEGIN
  521. const char *path = getenv(envname1);
  522. if (path == NULL) /* no environment variable? */
  523. path = getenv(envname2); /* try alternative name */
  524. #else
  525. const char *path = NULL;
  526. #endif // LOL END
  527. if (path == NULL || noenv(L)) /* no environment variable? */
  528. lua_pushstring(L, def); /* use default */
  529. else {
  530. /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */
  531. path = luaL_gsub(L, path, LUA_PATH_SEP LUA_PATH_SEP,
  532. LUA_PATH_SEP AUXMARK LUA_PATH_SEP);
  533. luaL_gsub(L, path, AUXMARK, def);
  534. lua_remove(L, -2);
  535. }
  536. setprogdir(L);
  537. lua_setfield(L, -2, fieldname);
  538. }
  539. static const luaL_Reg pk_funcs[] = {
  540. {"loadlib", ll_loadlib},
  541. {"searchpath", ll_searchpath},
  542. #if defined(LUA_COMPAT_MODULE)
  543. {"seeall", ll_seeall},
  544. #endif
  545. {NULL, NULL}
  546. };
  547. static const luaL_Reg ll_funcs[] = {
  548. #if defined(LUA_COMPAT_MODULE)
  549. {"module", ll_module},
  550. #endif
  551. {"require", ll_require},
  552. {NULL, NULL}
  553. };
  554. static void createsearcherstable (lua_State *L) {
  555. static const lua_CFunction searchers[] =
  556. {searcher_preload, searcher_Lua, searcher_C, searcher_Croot, NULL};
  557. int i;
  558. /* create 'searchers' table */
  559. lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0);
  560. /* fill it with pre-defined searchers */
  561. for (i=0; searchers[i] != NULL; i++) {
  562. lua_pushvalue(L, -2); /* set 'package' as upvalue for all searchers */
  563. lua_pushcclosure(L, searchers[i], 1);
  564. lua_rawseti(L, -2, i+1);
  565. }
  566. }
  567. LUAMOD_API int luaopen_package (lua_State *L) {
  568. /* create table CLIBS to keep track of loaded C libraries */
  569. luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS);
  570. lua_createtable(L, 0, 1); /* metatable for CLIBS */
  571. lua_pushcfunction(L, gctm);
  572. lua_setfield(L, -2, "__gc"); /* set finalizer for CLIBS table */
  573. lua_setmetatable(L, -2);
  574. /* create `package' table */
  575. luaL_newlib(L, pk_funcs);
  576. createsearcherstable(L);
  577. #if defined(LUA_COMPAT_LOADERS)
  578. lua_pushvalue(L, -1); /* make a copy of 'searchers' table */
  579. lua_setfield(L, -3, "loaders"); /* put it in field `loaders' */
  580. #endif
  581. lua_setfield(L, -2, "searchers"); /* put it in field 'searchers' */
  582. /* set field 'path' */
  583. setpath(L, "path", LUA_PATHVERSION, LUA_PATH, LUA_PATH_DEFAULT);
  584. /* set field 'cpath' */
  585. setpath(L, "cpath", LUA_CPATHVERSION, LUA_CPATH, LUA_CPATH_DEFAULT);
  586. /* store config information */
  587. lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATH_SEP "\n" LUA_PATH_MARK "\n"
  588. LUA_EXEC_DIR "\n" LUA_IGMARK "\n");
  589. lua_setfield(L, -2, "config");
  590. /* set field `loaded' */
  591. luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED");
  592. lua_setfield(L, -2, "loaded");
  593. /* set field `preload' */
  594. luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD");
  595. lua_setfield(L, -2, "preload");
  596. lua_pushglobaltable(L);
  597. lua_pushvalue(L, -2); /* set 'package' as upvalue for next lib */
  598. luaL_setfuncs(L, ll_funcs, 1); /* open lib into global table */
  599. lua_pop(L, 1); /* pop global table */
  600. return 1; /* return 'package' table */
  601. }