lib_package_rel.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
  1. /*
  2. ** Package library.
  3. ** Copyright (C) 2005-2013 Mike Pall. See Copyright Notice in luajit.h
  4. **
  5. ** Major portions taken verbatim or adapted from the Lua interpreter.
  6. ** Copyright (C) 1994-2012 Lua.org, PUC-Rio. See Copyright Notice in lua.h
  7. */
  8. #define lib_package_c
  9. #define LUA_LIB
  10. #include "lua.h"
  11. #include "lauxlib.h"
  12. #include "lualib.h"
  13. #include "lj_obj.h"
  14. #include "lj_err.h"
  15. #include "lj_lib.h"
  16. /* ------------------------------------------------------------------------ */
  17. /* Error codes for ll_loadfunc. */
  18. #define PACKAGE_ERR_LIB 1
  19. #define PACKAGE_ERR_FUNC 2
  20. #define PACKAGE_ERR_LOAD 3
  21. /* Redefined in platform specific part. */
  22. #define PACKAGE_LIB_FAIL "open"
  23. /* Symbol name prefixes. */
  24. #define SYMPREFIX_CF "luaopen_%s"
  25. #define SYMPREFIX_BC "luaJIT_BC_%s"
  26. /*
  27. ** {=========================================================================
  28. ** This determines the location of the executable for relative module loading
  29. ** Modified by the LuaDist project for UNIX platforms
  30. ** ==========================================================================
  31. */
  32. #if defined(_WIN32) || defined(__CYGWIN__)
  33. #include <windows.h>
  34. #define _PATH_MAX MAX_PATH
  35. #else
  36. #define _PATH_MAX PATH_MAX
  37. #endif
  38. #if defined(__linux__) || defined(__sun)
  39. #include <unistd.h> /* readlink */
  40. #endif
  41. #if defined(__APPLE__)
  42. #include <sys/param.h>
  43. #include <mach-o/dyld.h>
  44. #endif
  45. #if defined(__FreeBSD__)
  46. #include <sys/types.h>
  47. #include <sys/sysctl.h>
  48. #endif
  49. static void setprogdir(lua_State *L) {
  50. char progdir[_PATH_MAX + 1];
  51. char *lb;
  52. int nsize = sizeof(progdir)/sizeof(char);
  53. int n;
  54. #if defined(__CYGWIN__)
  55. char win_buff[_PATH_MAX + 1];
  56. GetModuleFileNameA(NULL, win_buff, nsize);
  57. cygwin_conv_to_posix_path(win_buff, progdir);
  58. n = strlen(progdir);
  59. #elif defined(_WIN32)
  60. n = GetModuleFileNameA(NULL, progdir, nsize);
  61. #elif defined(__linux__)
  62. n = readlink("/proc/self/exe", progdir, nsize);
  63. if (n > 0) progdir[n] = 0;
  64. #elif defined(__sun)
  65. pid_t pid = getpid();
  66. char linkname[256];
  67. sprintf(linkname, "/proc/%d/path/a.out", pid);
  68. n = readlink(linkname, progdir, nsize);
  69. if (n > 0) progdir[n] = 0;
  70. #elif defined(__FreeBSD__)
  71. int mib[4];
  72. mib[0] = CTL_KERN;
  73. mib[1] = KERN_PROC;
  74. mib[2] = KERN_PROC_PATHNAME;
  75. mib[3] = -1;
  76. size_t cb = nsize;
  77. sysctl(mib, 4, progdir, &cb, NULL, 0);
  78. n = cb;
  79. #elif defined(__BSD__)
  80. n = readlink("/proc/curproc/file", progdir, nsize);
  81. if (n > 0) progdir[n] = 0;
  82. #elif defined(__APPLE__)
  83. uint32_t nsize_apple = nsize;
  84. if (_NSGetExecutablePath(progdir, &nsize_apple) == 0)
  85. n = strlen(progdir);
  86. #else
  87. // FALLBACK
  88. // Use 'lsof' ... should work on most UNIX systems (incl. OSX)
  89. // lsof will list open files, this captures the 1st file listed (usually the executable)
  90. int pid;
  91. FILE* fd;
  92. char cmd[80];
  93. pid = getpid();
  94. sprintf(cmd, "lsof -p %d | awk '{if ($5==\"REG\") { print $9 ; exit}}' 2> /dev/null", pid);
  95. fd = popen(cmd, "r");
  96. n = fread(progdir, 1, nsize, fd);
  97. // remove newline
  98. if (n > 1) progdir[--n] = '\0';
  99. #endif
  100. if (n == 0 || n == nsize || (lb = strrchr(progdir, (int)LUA_DIRSEP[0])) == NULL)
  101. luaL_error(L, "unable to get process executable path");
  102. else {
  103. *lb = '\0';
  104. // Replace the relative path placeholder
  105. luaL_gsub(L, lua_tostring(L, -1), LUA_EXECDIR, progdir);
  106. lua_remove(L, -2);
  107. }
  108. }
  109. #if LJ_TARGET_DLOPEN
  110. #include <dlfcn.h>
  111. static void ll_unloadlib(void *lib)
  112. {
  113. dlclose(lib);
  114. }
  115. static void *ll_load(lua_State *L, const char *path, int gl)
  116. {
  117. void *lib = dlopen(path, RTLD_NOW | (gl ? RTLD_GLOBAL : RTLD_LOCAL));
  118. if (lib == NULL) lua_pushstring(L, dlerror());
  119. return lib;
  120. }
  121. static lua_CFunction ll_sym(lua_State *L, void *lib, const char *sym)
  122. {
  123. lua_CFunction f = (lua_CFunction)dlsym(lib, sym);
  124. if (f == NULL) lua_pushstring(L, dlerror());
  125. return f;
  126. }
  127. static const char *ll_bcsym(void *lib, const char *sym)
  128. {
  129. #if defined(RTLD_DEFAULT)
  130. if (lib == NULL) lib = RTLD_DEFAULT;
  131. #elif LJ_TARGET_OSX || LJ_TARGET_BSD
  132. if (lib == NULL) lib = (void *)(intptr_t)-2;
  133. #endif
  134. return (const char *)dlsym(lib, sym);
  135. }
  136. #elif LJ_TARGET_WINDOWS
  137. #define WIN32_LEAN_AND_MEAN
  138. #ifndef WINVER
  139. #define WINVER 0x0500
  140. #endif
  141. #include <windows.h>
  142. #ifndef GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
  143. #define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS 4
  144. #define GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT 2
  145. BOOL WINAPI GetModuleHandleExA(DWORD, LPCSTR, HMODULE*);
  146. #endif
  147. static void pusherror(lua_State *L)
  148. {
  149. DWORD error = GetLastError();
  150. char buffer[128];
  151. if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
  152. NULL, error, 0, buffer, sizeof(buffer), NULL))
  153. lua_pushstring(L, buffer);
  154. else
  155. lua_pushfstring(L, "system error %d\n", error);
  156. }
  157. static void ll_unloadlib(void *lib)
  158. {
  159. FreeLibrary((HINSTANCE)lib);
  160. }
  161. static void *ll_load(lua_State *L, const char *path, int gl)
  162. {
  163. HINSTANCE lib = LoadLibraryA(path);
  164. if (lib == NULL) pusherror(L);
  165. UNUSED(gl);
  166. return lib;
  167. }
  168. static lua_CFunction ll_sym(lua_State *L, void *lib, const char *sym)
  169. {
  170. lua_CFunction f = (lua_CFunction)GetProcAddress((HINSTANCE)lib, sym);
  171. if (f == NULL) pusherror(L);
  172. return f;
  173. }
  174. static const char *ll_bcsym(void *lib, const char *sym)
  175. {
  176. if (lib) {
  177. return (const char *)GetProcAddress((HINSTANCE)lib, sym);
  178. } else {
  179. HINSTANCE h = GetModuleHandleA(NULL);
  180. const char *p = (const char *)GetProcAddress(h, sym);
  181. if (p == NULL && GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS|GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
  182. (const char *)ll_bcsym, &h))
  183. p = (const char *)GetProcAddress(h, sym);
  184. return p;
  185. }
  186. }
  187. #else
  188. #undef PACKAGE_LIB_FAIL
  189. #define PACKAGE_LIB_FAIL "absent"
  190. #define DLMSG "dynamic libraries not enabled; no support for target OS"
  191. static void ll_unloadlib(void *lib)
  192. {
  193. UNUSED(lib);
  194. }
  195. static void *ll_load(lua_State *L, const char *path, int gl)
  196. {
  197. UNUSED(path); UNUSED(gl);
  198. lua_pushliteral(L, DLMSG);
  199. return NULL;
  200. }
  201. static lua_CFunction ll_sym(lua_State *L, void *lib, const char *sym)
  202. {
  203. UNUSED(lib); UNUSED(sym);
  204. lua_pushliteral(L, DLMSG);
  205. return NULL;
  206. }
  207. static const char *ll_bcsym(void *lib, const char *sym)
  208. {
  209. UNUSED(lib); UNUSED(sym);
  210. return NULL;
  211. }
  212. #endif
  213. /* ------------------------------------------------------------------------ */
  214. static void **ll_register(lua_State *L, const char *path)
  215. {
  216. void **plib;
  217. lua_pushfstring(L, "LOADLIB: %s", path);
  218. lua_gettable(L, LUA_REGISTRYINDEX); /* check library in registry? */
  219. if (!lua_isnil(L, -1)) { /* is there an entry? */
  220. plib = (void **)lua_touserdata(L, -1);
  221. } else { /* no entry yet; create one */
  222. lua_pop(L, 1);
  223. plib = (void **)lua_newuserdata(L, sizeof(void *));
  224. *plib = NULL;
  225. luaL_getmetatable(L, "_LOADLIB");
  226. lua_setmetatable(L, -2);
  227. lua_pushfstring(L, "LOADLIB: %s", path);
  228. lua_pushvalue(L, -2);
  229. lua_settable(L, LUA_REGISTRYINDEX);
  230. }
  231. return plib;
  232. }
  233. static const char *mksymname(lua_State *L, const char *modname,
  234. const char *prefix)
  235. {
  236. const char *funcname;
  237. const char *mark = strchr(modname, *LUA_IGMARK);
  238. if (mark) modname = mark + 1;
  239. funcname = luaL_gsub(L, modname, ".", "_");
  240. funcname = lua_pushfstring(L, prefix, funcname);
  241. lua_remove(L, -2); /* remove 'gsub' result */
  242. return funcname;
  243. }
  244. static int ll_loadfunc(lua_State *L, const char *path, const char *name, int r)
  245. {
  246. void **reg = ll_register(L, path);
  247. if (*reg == NULL) *reg = ll_load(L, path, (*name == '*'));
  248. if (*reg == NULL) {
  249. return PACKAGE_ERR_LIB; /* Unable to load library. */
  250. } else if (*name == '*') { /* Only load library into global namespace. */
  251. lua_pushboolean(L, 1);
  252. return 0;
  253. } else {
  254. const char *sym = r ? name : mksymname(L, name, SYMPREFIX_CF);
  255. lua_CFunction f = ll_sym(L, *reg, sym);
  256. if (f) {
  257. lua_pushcfunction(L, f);
  258. return 0;
  259. }
  260. if (!r) {
  261. const char *bcdata = ll_bcsym(*reg, mksymname(L, name, SYMPREFIX_BC));
  262. lua_pop(L, 1);
  263. if (bcdata) {
  264. if (luaL_loadbuffer(L, bcdata, ~(size_t)0, name) != 0)
  265. return PACKAGE_ERR_LOAD;
  266. return 0;
  267. }
  268. }
  269. return PACKAGE_ERR_FUNC; /* Unable to find function. */
  270. }
  271. }
  272. static int lj_cf_package_loadlib(lua_State *L)
  273. {
  274. const char *path = luaL_checkstring(L, 1);
  275. const char *init = luaL_checkstring(L, 2);
  276. int st = ll_loadfunc(L, path, init, 1);
  277. if (st == 0) { /* no errors? */
  278. return 1; /* return the loaded function */
  279. } else { /* error; error message is on stack top */
  280. lua_pushnil(L);
  281. lua_insert(L, -2);
  282. lua_pushstring(L, (st == PACKAGE_ERR_LIB) ? PACKAGE_LIB_FAIL : "init");
  283. return 3; /* return nil, error message, and where */
  284. }
  285. }
  286. static int lj_cf_package_unloadlib(lua_State *L)
  287. {
  288. void **lib = (void **)luaL_checkudata(L, 1, "_LOADLIB");
  289. if (*lib) ll_unloadlib(*lib);
  290. *lib = NULL; /* mark library as closed */
  291. return 0;
  292. }
  293. /* ------------------------------------------------------------------------ */
  294. static int readable(const char *filename)
  295. {
  296. FILE *f = fopen(filename, "r"); /* try to open file */
  297. if (f == NULL) return 0; /* open failed */
  298. fclose(f);
  299. return 1;
  300. }
  301. static const char *pushnexttemplate(lua_State *L, const char *path)
  302. {
  303. const char *l;
  304. while (*path == *LUA_PATHSEP) path++; /* skip separators */
  305. if (*path == '\0') return NULL; /* no more templates */
  306. l = strchr(path, *LUA_PATHSEP); /* find next separator */
  307. if (l == NULL) l = path + strlen(path);
  308. lua_pushlstring(L, path, (size_t)(l - path)); /* template */
  309. return l;
  310. }
  311. static const char *searchpath (lua_State *L, const char *name,
  312. const char *path, const char *sep,
  313. const char *dirsep)
  314. {
  315. luaL_Buffer msg; /* to build error message */
  316. luaL_buffinit(L, &msg);
  317. if (*sep != '\0') /* non-empty separator? */
  318. name = luaL_gsub(L, name, sep, dirsep); /* replace it by 'dirsep' */
  319. while ((path = pushnexttemplate(L, path)) != NULL) {
  320. const char *filename = luaL_gsub(L, lua_tostring(L, -1),
  321. LUA_PATH_MARK, name);
  322. lua_remove(L, -2); /* remove path template */
  323. if (readable(filename)) /* does file exist and is readable? */
  324. return filename; /* return that file name */
  325. lua_pushfstring(L, "\n\tno file " LUA_QS, filename);
  326. lua_remove(L, -2); /* remove file name */
  327. luaL_addvalue(&msg); /* concatenate error msg. entry */
  328. }
  329. luaL_pushresult(&msg); /* create error message */
  330. return NULL; /* not found */
  331. }
  332. static int lj_cf_package_searchpath(lua_State *L)
  333. {
  334. const char *f = searchpath(L, luaL_checkstring(L, 1),
  335. luaL_checkstring(L, 2),
  336. luaL_optstring(L, 3, "."),
  337. luaL_optstring(L, 4, LUA_DIRSEP));
  338. if (f != NULL) {
  339. return 1;
  340. } else { /* error message is on top of the stack */
  341. lua_pushnil(L);
  342. lua_insert(L, -2);
  343. return 2; /* return nil + error message */
  344. }
  345. }
  346. static const char *findfile(lua_State *L, const char *name,
  347. const char *pname)
  348. {
  349. const char *path;
  350. lua_getfield(L, LUA_ENVIRONINDEX, pname);
  351. path = lua_tostring(L, -1);
  352. if (path == NULL)
  353. luaL_error(L, LUA_QL("package.%s") " must be a string", pname);
  354. return searchpath(L, name, path, ".", LUA_DIRSEP);
  355. }
  356. static void loaderror(lua_State *L, const char *filename)
  357. {
  358. luaL_error(L, "error loading module " LUA_QS " from file " LUA_QS ":\n\t%s",
  359. lua_tostring(L, 1), filename, lua_tostring(L, -1));
  360. }
  361. static int lj_cf_package_loader_lua(lua_State *L)
  362. {
  363. const char *filename;
  364. const char *name = luaL_checkstring(L, 1);
  365. filename = findfile(L, name, "path");
  366. if (filename == NULL) return 1; /* library not found in this path */
  367. if (luaL_loadfile(L, filename) != 0)
  368. loaderror(L, filename);
  369. return 1; /* library loaded successfully */
  370. }
  371. static int lj_cf_package_loader_c(lua_State *L)
  372. {
  373. const char *name = luaL_checkstring(L, 1);
  374. const char *filename = findfile(L, name, "cpath");
  375. if (filename == NULL) return 1; /* library not found in this path */
  376. if (ll_loadfunc(L, filename, name, 0) != 0)
  377. loaderror(L, filename);
  378. return 1; /* library loaded successfully */
  379. }
  380. static int lj_cf_package_loader_croot(lua_State *L)
  381. {
  382. const char *filename;
  383. const char *name = luaL_checkstring(L, 1);
  384. const char *p = strchr(name, '.');
  385. int st;
  386. if (p == NULL) return 0; /* is root */
  387. lua_pushlstring(L, name, (size_t)(p - name));
  388. filename = findfile(L, lua_tostring(L, -1), "cpath");
  389. if (filename == NULL) return 1; /* root not found */
  390. if ((st = ll_loadfunc(L, filename, name, 0)) != 0) {
  391. if (st != PACKAGE_ERR_FUNC) loaderror(L, filename); /* real error */
  392. lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS,
  393. name, filename);
  394. return 1; /* function not found */
  395. }
  396. return 1;
  397. }
  398. static int lj_cf_package_loader_preload(lua_State *L)
  399. {
  400. const char *name = luaL_checkstring(L, 1);
  401. lua_getfield(L, LUA_ENVIRONINDEX, "preload");
  402. if (!lua_istable(L, -1))
  403. luaL_error(L, LUA_QL("package.preload") " must be a table");
  404. lua_getfield(L, -1, name);
  405. if (lua_isnil(L, -1)) { /* Not found? */
  406. const char *bcname = mksymname(L, name, SYMPREFIX_BC);
  407. const char *bcdata = ll_bcsym(NULL, bcname);
  408. if (bcdata == NULL || luaL_loadbuffer(L, bcdata, ~(size_t)0, name) != 0)
  409. lua_pushfstring(L, "\n\tno field package.preload['%s']", name);
  410. }
  411. return 1;
  412. }
  413. /* ------------------------------------------------------------------------ */
  414. static const int sentinel_ = 0;
  415. #define sentinel ((void *)&sentinel_)
  416. static int lj_cf_package_require(lua_State *L)
  417. {
  418. const char *name = luaL_checkstring(L, 1);
  419. int i;
  420. lua_settop(L, 1); /* _LOADED table will be at index 2 */
  421. lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
  422. lua_getfield(L, 2, name);
  423. if (lua_toboolean(L, -1)) { /* is it there? */
  424. if (lua_touserdata(L, -1) == sentinel) /* check loops */
  425. luaL_error(L, "loop or previous error loading module " LUA_QS, name);
  426. return 1; /* package is already loaded */
  427. }
  428. /* else must load it; iterate over available loaders */
  429. lua_getfield(L, LUA_ENVIRONINDEX, "loaders");
  430. if (!lua_istable(L, -1))
  431. luaL_error(L, LUA_QL("package.loaders") " must be a table");
  432. lua_pushliteral(L, ""); /* error message accumulator */
  433. for (i = 1; ; i++) {
  434. lua_rawgeti(L, -2, i); /* get a loader */
  435. if (lua_isnil(L, -1))
  436. luaL_error(L, "module " LUA_QS " not found:%s",
  437. name, lua_tostring(L, -2));
  438. lua_pushstring(L, name);
  439. lua_call(L, 1, 1); /* call it */
  440. if (lua_isfunction(L, -1)) /* did it find module? */
  441. break; /* module loaded successfully */
  442. else if (lua_isstring(L, -1)) /* loader returned error message? */
  443. lua_concat(L, 2); /* accumulate it */
  444. else
  445. lua_pop(L, 1);
  446. }
  447. lua_pushlightuserdata(L, sentinel);
  448. lua_setfield(L, 2, name); /* _LOADED[name] = sentinel */
  449. lua_pushstring(L, name); /* pass name as argument to module */
  450. lua_call(L, 1, 1); /* run loaded module */
  451. if (!lua_isnil(L, -1)) /* non-nil return? */
  452. lua_setfield(L, 2, name); /* _LOADED[name] = returned value */
  453. lua_getfield(L, 2, name);
  454. if (lua_touserdata(L, -1) == sentinel) { /* module did not set a value? */
  455. lua_pushboolean(L, 1); /* use true as result */
  456. lua_pushvalue(L, -1); /* extra copy to be returned */
  457. lua_setfield(L, 2, name); /* _LOADED[name] = true */
  458. }
  459. lj_lib_checkfpu(L);
  460. return 1;
  461. }
  462. /* ------------------------------------------------------------------------ */
  463. static void setfenv(lua_State *L)
  464. {
  465. lua_Debug ar;
  466. if (lua_getstack(L, 1, &ar) == 0 ||
  467. lua_getinfo(L, "f", &ar) == 0 || /* get calling function */
  468. lua_iscfunction(L, -1))
  469. luaL_error(L, LUA_QL("module") " not called from a Lua function");
  470. lua_pushvalue(L, -2);
  471. lua_setfenv(L, -2);
  472. lua_pop(L, 1);
  473. }
  474. static void dooptions(lua_State *L, int n)
  475. {
  476. int i;
  477. for (i = 2; i <= n; i++) {
  478. lua_pushvalue(L, i); /* get option (a function) */
  479. lua_pushvalue(L, -2); /* module */
  480. lua_call(L, 1, 0);
  481. }
  482. }
  483. static void modinit(lua_State *L, const char *modname)
  484. {
  485. const char *dot;
  486. lua_pushvalue(L, -1);
  487. lua_setfield(L, -2, "_M"); /* module._M = module */
  488. lua_pushstring(L, modname);
  489. lua_setfield(L, -2, "_NAME");
  490. dot = strrchr(modname, '.'); /* look for last dot in module name */
  491. if (dot == NULL) dot = modname; else dot++;
  492. /* set _PACKAGE as package name (full module name minus last part) */
  493. lua_pushlstring(L, modname, (size_t)(dot - modname));
  494. lua_setfield(L, -2, "_PACKAGE");
  495. }
  496. static int lj_cf_package_module(lua_State *L)
  497. {
  498. const char *modname = luaL_checkstring(L, 1);
  499. int loaded = lua_gettop(L) + 1; /* index of _LOADED table */
  500. lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
  501. lua_getfield(L, loaded, modname); /* get _LOADED[modname] */
  502. if (!lua_istable(L, -1)) { /* not found? */
  503. lua_pop(L, 1); /* remove previous result */
  504. /* try global variable (and create one if it does not exist) */
  505. if (luaL_findtable(L, LUA_GLOBALSINDEX, modname, 1) != NULL)
  506. lj_err_callerv(L, LJ_ERR_BADMODN, modname);
  507. lua_pushvalue(L, -1);
  508. lua_setfield(L, loaded, modname); /* _LOADED[modname] = new table */
  509. }
  510. /* check whether table already has a _NAME field */
  511. lua_getfield(L, -1, "_NAME");
  512. if (!lua_isnil(L, -1)) { /* is table an initialized module? */
  513. lua_pop(L, 1);
  514. } else { /* no; initialize it */
  515. lua_pop(L, 1);
  516. modinit(L, modname);
  517. }
  518. lua_pushvalue(L, -1);
  519. setfenv(L);
  520. dooptions(L, loaded - 1);
  521. return 0;
  522. }
  523. static int lj_cf_package_seeall(lua_State *L)
  524. {
  525. luaL_checktype(L, 1, LUA_TTABLE);
  526. if (!lua_getmetatable(L, 1)) {
  527. lua_createtable(L, 0, 1); /* create new metatable */
  528. lua_pushvalue(L, -1);
  529. lua_setmetatable(L, 1);
  530. }
  531. lua_pushvalue(L, LUA_GLOBALSINDEX);
  532. lua_setfield(L, -2, "__index"); /* mt.__index = _G */
  533. return 0;
  534. }
  535. /* ------------------------------------------------------------------------ */
  536. #define AUXMARK "\1"
  537. static void setpath(lua_State *L, const char *fieldname, const char *envname,
  538. const char *def, int noenv)
  539. {
  540. #if LJ_TARGET_CONSOLE
  541. const char *path = NULL;
  542. UNUSED(envname);
  543. #else
  544. const char *path = getenv(envname);
  545. #endif
  546. if (path == NULL || noenv) {
  547. lua_pushstring(L, def);
  548. } else {
  549. path = luaL_gsub(L, path, LUA_PATHSEP LUA_PATHSEP,
  550. LUA_PATHSEP AUXMARK LUA_PATHSEP);
  551. luaL_gsub(L, path, AUXMARK, def);
  552. lua_remove(L, -2);
  553. }
  554. setprogdir(L);
  555. lua_setfield(L, -2, fieldname);
  556. }
  557. static const luaL_Reg package_lib[] = {
  558. { "loadlib", lj_cf_package_loadlib },
  559. { "searchpath", lj_cf_package_searchpath },
  560. { "seeall", lj_cf_package_seeall },
  561. { NULL, NULL }
  562. };
  563. static const luaL_Reg package_global[] = {
  564. { "module", lj_cf_package_module },
  565. { "require", lj_cf_package_require },
  566. { NULL, NULL }
  567. };
  568. static const lua_CFunction package_loaders[] =
  569. {
  570. lj_cf_package_loader_preload,
  571. lj_cf_package_loader_lua,
  572. lj_cf_package_loader_c,
  573. lj_cf_package_loader_croot,
  574. NULL
  575. };
  576. LUALIB_API int luaopen_package(lua_State *L)
  577. {
  578. int i;
  579. int noenv;
  580. luaL_newmetatable(L, "_LOADLIB");
  581. lj_lib_pushcf(L, lj_cf_package_unloadlib, 1);
  582. lua_setfield(L, -2, "__gc");
  583. luaL_register(L, LUA_LOADLIBNAME, package_lib);
  584. lua_pushvalue(L, -1);
  585. lua_replace(L, LUA_ENVIRONINDEX);
  586. lua_createtable(L, sizeof(package_loaders)/sizeof(package_loaders[0])-1, 0);
  587. for (i = 0; package_loaders[i] != NULL; i++) {
  588. lj_lib_pushcf(L, package_loaders[i], 1);
  589. lua_rawseti(L, -2, i+1);
  590. }
  591. lua_setfield(L, -2, "loaders");
  592. lua_getfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");
  593. noenv = lua_toboolean(L, -1);
  594. lua_pop(L, 1);
  595. setpath(L, "path", LUA_PATH, LUA_PATH_DEFAULT, noenv);
  596. setpath(L, "cpath", LUA_CPATH, LUA_CPATH_DEFAULT, noenv);
  597. lua_pushliteral(L, LUA_PATH_CONFIG);
  598. lua_setfield(L, -2, "config");
  599. luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 16);
  600. lua_setfield(L, -2, "loaded");
  601. luaL_findtable(L, LUA_REGISTRYINDEX, "_PRELOAD", 4);
  602. lua_setfield(L, -2, "preload");
  603. lua_pushvalue(L, LUA_GLOBALSINDEX);
  604. luaL_register(L, NULL, package_global);
  605. lua_pop(L, 1);
  606. return 1;
  607. }