|
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 |
|
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, 0, sizeof(loaders)/sizeof(loaders[0]) - 1); |
|
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 |