summaryrefslogtreecommitdiff
path: root/apps/plugins/lua/loadlib.c
diff options
context:
space:
mode:
authorRichard Quirk <richard.quirk@gmail.com>2014-03-19 19:31:31 +0100
committerMarcin Bukat <marcin.bukat@gmail.com>2014-04-02 20:31:54 +0200
commit36378988ad4059982742f05f5eb50580b456840a (patch)
treeee70be810d894566c5e351f21a1ebb79be742a85 /apps/plugins/lua/loadlib.c
parent020f16a1c7d5bc9a302671cef03f56ac735e20c5 (diff)
downloadrockbox-36378988ad4059982742f05f5eb50580b456840a.tar.gz
rockbox-36378988ad4059982742f05f5eb50580b456840a.zip
Update lua plugin to 5.2.3
Prior to this patch the Lua plugin used version 5.1.4. This change reduces the number of modifications in the Lua source using some new defines and because the upstream source is now more flexible. Unless otherwise stated, l*.[ch] files are taken unmodified from the upstream lua-5.2.3. fscanf.c: file descriptors in rockbox are just ints, they are hidden behind a void* now so liolib requires less modifications. fscanf is updated to use void* too. getc.c: this is a new file required for getc implementation in lauxlib.c lauxlib.c: LoadF replaced FILE* with int, the rockbox file descriptor int are cast to FILE* (actually void* due to typedef). getc uses the PREFIX version. stdin is not used, as per 5.1.4. lbaselib.c: now uses strspn in the number parsing. print uses DEBUGF now rather than being commented out. lbitlib.c: use the built-in version from 5.2.3 rather than Reuben Thomas's external library. Backwards compatible and adds some new bit operations. ldo.c: the LUAI_THROW/TRY defines are now in the core lua code, so have been removed from rockconf.h liolib.c: here the implementation has changed to use the LStream from the original source, and cast the FILE* pointers to int. This has reduced the number of modifications from the upstream version. llex.c: the only change from upstream is to remove the locale include. lmathlib.c: updated from the 5.2.3 version and re-applied the changes that were made vs 5.1.4 for random numbers and to remove unsupported float functions. loadlib.c: upstream version, with the 5.1.4 changes for missing functions. lobject.c: upstream version, with ctype.h added and sprintf changed to snprintf. loslib.c: upstream version with locale.h removed and 5.1.4 changes for unsupportable functions. lstrlib.c: sprintf changed to snprintf. ltable.c: upstream with the hashnum function from 5.1.4 to avoid frexp in luai_hashnum. luaconf.h: updated to 5.2.3 version, restored relevant parts from the original 5.1.4 configuration. The COMPAT defines that are no longer available are not included. lundump.c: VERSION macro conflicts with the core Rockbox equivalent. rocklib.c: luaL_reg is no longer available, replaced by luaL_Reg equivalent. Moved checkboolean/optboolean functions to this file and out of core lua files. luaL_getn is no longer available, replaced by luaL_rawlen. luaL_register is deprecated, use the newlib/setfuncs replacements. rli_init has to be called before setting up the newlib to avoid overwriting the rb table. rocklib_aux.pl: use rli_checkboolean from rocklib.c. rocklua.c: new default bits library used, update the library loading code with idiomatic 5.2 code. strcspn.c: no longer needed, but strspn.c is required for strspn in lbaselib.c Change-Id: I0c7945c755f79083afe98ec117e1e8cf13de2651 Reviewed-on: http://gerrit.rockbox.org/774 Tested: Richard Quirk <richard.quirk@gmail.com> Reviewed-by: Marcin Bukat <marcin.bukat@gmail.com>
Diffstat (limited to 'apps/plugins/lua/loadlib.c')
-rw-r--r--apps/plugins/lua/loadlib.c650
1 files changed, 525 insertions, 125 deletions
diff --git a/apps/plugins/lua/loadlib.c b/apps/plugins/lua/loadlib.c
index 1cc7ebd7db..f5a63386b5 100644
--- a/apps/plugins/lua/loadlib.c
+++ b/apps/plugins/lua/loadlib.c
@@ -1,14 +1,22 @@
1/* 1/*
2** $Id: loadlib.c,v 1.52.1.3 2008/08/06 13:29:28 roberto Exp $ 2** $Id: loadlib.c,v 1.111.1.1 2013/04/12 18:48:47 roberto Exp $
3** Dynamic library loader for Lua 3** Dynamic library loader for Lua
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5** 5**
6** This module contains an implementation of loadlib for Unix systems 6** This module contains an implementation of loadlib for Unix systems
7** that have dlfcn, an implementation for Darwin (Mac OS X), an 7** that have dlfcn, an implementation for Windows, and a stub for other
8** implementation for Windows, and a stub for other systems. 8** systems.
9*/ 9*/
10 10
11 11
12/*
13** if needed, includes windows header before everything else
14*/
15#if defined(_WIN32)
16#include <windows.h>
17#endif
18
19
12#include <stdlib.h> 20#include <stdlib.h>
13#include <string.h> 21#include <string.h>
14 22
@@ -20,10 +28,296 @@
20 28
21#include "lauxlib.h" 29#include "lauxlib.h"
22#include "lualib.h" 30#include "lualib.h"
23#include "rocklib.h"
24 31
25 32
26#define setprogdir(L) ((void)0) 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*/
111static void ll_unloadlib (void *lib);
112static void *ll_load (lua_State *L, const char *path, int seeglb);
113static 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
129static void ll_unloadlib (void *lib) {
130 dlclose(lib);
131}
132
133
134static void *ll_load (lua_State *L, const char *path, int seeglb) {
135 void *lib = dlopen(path, RTLD_NOW | (seeglb ? RTLD_GLOBAL : RTLD_LOCAL));
136 if (lib == NULL) lua_pushstring(L, dlerror());
137 return lib;
138}
139
140
141static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
142 lua_CFunction f = (lua_CFunction)dlsym(lib, sym);
143 if (f == NULL) lua_pushstring(L, dlerror());
144 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
168static 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 = rb->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
183static 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
193static void ll_unloadlib (void *lib) {
194 FreeLibrary((HMODULE)lib);
195}
196
197
198static 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
206static 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
229static void ll_unloadlib (void *lib) {
230 (void)(lib); /* not used */
231}
232
233
234static 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
241static 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
251static void *ll_checkclib (lua_State *L, const char *path) {
252 void *plib;
253 lua_getfield(L, LUA_REGISTRYINDEX, CLIBS);
254 lua_getfield(L, -1, path);
255 plib = lua_touserdata(L, -1); /* plib = CLIBS[path] */
256 lua_pop(L, 2); /* pop CLIBS table and 'plib' */
257 return plib;
258}
259
260
261static void ll_addtoclib (lua_State *L, const char *path, void *plib) {
262 lua_getfield(L, LUA_REGISTRYINDEX, CLIBS);
263 lua_pushlightuserdata(L, plib);
264 lua_pushvalue(L, -1);
265 lua_setfield(L, -3, path); /* CLIBS[path] = plib */
266 lua_rawseti(L, -2, luaL_len(L, -2) + 1); /* CLIBS[#CLIBS + 1] = plib */
267 lua_pop(L, 1); /* pop CLIBS table */
268}
269
270
271/*
272** __gc tag method for CLIBS table: calls 'll_unloadlib' for all lib
273** handles in list CLIBS
274*/
275static int gctm (lua_State *L) {
276 int n = luaL_len(L, 1);
277 for (; n >= 1; n--) { /* for each handle, in reverse order */
278 lua_rawgeti(L, 1, n); /* get handle CLIBS[n] */
279 ll_unloadlib(lua_touserdata(L, -1));
280 lua_pop(L, 1); /* pop handle */
281 }
282 return 0;
283}
284
285
286static int ll_loadfunc (lua_State *L, const char *path, const char *sym) {
287 void *reg = ll_checkclib(L, path); /* check loaded C libraries */
288 if (reg == NULL) { /* must load library? */
289 reg = ll_load(L, path, *sym == '*');
290 if (reg == NULL) return ERRLIB; /* unable to load library */
291 ll_addtoclib(L, path, reg);
292 }
293 if (*sym == '*') { /* loading only library (no function)? */
294 lua_pushboolean(L, 1); /* return 'true' */
295 return 0; /* no errors */
296 }
297 else {
298 lua_CFunction f = ll_sym(L, reg, sym);
299 if (f == NULL)
300 return ERRFUNC; /* unable to find function */
301 lua_pushcfunction(L, f); /* else create new function */
302 return 0; /* no errors */
303 }
304}
305
306
307static int ll_loadlib (lua_State *L) {
308 const char *path = luaL_checkstring(L, 1);
309 const char *init = luaL_checkstring(L, 2);
310 int stat = ll_loadfunc(L, path, init);
311 if (stat == 0) /* no errors? */
312 return 1; /* return the loaded function */
313 else { /* error; error message is on stack top */
314 lua_pushnil(L);
315 lua_insert(L, -2);
316 lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init");
317 return 3; /* return nil, error message, and where */
318 }
319}
320
27 321
28 322
29/* 323/*
@@ -34,70 +328,143 @@
34 328
35 329
36static int readable (const char *filename) { 330static int readable (const char *filename) {
37 int f = rb->open(filename, O_RDONLY); /* try to open file */ 331 return rb->file_exists(filename);
38 if (f < 0) return 0; /* open failed */
39 rb->close(f);
40 return 1;
41} 332}
42 333
43 334
44static const char *pushnexttemplate (lua_State *L, const char *path) { 335static const char *pushnexttemplate (lua_State *L, const char *path) {
45 const char *l; 336 const char *l;
46 while (*path == *LUA_PATHSEP) path++; /* skip separators */ 337 while (*path == *LUA_PATH_SEP) path++; /* skip separators */
47 if (*path == '\0') return NULL; /* no more templates */ 338 if (*path == '\0') return NULL; /* no more templates */
48 l = strchr(path, *LUA_PATHSEP); /* find next separator */ 339 l = strchr(path, *LUA_PATH_SEP); /* find next separator */
49 if (l == NULL) l = path + strlen(path); 340 if (l == NULL) l = path + strlen(path);
50 lua_pushlstring(L, path, l - path); /* template */ 341 lua_pushlstring(L, path, l - path); /* template */
51 return l; 342 return l;
52} 343}
53 344
54 345
55static const char *findfile (lua_State *L, const char *name, 346static const char *searchpath (lua_State *L, const char *name,
56 const char *pname) { 347 const char *path,
57 const char *path, *current_path = get_current_path(L, 2); 348 const char *sep,
58 name = luaL_gsub(L, name, ".", LUA_DIRSEP); 349 const char *dirsep) {
59 lua_getfield(L, LUA_ENVIRONINDEX, pname); 350 luaL_Buffer msg; /* to build error message */
60 path = lua_tostring(L, -1); 351 luaL_buffinit(L, &msg);
61 if (path == NULL) 352 if (*sep != '\0') /* non-empty separator? */
62 luaL_error(L, LUA_QL("package.%s") " must be a string", pname); 353 name = luaL_gsub(L, name, sep, dirsep); /* replace it by 'dirsep' */
63 lua_pushliteral(L, ""); /* error accumulator */
64 while ((path = pushnexttemplate(L, path)) != NULL) { 354 while ((path = pushnexttemplate(L, path)) != NULL) {
65 const char *filename; 355 const char *filename = luaL_gsub(L, lua_tostring(L, -1),
66 filename = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name); 356 LUA_PATH_MARK, name);
67 if(current_path != NULL) filename = luaL_gsub(L, filename, "$", current_path);
68 lua_remove(L, -2); /* remove path template */ 357 lua_remove(L, -2); /* remove path template */
69 if (readable(filename)) /* does file exist and is readable? */ 358 if (readable(filename)) /* does file exist and is readable? */
70 return filename; /* return that file name */ 359 return filename; /* return that file name */
71 lua_pushfstring(L, "\n\tno file " LUA_QS, filename); 360 lua_pushfstring(L, "\n\tno file " LUA_QS, filename);
72 lua_remove(L, -2); /* remove file name */ 361 lua_remove(L, -2); /* remove file name */
73 lua_concat(L, 2); /* add entry to possible error message */ 362 luaL_addvalue(&msg); /* concatenate error msg. entry */
74 } 363 }
364 luaL_pushresult(&msg); /* create error message */
75 return NULL; /* not found */ 365 return NULL; /* not found */
76} 366}
77 367
78 368
79static void loaderror (lua_State *L, const char *filename) { 369static int ll_searchpath (lua_State *L) {
80 luaL_error(L, "error loading module " LUA_QS " from file " LUA_QS ":\n\t%s", 370 const char *f = searchpath(L, luaL_checkstring(L, 1),
81 lua_tostring(L, 1), filename, lua_tostring(L, -1)); 371 luaL_checkstring(L, 2),
372 luaL_optstring(L, 3, "."),
373 luaL_optstring(L, 4, LUA_DIRSEP));
374 if (f != NULL) return 1;
375 else { /* error message is on top of the stack */
376 lua_pushnil(L);
377 lua_insert(L, -2);
378 return 2; /* return nil + error message */
379 }
82} 380}
83 381
84 382
85static int loader_Lua (lua_State *L) { 383static const char *findfile (lua_State *L, const char *name,
384 const char *pname,
385 const char *dirsep) {
386 const char *path;
387 lua_getfield(L, lua_upvalueindex(1), pname);
388 path = lua_tostring(L, -1);
389 if (path == NULL)
390 luaL_error(L, LUA_QL("package.%s") " must be a string", pname);
391 return searchpath(L, name, path, ".", dirsep);
392}
393
394
395static int checkload (lua_State *L, int stat, const char *filename) {
396 if (stat) { /* module loaded successfully? */
397 lua_pushstring(L, filename); /* will be 2nd argument to module */
398 return 2; /* return open function and file name */
399 }
400 else
401 return luaL_error(L, "error loading module " LUA_QS
402 " from file " LUA_QS ":\n\t%s",
403 lua_tostring(L, 1), filename, lua_tostring(L, -1));
404}
405
406
407static int searcher_Lua (lua_State *L) {
86 const char *filename; 408 const char *filename;
87 const char *name = luaL_checkstring(L, 1); 409 const char *name = luaL_checkstring(L, 1);
88 filename = findfile(L, name, "path"); 410 filename = findfile(L, name, "path", LUA_LSUBSEP);
89 if (filename == NULL) return 1; /* library not found in this path */ 411 if (filename == NULL) return 1; /* module not found in this path */
90 if (luaL_loadfile(L, filename) != 0) 412 return checkload(L, (luaL_loadfile(L, filename) == LUA_OK), filename);
91 loaderror(L, filename); 413}
92 return 1; /* library loaded successfully */ 414
415
416static int loadfunc (lua_State *L, const char *filename, const char *modname) {
417 const char *funcname;
418 const char *mark;
419 modname = luaL_gsub(L, modname, ".", LUA_OFSEP);
420 mark = strchr(modname, *LUA_IGMARK);
421 if (mark) {
422 int stat;
423 funcname = lua_pushlstring(L, modname, mark - modname);
424 funcname = lua_pushfstring(L, LUA_POF"%s", funcname);
425 stat = ll_loadfunc(L, filename, funcname);
426 if (stat != ERRFUNC) return stat;
427 modname = mark + 1; /* else go ahead and try old-style name */
428 }
429 funcname = lua_pushfstring(L, LUA_POF"%s", modname);
430 return ll_loadfunc(L, filename, funcname);
93} 431}
94 432
95 433
96static int loader_preload (lua_State *L) { 434static int searcher_C (lua_State *L) {
97 const char *name = luaL_checkstring(L, 1); 435 const char *name = luaL_checkstring(L, 1);
98 lua_getfield(L, LUA_ENVIRONINDEX, "preload"); 436 const char *filename = findfile(L, name, "cpath", LUA_CSUBSEP);
99 if (!lua_istable(L, -1)) 437 if (filename == NULL) return 1; /* module not found in this path */
100 luaL_error(L, LUA_QL("package.preload") " must be a table"); 438 return checkload(L, (loadfunc(L, filename, name) == 0), filename);
439}
440
441
442static int searcher_Croot (lua_State *L) {
443 const char *filename;
444 const char *name = luaL_checkstring(L, 1);
445 const char *p = strchr(name, '.');
446 int stat;
447 if (p == NULL) return 0; /* is root */
448 lua_pushlstring(L, name, p - name);
449 filename = findfile(L, lua_tostring(L, -1), "cpath", LUA_CSUBSEP);
450 if (filename == NULL) return 1; /* root not found */
451 if ((stat = loadfunc(L, filename, name)) != 0) {
452 if (stat != ERRFUNC)
453 return checkload(L, 0, filename); /* real error */
454 else { /* open function not found */
455 lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS,
456 name, filename);
457 return 1;
458 }
459 }
460 lua_pushstring(L, filename); /* will be 2nd argument to module */
461 return 2;
462}
463
464
465static int searcher_preload (lua_State *L) {
466 const char *name = luaL_checkstring(L, 1);
467 lua_getfield(L, LUA_REGISTRYINDEX, "_PRELOAD");
101 lua_getfield(L, -1, name); 468 lua_getfield(L, -1, name);
102 if (lua_isnil(L, -1)) /* not found? */ 469 if (lua_isnil(L, -1)) /* not found? */
103 lua_pushfstring(L, "\n\tno field package.preload['%s']", name); 470 lua_pushfstring(L, "\n\tno field package.preload['%s']", name);
@@ -105,48 +472,53 @@ static int loader_preload (lua_State *L) {
105} 472}
106 473
107 474
108static const int sentinel_ = 0; 475static void findloader (lua_State *L, const char *name) {
109#define sentinel ((void *)&sentinel_) 476 int i;
477 luaL_Buffer msg; /* to build error message */
478 luaL_buffinit(L, &msg);
479 lua_getfield(L, lua_upvalueindex(1), "searchers"); /* will be at index 3 */
480 if (!lua_istable(L, 3))
481 luaL_error(L, LUA_QL("package.searchers") " must be a table");
482 /* iterate over available searchers to find a loader */
483 for (i = 1; ; i++) {
484 lua_rawgeti(L, 3, i); /* get a searcher */
485 if (lua_isnil(L, -1)) { /* no more searchers? */
486 lua_pop(L, 1); /* remove nil */
487 luaL_pushresult(&msg); /* create error message */
488 luaL_error(L, "module " LUA_QS " not found:%s",
489 name, lua_tostring(L, -1));
490 }
491 lua_pushstring(L, name);
492 lua_call(L, 1, 2); /* call it */
493 if (lua_isfunction(L, -2)) /* did it find a loader? */
494 return; /* module loader found */
495 else if (lua_isstring(L, -2)) { /* searcher returned error message? */
496 lua_pop(L, 1); /* remove extra return */
497 luaL_addvalue(&msg); /* concatenate error message */
498 }
499 else
500 lua_pop(L, 2); /* remove both returns */
501 }
502}
110 503
111 504
112static int ll_require (lua_State *L) { 505static int ll_require (lua_State *L) {
113 const char *name = luaL_checkstring(L, 1); 506 const char *name = luaL_checkstring(L, 1);
114 int i;
115 lua_settop(L, 1); /* _LOADED table will be at index 2 */ 507 lua_settop(L, 1); /* _LOADED table will be at index 2 */
116 lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); 508 lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
117 lua_getfield(L, 2, name); 509 lua_getfield(L, 2, name); /* _LOADED[name] */
118 if (lua_toboolean(L, -1)) { /* is it there? */ 510 if (lua_toboolean(L, -1)) /* is it there? */
119 if (lua_touserdata(L, -1) == sentinel) /* check loops */
120 luaL_error(L, "loop or previous error loading module " LUA_QS, name);
121 return 1; /* package is already loaded */ 511 return 1; /* package is already loaded */
122 } 512 /* else must load package */
123 /* else must load it; iterate over available loaders */ 513 lua_pop(L, 1); /* remove 'getfield' result */
124 lua_getfield(L, LUA_ENVIRONINDEX, "loaders"); 514 findloader(L, name);
125 if (!lua_istable(L, -1)) 515 lua_pushstring(L, name); /* pass name as argument to module loader */
126 luaL_error(L, LUA_QL("package.loaders") " must be a table"); 516 lua_insert(L, -2); /* name is 1st argument (before search data) */
127 lua_pushliteral(L, ""); /* error message accumulator */ 517 lua_call(L, 2, 1); /* run loader to load module */
128 for (i=1; ; i++) {
129 lua_rawgeti(L, -2, i); /* get a loader */
130 if (lua_isnil(L, -1))
131 luaL_error(L, "module " LUA_QS " not found:%s",
132 name, lua_tostring(L, -2));
133 lua_pushstring(L, name);
134 lua_call(L, 1, 1); /* call it */
135 if (lua_isfunction(L, -1)) /* did it find module? */
136 break; /* module loaded successfully */
137 else if (lua_isstring(L, -1)) /* loader returned error message? */
138 lua_concat(L, 2); /* accumulate it */
139 else
140 lua_pop(L, 1);
141 }
142 lua_pushlightuserdata(L, sentinel);
143 lua_setfield(L, 2, name); /* _LOADED[name] = sentinel */
144 lua_pushstring(L, name); /* pass name as argument to module */
145 lua_call(L, 1, 1); /* run loaded module */
146 if (!lua_isnil(L, -1)) /* non-nil return? */ 518 if (!lua_isnil(L, -1)) /* non-nil return? */
147 lua_setfield(L, 2, name); /* _LOADED[name] = returned value */ 519 lua_setfield(L, 2, name); /* _LOADED[name] = returned value */
148 lua_getfield(L, 2, name); 520 lua_getfield(L, 2, name);
149 if (lua_touserdata(L, -1) == sentinel) { /* module did not set a value? */ 521 if (lua_isnil(L, -1)) { /* module did not set a value? */
150 lua_pushboolean(L, 1); /* use true as result */ 522 lua_pushboolean(L, 1); /* use true as result */
151 lua_pushvalue(L, -1); /* extra copy to be returned */ 523 lua_pushvalue(L, -1); /* extra copy to be returned */
152 lua_setfield(L, 2, name); /* _LOADED[name] = true */ 524 lua_setfield(L, 2, name); /* _LOADED[name] = true */
@@ -163,26 +535,31 @@ static int ll_require (lua_State *L) {
163** 'module' function 535** 'module' function
164** ======================================================= 536** =======================================================
165*/ 537*/
166 538#if defined(LUA_COMPAT_MODULE)
167 539
168static void setfenv (lua_State *L) { 540/*
541** changes the environment variable of calling function
542*/
543static void set_env (lua_State *L) {
169 lua_Debug ar; 544 lua_Debug ar;
170 if (lua_getstack(L, 1, &ar) == 0 || 545 if (lua_getstack(L, 1, &ar) == 0 ||
171 lua_getinfo(L, "f", &ar) == 0 || /* get calling function */ 546 lua_getinfo(L, "f", &ar) == 0 || /* get calling function */
172 lua_iscfunction(L, -1)) 547 lua_iscfunction(L, -1))
173 luaL_error(L, LUA_QL("module") " not called from a Lua function"); 548 luaL_error(L, LUA_QL("module") " not called from a Lua function");
174 lua_pushvalue(L, -2); 549 lua_pushvalue(L, -2); /* copy new environment table to top */
175 lua_setfenv(L, -2); 550 lua_setupvalue(L, -2, 1);
176 lua_pop(L, 1); 551 lua_pop(L, 1); /* remove function */
177} 552}
178 553
179 554
180static void dooptions (lua_State *L, int n) { 555static void dooptions (lua_State *L, int n) {
181 int i; 556 int i;
182 for (i = 2; i <= n; i++) { 557 for (i = 2; i <= n; i++) {
183 lua_pushvalue(L, i); /* get option (a function) */ 558 if (lua_isfunction(L, i)) { /* avoid 'calling' extra info. */
184 lua_pushvalue(L, -2); /* module */ 559 lua_pushvalue(L, i); /* get option (a function) */
185 lua_call(L, 1, 0); 560 lua_pushvalue(L, -2); /* module */
561 lua_call(L, 1, 0);
562 }
186 } 563 }
187} 564}
188 565
@@ -204,17 +581,8 @@ static void modinit (lua_State *L, const char *modname) {
204 581
205static int ll_module (lua_State *L) { 582static int ll_module (lua_State *L) {
206 const char *modname = luaL_checkstring(L, 1); 583 const char *modname = luaL_checkstring(L, 1);
207 int loaded = lua_gettop(L) + 1; /* index of _LOADED table */ 584 int lastarg = lua_gettop(L); /* last parameter */
208 lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); 585 luaL_pushmodule(L, modname, 1); /* get/create module table */
209 lua_getfield(L, loaded, modname); /* get _LOADED[modname] */
210 if (!lua_istable(L, -1)) { /* not found? */
211 lua_pop(L, 1); /* remove previous result */
212 /* try global variable (and create one if it does not exist) */
213 if (luaL_findtable(L, LUA_GLOBALSINDEX, modname, 1) != NULL)
214 return luaL_error(L, "name conflict for module " LUA_QS, modname);
215 lua_pushvalue(L, -1);
216 lua_setfield(L, loaded, modname); /* _LOADED[modname] = new table */
217 }
218 /* check whether table already has a _NAME field */ 586 /* check whether table already has a _NAME field */
219 lua_getfield(L, -1, "_NAME"); 587 lua_getfield(L, -1, "_NAME");
220 if (!lua_isnil(L, -1)) /* is table an initialized module? */ 588 if (!lua_isnil(L, -1)) /* is table an initialized module? */
@@ -224,9 +592,9 @@ static int ll_module (lua_State *L) {
224 modinit(L, modname); 592 modinit(L, modname);
225 } 593 }
226 lua_pushvalue(L, -1); 594 lua_pushvalue(L, -1);
227 setfenv(L); 595 set_env(L);
228 dooptions(L, loaded - 1); 596 dooptions(L, lastarg);
229 return 0; 597 return 1;
230} 598}
231 599
232 600
@@ -237,22 +605,38 @@ static int ll_seeall (lua_State *L) {
237 lua_pushvalue(L, -1); 605 lua_pushvalue(L, -1);
238 lua_setmetatable(L, 1); 606 lua_setmetatable(L, 1);
239 } 607 }
240 lua_pushvalue(L, LUA_GLOBALSINDEX); 608 lua_pushglobaltable(L);
241 lua_setfield(L, -2, "__index"); /* mt.__index = _G */ 609 lua_setfield(L, -2, "__index"); /* mt.__index = _G */
242 return 0; 610 return 0;
243} 611}
244 612
245 613#endif
246/* }====================================================== */ 614/* }====================================================== */
247 615
248 616
249 617
250/* auxiliary mark (for internal use) */ 618/* auxiliary mark (for internal use) */
251#define AUXMARK "\1" 619#define AUXMARK "\1"
620
621
622/*
623** return registry.LUA_NOENV as a boolean
624*/
625#if 0
626static int noenv (lua_State *L) {
627 int b;
628 lua_getfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");
629 b = lua_toboolean(L, -1);
630 lua_pop(L, 1); /* remove value */
631 return b;
632}
633#endif
634
252 635
253static void setpath (lua_State *L, const char *fieldname, const char *envname, 636static void setpath (lua_State *L, const char *fieldname, const char *envname1,
254 const char *def) { 637 const char *envname2, const char *def) {
255 (void)envname; 638 (void)envname1;
639 (void)envname2;
256 lua_pushstring(L, def); /* use default */ 640 lua_pushstring(L, def); /* use default */
257 setprogdir(L); 641 setprogdir(L);
258 lua_setfield(L, -2, fieldname); 642 lua_setfield(L, -2, fieldname);
@@ -260,56 +644,72 @@ static void setpath (lua_State *L, const char *fieldname, const char *envname,
260 644
261 645
262static const luaL_Reg pk_funcs[] = { 646static const luaL_Reg pk_funcs[] = {
647 {"loadlib", ll_loadlib},
648 {"searchpath", ll_searchpath},
649#if defined(LUA_COMPAT_MODULE)
263 {"seeall", ll_seeall}, 650 {"seeall", ll_seeall},
651#endif
264 {NULL, NULL} 652 {NULL, NULL}
265}; 653};
266 654
267 655
268static const luaL_Reg ll_funcs[] = { 656static const luaL_Reg ll_funcs[] = {
657#if defined(LUA_COMPAT_MODULE)
269 {"module", ll_module}, 658 {"module", ll_module},
659#endif
270 {"require", ll_require}, 660 {"require", ll_require},
271 {NULL, NULL} 661 {NULL, NULL}
272}; 662};
273 663
274 664
275static const lua_CFunction loaders[] = 665static void createsearcherstable (lua_State *L) {
276 {loader_preload, loader_Lua, NULL}; 666 static const lua_CFunction searchers[] =
667 {searcher_preload, searcher_Lua, searcher_C, searcher_Croot, NULL};
668 int i;
669 /* create 'searchers' table */
670 lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0);
671 /* fill it with pre-defined searchers */
672 for (i=0; searchers[i] != NULL; i++) {
673 lua_pushvalue(L, -2); /* set 'package' as upvalue for all searchers */
674 lua_pushcclosure(L, searchers[i], 1);
675 lua_rawseti(L, -2, i+1);
676 }
677}
277 678
278 679
279LUALIB_API int luaopen_package (lua_State *L) { 680LUAMOD_API int luaopen_package (lua_State *L) {
280 int i; 681 /* create table CLIBS to keep track of loaded C libraries */
281 /* create new type _LOADLIB */ 682 luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS);
282 luaL_newmetatable(L, "_LOADLIB"); 683 lua_createtable(L, 0, 1); /* metatable for CLIBS */
684 lua_pushcfunction(L, gctm);
685 lua_setfield(L, -2, "__gc"); /* set finalizer for CLIBS table */
686 lua_setmetatable(L, -2);
283 /* create `package' table */ 687 /* create `package' table */
284 luaL_register(L, LUA_LOADLIBNAME, pk_funcs); 688 luaL_newlib(L, pk_funcs);
285#if defined(LUA_COMPAT_LOADLIB) 689 createsearcherstable(L);
286 lua_getfield(L, -1, "loadlib"); 690#if defined(LUA_COMPAT_LOADERS)
287 lua_setfield(L, LUA_GLOBALSINDEX, "loadlib"); 691 lua_pushvalue(L, -1); /* make a copy of 'searchers' table */
692 lua_setfield(L, -3, "loaders"); /* put it in field `loaders' */
288#endif 693#endif
289 lua_pushvalue(L, -1); 694 lua_setfield(L, -2, "searchers"); /* put it in field 'searchers' */
290 lua_replace(L, LUA_ENVIRONINDEX); 695 /* set field 'path' */
291 /* create `loaders' table */ 696 setpath(L, "path", LUA_PATHVERSION, LUA_PATH, LUA_PATH_DEFAULT);
292 lua_createtable(L, 0, sizeof(loaders)/sizeof(loaders[0]) - 1); 697 /* set field 'cpath' */
293 /* fill it with pre-defined loaders */ 698 setpath(L, "cpath", LUA_CPATHVERSION, LUA_CPATH, LUA_CPATH_DEFAULT);
294 for (i=0; loaders[i] != NULL; i++) {
295 lua_pushcfunction(L, loaders[i]);
296 lua_rawseti(L, -2, i+1);
297 }
298 lua_setfield(L, -2, "loaders"); /* put it in field `loaders' */
299 setpath(L, "path", LUA_PATH, LUA_PATH_DEFAULT); /* set field `path' */
300 /* store config information */ 699 /* store config information */
301 lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATHSEP "\n" LUA_PATH_MARK "\n" 700 lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATH_SEP "\n" LUA_PATH_MARK "\n"
302 LUA_EXECDIR "\n" LUA_IGMARK); 701 LUA_EXEC_DIR "\n" LUA_IGMARK "\n");
303 lua_setfield(L, -2, "config"); 702 lua_setfield(L, -2, "config");
304 /* set field `loaded' */ 703 /* set field `loaded' */
305 luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 2); 704 luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED");
306 lua_setfield(L, -2, "loaded"); 705 lua_setfield(L, -2, "loaded");
307 /* set field `preload' */ 706 /* set field `preload' */
308 lua_newtable(L); 707 luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD");
309 lua_setfield(L, -2, "preload"); 708 lua_setfield(L, -2, "preload");
310 lua_pushvalue(L, LUA_GLOBALSINDEX); 709 lua_pushglobaltable(L);
311 luaL_register(L, NULL, ll_funcs); /* open lib into global table */ 710 lua_pushvalue(L, -2); /* set 'package' as upvalue for next lib */
312 lua_pop(L, 1); 711 luaL_setfuncs(L, ll_funcs, 1); /* open lib into global table */
712 lua_pop(L, 1); /* pop global table */
313 return 1; /* return 'package' table */ 713 return 1; /* return 'package' table */
314} 714}
315 715