diff options
-rw-r--r-- | lauxlib.c | 52 | ||||
-rw-r--r-- | lauxlib.h | 7 | ||||
-rw-r--r-- | lbaselib.c | 96 |
3 files changed, 80 insertions, 75 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lauxlib.c,v 1.115 2004/06/02 19:06:14 roberto Exp roberto $ | 2 | ** $Id: lauxlib.c,v 1.116 2004/06/17 14:06:52 roberto Exp roberto $ |
3 | ** Auxiliary functions for building Lua libraries | 3 | ** Auxiliary functions for building Lua libraries |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -342,6 +342,56 @@ LUALIB_API int luaL_getn (lua_State *L, int t) { | |||
342 | 342 | ||
343 | 343 | ||
344 | 344 | ||
345 | |||
346 | static const char *pushnexttemplate (lua_State *L, const char *path) { | ||
347 | const char *l; | ||
348 | if (*path == '\0') return NULL; /* no more templates */ | ||
349 | if (*path == LUA_PATH_SEP) path++; /* skip separator */ | ||
350 | l = strchr(path, LUA_PATH_SEP); /* find next separator */ | ||
351 | if (l == NULL) l = path+strlen(path); | ||
352 | lua_pushlstring(L, path, l - path); /* template */ | ||
353 | return l; | ||
354 | } | ||
355 | |||
356 | |||
357 | static void pushcomposename (lua_State *L) { | ||
358 | const char *tem = lua_tostring(L, -1); | ||
359 | const char *wild; | ||
360 | int n = 1; | ||
361 | while ((wild = strchr(tem, LUA_PATH_MARK)) != NULL) { | ||
362 | /* is there stack space for prefix, name, and eventual last suffix? */ | ||
363 | luaL_checkstack(L, 3, "too many marks in a path component"); | ||
364 | lua_pushlstring(L, tem, wild - tem); /* push prefix */ | ||
365 | lua_pushvalue(L, 1); /* push package name (in place of MARK) */ | ||
366 | tem = wild + 1; /* continue after MARK */ | ||
367 | n += 2; | ||
368 | } | ||
369 | lua_pushstring(L, tem); /* push last suffix (`n' already includes this) */ | ||
370 | lua_concat(L, n); | ||
371 | } | ||
372 | |||
373 | |||
374 | LUALIB_API int luaL_searchpath (lua_State *L, const char *name, | ||
375 | const char *path, luaL_Loader f, void *data) { | ||
376 | int status; | ||
377 | const char *p = path; | ||
378 | int top = lua_gettop(L); | ||
379 | do { | ||
380 | lua_settop(L, top); | ||
381 | if ((p = pushnexttemplate(L, p)) == NULL) { | ||
382 | lua_pushfstring(L, "cound not find `%s' in path `%s'", name, path); | ||
383 | return LUA_ERRFILE; | ||
384 | } | ||
385 | pushcomposename(L); | ||
386 | lua_remove(L, -2); /* remove path template */ | ||
387 | lua_assert(lua_gettop(L) == top + 1); | ||
388 | status = f(data, lua_tostring(L, -1)); /* try to load it */ | ||
389 | lua_remove(L, top+1); /* remove file name */ | ||
390 | } while (status == LUA_ERRFILE); | ||
391 | return status; | ||
392 | } | ||
393 | |||
394 | |||
345 | /* | 395 | /* |
346 | ** {====================================================== | 396 | ** {====================================================== |
347 | ** Generic Buffer manipulation | 397 | ** Generic Buffer manipulation |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lauxlib.h,v 1.65 2004/05/31 19:27:14 roberto Exp roberto $ | 2 | ** $Id: lauxlib.h,v 1.66 2004/06/02 17:37:03 roberto Exp roberto $ |
3 | ** Auxiliary functions for building Lua libraries | 3 | ** Auxiliary functions for building Lua libraries |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -25,6 +25,8 @@ typedef struct luaL_reg { | |||
25 | } luaL_reg; | 25 | } luaL_reg; |
26 | 26 | ||
27 | 27 | ||
28 | typedef int (*luaL_Loader)(void *data, const char *name); | ||
29 | |||
28 | LUALIB_API void luaL_openlib (lua_State *L, const char *libname, | 30 | LUALIB_API void luaL_openlib (lua_State *L, const char *libname, |
29 | const luaL_reg *l, int nup); | 31 | const luaL_reg *l, int nup); |
30 | LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *e); | 32 | LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *e); |
@@ -54,6 +56,9 @@ LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...); | |||
54 | 56 | ||
55 | LUALIB_API int luaL_findstring (const char *st, const char *const lst[]); | 57 | LUALIB_API int luaL_findstring (const char *st, const char *const lst[]); |
56 | 58 | ||
59 | LUALIB_API int luaL_searchpath (lua_State *L, const char *name, | ||
60 | const char *path, luaL_Loader f, void *data); | ||
61 | |||
57 | LUALIB_API int luaL_ref (lua_State *L, int t); | 62 | LUALIB_API int luaL_ref (lua_State *L, int t); |
58 | LUALIB_API void luaL_unref (lua_State *L, int t, int ref); | 63 | LUALIB_API void luaL_unref (lua_State *L, int t, int ref); |
59 | 64 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lbaselib.c,v 1.147 2004/06/15 13:31:30 roberto Exp roberto $ | 2 | ** $Id: lbaselib.c,v 1.148 2004/06/21 16:45:09 roberto Exp roberto $ |
3 | ** Basic library | 3 | ** Basic library |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -261,7 +261,11 @@ static int luaB_loadstring (lua_State *L) { | |||
261 | 261 | ||
262 | static int luaB_loadfile (lua_State *L) { | 262 | static int luaB_loadfile (lua_State *L) { |
263 | const char *fname = luaL_optstring(L, 1, NULL); | 263 | const char *fname = luaL_optstring(L, 1, NULL); |
264 | return load_aux(L, luaL_loadfile(L, fname)); | 264 | const char *path = luaL_optstring(L, 2, NULL); |
265 | int status = (path == NULL) | ||
266 | ? luaL_loadfile(L, fname) | ||
267 | : luaL_searchpath(L, fname, path, (luaL_Loader)luaL_loadfile, L); | ||
268 | return load_aux(L, status); | ||
265 | } | 269 | } |
266 | 270 | ||
267 | 271 | ||
@@ -455,7 +459,6 @@ static const char *getpath (lua_State *L) { | |||
455 | const char *path; | 459 | const char *path; |
456 | lua_getglobal(L, LUA_PATH); /* try global variable */ | 460 | lua_getglobal(L, LUA_PATH); /* try global variable */ |
457 | path = lua_tostring(L, -1); | 461 | path = lua_tostring(L, -1); |
458 | lua_pop(L, 1); | ||
459 | if (path) return path; | 462 | if (path) return path; |
460 | path = getenv(LUA_PATH); /* else try environment variable */ | 463 | path = getenv(LUA_PATH); /* else try environment variable */ |
461 | if (path) return path; | 464 | if (path) return path; |
@@ -463,81 +466,28 @@ static const char *getpath (lua_State *L) { | |||
463 | } | 466 | } |
464 | 467 | ||
465 | 468 | ||
466 | static const char *pushnextpath (lua_State *L, const char *path) { | ||
467 | const char *l; | ||
468 | if (*path == '\0') return NULL; /* no more paths */ | ||
469 | if (*path == LUA_PATH_SEP) path++; /* skip separator */ | ||
470 | l = strchr(path, LUA_PATH_SEP); /* find next separator */ | ||
471 | if (l == NULL) l = path+strlen(path); | ||
472 | lua_pushlstring(L, path, l - path); /* directory name */ | ||
473 | return l; | ||
474 | } | ||
475 | |||
476 | |||
477 | static void pushcomposename (lua_State *L) { | ||
478 | const char *path = lua_tostring(L, -1); | ||
479 | const char *wild; | ||
480 | int n = 1; | ||
481 | while ((wild = strchr(path, LUA_PATH_MARK)) != NULL) { | ||
482 | /* is there stack space for prefix, name, and eventual last suffix? */ | ||
483 | luaL_checkstack(L, 3, "too many marks in a path component"); | ||
484 | lua_pushlstring(L, path, wild - path); /* push prefix */ | ||
485 | lua_pushvalue(L, 1); /* push package name (in place of MARK) */ | ||
486 | path = wild + 1; /* continue after MARK */ | ||
487 | n += 2; | ||
488 | } | ||
489 | lua_pushstring(L, path); /* push last suffix (`n' already includes this) */ | ||
490 | lua_concat(L, n); | ||
491 | } | ||
492 | |||
493 | |||
494 | static int luaB_require (lua_State *L) { | 469 | static int luaB_require (lua_State *L) { |
495 | const char *path; | 470 | const char *name = luaL_checkstring(L, 1); |
496 | int status = LUA_ERRFILE; /* not found (yet) */ | 471 | const char *path = getpath(L); |
497 | luaL_checkstring(L, 1); | ||
498 | lua_settop(L, 1); | ||
499 | lua_getglobal(L, REQTAB); | 472 | lua_getglobal(L, REQTAB); |
500 | if (!lua_istable(L, 2)) return luaL_error(L, "`" REQTAB "' is not a table"); | 473 | if (!lua_istable(L, -1)) |
501 | path = getpath(L); | 474 | return luaL_error(L, "global `" REQTAB "' is not a table"); |
502 | lua_pushvalue(L, 1); /* check package's name in book-keeping table */ | 475 | lua_getfield(L, -1, name); |
503 | lua_rawget(L, 2); | ||
504 | if (lua_toboolean(L, -1)) /* is it there? */ | 476 | if (lua_toboolean(L, -1)) /* is it there? */ |
505 | return 1; /* package is already loaded; return its result */ | 477 | return 1; /* package is already loaded; return its result */ |
506 | else { /* must load it */ | 478 | /* else must load it */ |
507 | while (status == LUA_ERRFILE) { | 479 | if (luaL_searchpath(L, name, path, (luaL_Loader)luaL_loadfile, L) != 0) |
508 | lua_settop(L, 3); /* reset stack position */ | 480 | return luaL_error(L, "error loading package `%s' (%s)", name, |
509 | if ((path = pushnextpath(L, path)) == NULL) break; | 481 | lua_tostring(L, -1)); |
510 | pushcomposename(L); | 482 | lua_pushvalue(L, 1); /* pass name as argument to module */ |
511 | status = luaL_loadfile(L, lua_tostring(L, -1)); /* try to load it */ | 483 | lua_call(L, 1, 1); /* run loaded module */ |
512 | } | 484 | if (lua_isnil(L, -1)) { /* nil return? */ |
513 | } | 485 | lua_pop(L, 1); /* remove it */ |
514 | switch (status) { | 486 | lua_pushboolean(L, 1); /* replace to true */ |
515 | case 0: { | ||
516 | lua_getglobal(L, "_REQUIREDNAME"); /* save previous name */ | ||
517 | lua_insert(L, -2); /* put it below function */ | ||
518 | lua_pushvalue(L, 1); | ||
519 | lua_setglobal(L, "_REQUIREDNAME"); /* set new name */ | ||
520 | lua_call(L, 0, 1); /* run loaded module */ | ||
521 | lua_insert(L, -2); /* put result below previous name */ | ||
522 | lua_setglobal(L, "_REQUIREDNAME"); /* reset to previous name */ | ||
523 | if (lua_isnil(L, -1)) { /* no/nil return? */ | ||
524 | lua_pushboolean(L, 1); | ||
525 | lua_replace(L, -2); /* replace to true */ | ||
526 | } | ||
527 | lua_pushvalue(L, 1); | ||
528 | lua_pushvalue(L, -2); | ||
529 | lua_rawset(L, 2); /* mark it as loaded */ | ||
530 | return 1; /* return value */ | ||
531 | } | ||
532 | case LUA_ERRFILE: { /* file not found */ | ||
533 | return luaL_error(L, "could not load package `%s' from path `%s'", | ||
534 | lua_tostring(L, 1), getpath(L)); | ||
535 | } | ||
536 | default: { | ||
537 | return luaL_error(L, "error loading package `%s' (%s)", | ||
538 | lua_tostring(L, 1), lua_tostring(L, -1)); | ||
539 | } | ||
540 | } | 487 | } |
488 | lua_pushvalue(L, -1); /* duplicate result (to return it) */ | ||
489 | lua_setfield(L, -4, name); /* mark `name' as loaded */ | ||
490 | return 1; /* return value */ | ||
541 | } | 491 | } |
542 | 492 | ||
543 | /* }====================================================== */ | 493 | /* }====================================================== */ |