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