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