diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2004-06-21 17:05:29 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2004-06-21 17:05:29 -0300 |
| commit | 0c49857c1ab08a5adfe1e21e5370e8aa132e4da1 (patch) | |
| tree | 293301c3531f061c3a8bf7b7da898309dd3af21e | |
| parent | 6b41e84da577b2d31cc659255b036bd0c2d6483f (diff) | |
| download | lua-0c49857c1ab08a5adfe1e21e5370e8aa132e4da1.tar.gz lua-0c49857c1ab08a5adfe1e21e5370e8aa132e4da1.tar.bz2 lua-0c49857c1ab08a5adfe1e21e5370e8aa132e4da1.zip | |
new scheme to search paths
| -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 | /* }====================================================== */ |
