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 */ |