diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2005-01-14 12:17:18 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2005-01-14 12:17:18 -0200 |
| commit | d2bda8046c1061c353f9e787e987772b9f96099b (patch) | |
| tree | af04c46ca7e3dc02cd44008c5e2a2f881cf97dc2 | |
| parent | a72fbf794d263d6c2e99e06f4efbe7a75d532a8c (diff) | |
| download | lua-d2bda8046c1061c353f9e787e987772b9f96099b.tar.gz lua-d2bda8046c1061c353f9e787e987772b9f96099b.tar.bz2 lua-d2bda8046c1061c353f9e787e987772b9f96099b.zip | |
new implementation for loaders
| -rw-r--r-- | loadlib.c | 77 |
1 files changed, 51 insertions, 26 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: loadlib.c,v 1.14 2004/12/27 15:58:15 roberto Exp roberto $ | 2 | ** $Id: loadlib.c,v 1.15 2004/12/29 18:56:34 roberto Exp roberto $ |
| 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 | * |
| @@ -293,45 +293,59 @@ static int ll_loadlib (lua_State *L) { | |||
| 293 | */ | 293 | */ |
| 294 | 294 | ||
| 295 | 295 | ||
| 296 | static const char *loadLua (lua_State *L, const char *fname, const char *name) { | 296 | static int loader_Lua (lua_State *L) { |
| 297 | const char *name = luaL_checkstring(L, 1); | ||
| 298 | const char *fname = luaL_gsub(L, name, ".", LUA_DIRSEP); | ||
| 297 | const char *path; | 299 | const char *path; |
| 298 | /* try first `LUA_PATH' for compatibility */ | 300 | /* try first `LUA_PATH' for compatibility */ |
| 299 | lua_getglobal(L, "LUA_PATH"); | 301 | lua_getglobal(L, "LUA_PATH"); |
| 300 | path = lua_tostring(L, -1); | 302 | path = lua_tostring(L, -1); |
| 301 | if (!path) { | 303 | if (!path) { |
| 302 | lua_pop(L, 1); | 304 | lua_pop(L, 1); |
| 303 | luaL_getfield(L, LUA_GLOBALSINDEX, "package.path"); | 305 | luaL_getfield(L, LUA_REGISTRYINDEX, "_PACKAGE.path"); |
| 304 | path = lua_tostring(L, -1); | 306 | path = lua_tostring(L, -1); |
| 305 | } | 307 | } |
| 306 | if (path == NULL) | 308 | if (path == NULL) |
| 307 | luaL_error(L, "`package.path' must be a string"); | 309 | luaL_error(L, "`package.path' must be a string"); |
| 308 | fname = luaL_searchpath(L, fname, path); | 310 | fname = luaL_searchpath(L, fname, path); |
| 309 | if (fname == NULL) return path; /* library not found in this path */ | 311 | if (fname == NULL) return 0; /* library not found in this path */ |
| 310 | if (luaL_loadfile(L, fname) != 0) | 312 | if (luaL_loadfile(L, fname) != 0) |
| 311 | luaL_error(L, "error loading package `%s' (%s)", name, lua_tostring(L, -1)); | 313 | luaL_error(L, "error loading package `%s' (%s)", name, lua_tostring(L, -1)); |
| 312 | return NULL; /* library loaded successfully */ | 314 | return 1; /* library loaded successfully */ |
| 313 | } | 315 | } |
| 314 | 316 | ||
| 315 | 317 | ||
| 316 | static const char *loadC (lua_State *L, const char *fname, const char *name) { | 318 | static int loader_C (lua_State *L) { |
| 319 | const char *name = luaL_checkstring(L, 1); | ||
| 320 | const char *fname = luaL_gsub(L, name, ".", LUA_DIRSEP); | ||
| 317 | const char *path; | 321 | const char *path; |
| 318 | const char *funcname; | 322 | const char *funcname; |
| 319 | luaL_getfield(L, LUA_GLOBALSINDEX, "package.cpath"); | 323 | luaL_getfield(L, LUA_REGISTRYINDEX, "_PACKAGE.cpath"); |
| 320 | path = lua_tostring(L, -1); | 324 | path = lua_tostring(L, -1); |
| 321 | if (path == NULL) | 325 | if (path == NULL) |
| 322 | luaL_error(L, "`package.cpath' must be a string"); | 326 | luaL_error(L, "`package.cpath' must be a string"); |
| 323 | fname = luaL_searchpath(L, fname, path); | 327 | fname = luaL_searchpath(L, fname, path); |
| 324 | if (fname == NULL) return path; /* library not found in this path */ | 328 | if (fname == NULL) return 0; /* library not found in this path */ |
| 325 | funcname = luaL_gsub(L, name, ".", LUA_OFSEP); | 329 | funcname = luaL_gsub(L, name, ".", LUA_OFSEP); |
| 326 | funcname = lua_pushfstring(L, "%s%s", POF, funcname); | 330 | funcname = lua_pushfstring(L, "%s%s", POF, funcname); |
| 327 | if (ll_loadfunc(L, fname, funcname) != 1) | 331 | if (ll_loadfunc(L, fname, funcname) != 1) |
| 328 | luaL_error(L, "error loading package `%s' (%s)", name, lua_tostring(L, -2)); | 332 | luaL_error(L, "error loading package `%s' (%s)", name, lua_tostring(L, -2)); |
| 329 | return NULL; /* library loaded successfully */ | 333 | return 1; /* library loaded successfully */ |
| 334 | } | ||
| 335 | |||
| 336 | |||
| 337 | static int loader_preload (lua_State *L) { | ||
| 338 | luaL_getfield(L, LUA_REGISTRYINDEX, "_PACKAGE.preload"); | ||
| 339 | if (!lua_istable(L, -1)) | ||
| 340 | luaL_error(L, "`package.preload' must be a table"); | ||
| 341 | lua_getfield(L, -1, luaL_checkstring(L, 1)); | ||
| 342 | return 1; | ||
| 330 | } | 343 | } |
| 331 | 344 | ||
| 332 | 345 | ||
| 333 | static int ll_require (lua_State *L) { | 346 | static int ll_require (lua_State *L) { |
| 334 | const char *name = luaL_checkstring(L, 1); | 347 | const char *name = luaL_checkstring(L, 1); |
| 348 | int i; | ||
| 335 | lua_settop(L, 1); | 349 | lua_settop(L, 1); |
| 336 | lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); | 350 | lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); |
| 337 | lua_getfield(L, 2, name); | 351 | lua_getfield(L, 2, name); |
| @@ -340,22 +354,18 @@ static int ll_require (lua_State *L) { | |||
| 340 | /* else must load it; first mark it as loaded */ | 354 | /* else must load it; first mark it as loaded */ |
| 341 | lua_pushboolean(L, 1); | 355 | lua_pushboolean(L, 1); |
| 342 | lua_setfield(L, 2, name); /* _LOADED[name] = true */ | 356 | lua_setfield(L, 2, name); /* _LOADED[name] = true */ |
| 343 | /* check whether it is preloaded */ | 357 | /* iterate over available loaders */ |
| 344 | lua_getfield(L, LUA_REGISTRYINDEX, "_PRELOAD"); | 358 | luaL_getfield(L, LUA_REGISTRYINDEX, "_PACKAGE.loaders"); |
| 345 | lua_getfield(L, -1, name); | 359 | if (!lua_istable(L, -1)) |
| 346 | if (lua_isnil(L, -1)) { /* no preload function for that module? */ | 360 | luaL_error(L, "`package.loaders' must be a table"); |
| 347 | const char *fname = luaL_gsub(L, name, ".", LUA_DIRSEP); | 361 | for (i=1;; i++) { |
| 348 | const char *cpath = loadC(L, fname, name); /* try a C module */ | 362 | lua_rawgeti(L, -1, i); /* get a loader */ |
| 349 | if (cpath) { /* not found? */ | 363 | if (lua_isnil(L, -1)) |
| 350 | const char *path = loadLua(L, fname, name); /* try a Lua module */ | 364 | return luaL_error(L, "package `%s' not found", name); |
| 351 | if (path) { /* yet not found? */ | 365 | lua_pushstring(L, name); |
| 352 | lua_pushnil(L); | 366 | lua_call(L, 1, 1); /* call it */ |
| 353 | lua_setfield(L, 2, name); /* unmark _LOADED[name] */ | 367 | if (lua_isnil(L, -1)) lua_pop(L, 1); |
| 354 | return luaL_error(L, "package `%s' not found\n" | 368 | else break; /* module loaded successfully */ |
| 355 | " cpath: %s\n path: %s", | ||
| 356 | name, cpath, path); | ||
| 357 | } | ||
| 358 | } | ||
| 359 | } | 369 | } |
| 360 | lua_pushvalue(L, 1); /* pass name as argument to module */ | 370 | lua_pushvalue(L, 1); /* pass name as argument to module */ |
| 361 | lua_call(L, 1, 1); /* run loaded module */ | 371 | lua_call(L, 1, 1); /* run loaded module */ |
| @@ -430,9 +440,13 @@ static const luaL_reg ll_funcs[] = { | |||
| 430 | }; | 440 | }; |
| 431 | 441 | ||
| 432 | 442 | ||
| 443 | static const lua_CFunction loaders[] = | ||
| 444 | {loader_preload, loader_C, loader_Lua, NULL}; | ||
| 445 | |||
| 433 | 446 | ||
| 434 | LUALIB_API int luaopen_loadlib (lua_State *L) { | 447 | LUALIB_API int luaopen_loadlib (lua_State *L) { |
| 435 | const char *path; | 448 | const char *path; |
| 449 | int i; | ||
| 436 | /* create new type _LOADLIB */ | 450 | /* create new type _LOADLIB */ |
| 437 | luaL_newmetatable(L, "_LOADLIB"); | 451 | luaL_newmetatable(L, "_LOADLIB"); |
| 438 | lua_pushcfunction(L, gctm); | 452 | lua_pushcfunction(L, gctm); |
| @@ -441,6 +455,17 @@ LUALIB_API int luaopen_loadlib (lua_State *L) { | |||
| 441 | lua_newtable(L); | 455 | lua_newtable(L); |
| 442 | lua_pushvalue(L, -1); | 456 | lua_pushvalue(L, -1); |
| 443 | lua_setglobal(L, "package"); | 457 | lua_setglobal(L, "package"); |
| 458 | lua_pushvalue(L, -1); | ||
| 459 | lua_setfield(L, LUA_REGISTRYINDEX, "_PACKAGE"); | ||
| 460 | /* create `loaders' table */ | ||
| 461 | lua_newtable(L); | ||
| 462 | /* fill it with pre-defined loaders */ | ||
| 463 | for (i=0; loaders[i] != NULL; i++) { | ||
| 464 | lua_pushcfunction(L, loaders[i]); | ||
| 465 | lua_rawseti(L, -2, i+1); | ||
| 466 | } | ||
| 467 | /* put it in field `loaders' */ | ||
| 468 | lua_setfield(L, -2, "loaders"); | ||
| 444 | /* set field `path' */ | 469 | /* set field `path' */ |
| 445 | path = getenv(LUA_PATH); | 470 | path = getenv(LUA_PATH); |
| 446 | if (path == NULL) path = LUA_PATH_DEFAULT; | 471 | if (path == NULL) path = LUA_PATH_DEFAULT; |
| @@ -455,7 +480,7 @@ LUALIB_API int luaopen_loadlib (lua_State *L) { | |||
| 455 | lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); | 480 | lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); |
| 456 | lua_setfield(L, -2, "loaded"); | 481 | lua_setfield(L, -2, "loaded"); |
| 457 | /* set field `preload' */ | 482 | /* set field `preload' */ |
| 458 | lua_getfield(L, LUA_REGISTRYINDEX, "_PRELOAD"); | 483 | lua_newtable(L); |
| 459 | lua_setfield(L, -2, "preload"); | 484 | lua_setfield(L, -2, "preload"); |
| 460 | lua_pushvalue(L, LUA_GLOBALSINDEX); | 485 | lua_pushvalue(L, LUA_GLOBALSINDEX); |
| 461 | luaL_openlib(L, NULL, ll_funcs, 0); /* open lib into global table */ | 486 | luaL_openlib(L, NULL, ll_funcs, 0); /* open lib into global table */ |
