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