diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2005-08-31 20:17:29 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2005-08-31 20:17:29 -0300 |
commit | 351f7dad6b44f05f080e383d81e02b2878048f16 (patch) | |
tree | 60b5304c22a560c3c10f30db43af26be597fc2d8 | |
parent | 3b19af44b05ce5e7f7db3708d052cca25fe6d7d3 (diff) | |
download | lua-351f7dad6b44f05f080e383d81e02b2878048f16.tar.gz lua-351f7dad6b44f05f080e383d81e02b2878048f16.tar.bz2 lua-351f7dad6b44f05f080e383d81e02b2878048f16.zip |
default for 'module' is opaque (with option 'seeall')
-rw-r--r-- | loadlib.c | 115 |
1 files changed, 71 insertions, 44 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: loadlib.c,v 1.41 2005/08/26 17:32:05 roberto Exp roberto $ | 2 | ** $Id: loadlib.c,v 1.42 2005/08/26 17:36:32 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 | ** |
@@ -372,7 +372,7 @@ static const char *findfile (lua_State *L, const char *name, | |||
372 | 372 | ||
373 | 373 | ||
374 | static void loaderror (lua_State *L) { | 374 | static void loaderror (lua_State *L) { |
375 | luaL_error(L, "error loading package " LUA_QS " (%s)", | 375 | luaL_error(L, "error loading module " LUA_QS " (%s)", |
376 | lua_tostring(L, 1), lua_tostring(L, -1)); | 376 | lua_tostring(L, 1), lua_tostring(L, -1)); |
377 | } | 377 | } |
378 | 378 | ||
@@ -440,13 +440,20 @@ static int loader_preload (lua_State *L) { | |||
440 | } | 440 | } |
441 | 441 | ||
442 | 442 | ||
443 | static int require_aux (lua_State *L, const char *name) { | 443 | static const int sentinel = 0; |
444 | |||
445 | |||
446 | static int ll_require (lua_State *L) { | ||
447 | const char *name = luaL_checkstring(L, 1); | ||
444 | int i; | 448 | int i; |
445 | int loadedtable = lua_gettop(L) + 1; | 449 | lua_settop(L, 1); /* _LOADED table will be at index 2 */ |
446 | lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); | 450 | lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); |
447 | lua_getfield(L, loadedtable, name); | 451 | lua_getfield(L, 2, name); |
448 | if (lua_toboolean(L, -1)) /* is it there? */ | 452 | if (lua_toboolean(L, -1)) { /* is it there? */ |
453 | if (lua_touserdata(L, -1) == &sentinel) /* check loops */ | ||
454 | luaL_error(L, "loop or previous error loading module " LUA_QS, name); | ||
449 | return 1; /* package is already loaded */ | 455 | return 1; /* package is already loaded */ |
456 | } | ||
450 | /* else must load it; iterate over available loaders */ | 457 | /* else must load it; iterate over available loaders */ |
451 | lua_getfield(L, LUA_ENVIRONINDEX, "loaders"); | 458 | lua_getfield(L, LUA_ENVIRONINDEX, "loaders"); |
452 | if (!lua_istable(L, -1)) | 459 | if (!lua_istable(L, -1)) |
@@ -454,32 +461,24 @@ static int require_aux (lua_State *L, const char *name) { | |||
454 | for (i=1; ; i++) { | 461 | for (i=1; ; i++) { |
455 | lua_rawgeti(L, -1, i); /* get a loader */ | 462 | lua_rawgeti(L, -1, i); /* get a loader */ |
456 | if (lua_isnil(L, -1)) | 463 | if (lua_isnil(L, -1)) |
457 | return 0; /* package not found */ | 464 | luaL_error(L, "module " LUA_QS " not found", name); |
458 | lua_pushstring(L, name); | 465 | lua_pushstring(L, name); |
459 | lua_call(L, 1, 1); /* call it */ | 466 | lua_call(L, 1, 1); /* call it */ |
460 | if (lua_isnil(L, -1)) lua_pop(L, 1); /* did not found module */ | 467 | if (lua_isnil(L, -1)) lua_pop(L, 1); /* did not found module */ |
461 | else break; /* module loaded successfully */ | 468 | else break; /* module loaded successfully */ |
462 | } | 469 | } |
463 | lua_pushboolean(L, 1); | 470 | lua_pushlightuserdata(L, (void *)&sentinel); |
464 | lua_setfield(L, loadedtable, name); /* _LOADED[name] = true */ | 471 | lua_setfield(L, 2, name); /* _LOADED[name] = sentinel */ |
465 | lua_pushstring(L, name); /* pass name as argument to module */ | 472 | lua_pushstring(L, name); /* pass name as argument to module */ |
466 | if (lua_pcall(L, 1, 1, 0) != 0) { /* run loaded module */ | 473 | lua_call(L, 1, 1); /* run loaded module */ |
467 | lua_pushnil(L); /* in case of errors... */ | ||
468 | lua_setfield(L, loadedtable, name); /* ...clear _LOADED[name] */ | ||
469 | luaL_error(L, "error loading package " LUA_QS " (%s)", | ||
470 | name, lua_tostring(L, -1)); /* propagate error */ | ||
471 | } | ||
472 | if (!lua_isnil(L, -1)) /* non-nil return? */ | 474 | if (!lua_isnil(L, -1)) /* non-nil return? */ |
473 | lua_setfield(L, loadedtable, name); /* _LOADED[name] = returned value */ | 475 | lua_setfield(L, 2, name); /* _LOADED[name] = returned value */ |
474 | lua_getfield(L, loadedtable, name); /* return _LOADED[name] */ | 476 | lua_getfield(L, 2, name); |
475 | return 1; | 477 | if (lua_touserdata(L, -1) == &sentinel) { /* module did not set a value? */ |
476 | } | 478 | lua_pushboolean(L, 1); /* use true as result */ |
477 | 479 | lua_pushvalue(L, -1); /* extra copy to be returned */ | |
478 | 480 | lua_setfield(L, 2, name); /* _LOADED[name] = true */ | |
479 | static int ll_require (lua_State *L) { | 481 | } |
480 | const char *name = luaL_checkstring(L, 1); | ||
481 | if (!require_aux(L, name)) /* error? */ | ||
482 | luaL_error(L, "package " LUA_QS " not found", name); | ||
483 | return 1; | 482 | return 1; |
484 | } | 483 | } |
485 | 484 | ||
@@ -500,22 +499,47 @@ static void setfenv (lua_State *L) { | |||
500 | lua_getinfo(L, "f", &ar); | 499 | lua_getinfo(L, "f", &ar); |
501 | lua_pushvalue(L, -2); | 500 | lua_pushvalue(L, -2); |
502 | lua_setfenv(L, -2); | 501 | lua_setfenv(L, -2); |
502 | lua_pop(L, 1); | ||
503 | } | ||
504 | |||
505 | |||
506 | static void dooptions (lua_State *L, int n) { | ||
507 | int i; | ||
508 | for (i = 2; i <= n; i++) { | ||
509 | lua_pushvalue(L, i); /* get option (a function) */ | ||
510 | lua_pushvalue(L, -2); /* module */ | ||
511 | lua_call(L, 1, 0); | ||
512 | } | ||
513 | } | ||
514 | |||
515 | |||
516 | static void modinit (lua_State *L, const char *modname) { | ||
517 | const char *dot; | ||
518 | lua_pushvalue(L, -1); | ||
519 | lua_setfield(L, -2, "_M"); /* module._M = module */ | ||
520 | lua_pushstring(L, modname); | ||
521 | lua_setfield(L, -2, "_NAME"); | ||
522 | dot = strrchr(modname, '.'); /* look for last dot in module name */ | ||
523 | if (dot == NULL) dot = modname; | ||
524 | else dot++; | ||
525 | /* set _PACKAGE as package name (full module name minus last part) */ | ||
526 | lua_pushlstring(L, modname, dot - modname); | ||
527 | lua_setfield(L, -2, "_PACKAGE"); | ||
503 | } | 528 | } |
504 | 529 | ||
505 | 530 | ||
506 | static int ll_module (lua_State *L) { | 531 | static int ll_module (lua_State *L) { |
507 | const char *modname = luaL_checkstring(L, 1); | 532 | const char *modname = luaL_checkstring(L, 1); |
508 | const char *dot; | 533 | int loaded = lua_gettop(L) + 1; /* index of _LOADED table */ |
509 | lua_settop(L, 1); | ||
510 | lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); | 534 | lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); |
511 | lua_getfield(L, 2, modname); /* get _LOADED[modname] */ | 535 | lua_getfield(L, loaded, modname); /* get _LOADED[modname] */ |
512 | if (!lua_istable(L, -1)) { /* not found? */ | 536 | if (!lua_istable(L, -1)) { /* not found? */ |
513 | lua_pop(L, 1); /* remove previous result */ | 537 | lua_pop(L, 1); /* remove previous result */ |
514 | /* try global variable (and create one if it does not exist) */ | 538 | /* try global variable (and create one if it does not exist) */ |
515 | if (luaL_findtable(L, LUA_GLOBALSINDEX, modname) != NULL) | 539 | if (luaL_findtable(L, LUA_GLOBALSINDEX, modname) != NULL) |
516 | return luaL_error(L, "name conflict for module " LUA_QS, modname); | 540 | return luaL_error(L, "name conflict for module " LUA_QS, modname); |
517 | lua_pushvalue(L, -1); | 541 | lua_pushvalue(L, -1); |
518 | lua_setfield(L, 2, modname); /* _LOADED[modname] = new table */ | 542 | lua_setfield(L, loaded, modname); /* _LOADED[modname] = new table */ |
519 | } | 543 | } |
520 | /* check whether table already has a _NAME field */ | 544 | /* check whether table already has a _NAME field */ |
521 | lua_getfield(L, -1, "_NAME"); | 545 | lua_getfield(L, -1, "_NAME"); |
@@ -523,26 +547,28 @@ static int ll_module (lua_State *L) { | |||
523 | lua_pop(L, 1); | 547 | lua_pop(L, 1); |
524 | else { /* no; initialize it */ | 548 | else { /* no; initialize it */ |
525 | lua_pop(L, 1); | 549 | lua_pop(L, 1); |
526 | /* create new metatable */ | 550 | modinit(L, modname); |
527 | lua_newtable(L); | ||
528 | lua_pushvalue(L, LUA_GLOBALSINDEX); | ||
529 | lua_setfield(L, -2, "__index"); /* mt.__index = _G */ | ||
530 | lua_setmetatable(L, -2); | ||
531 | lua_pushvalue(L, -1); | ||
532 | lua_setfield(L, -2, "_M"); /* module._M = module */ | ||
533 | lua_pushstring(L, modname); | ||
534 | lua_setfield(L, -2, "_NAME"); | ||
535 | dot = strrchr(modname, '.'); /* look for last dot in module name */ | ||
536 | if (dot == NULL) dot = modname; | ||
537 | else dot++; | ||
538 | /* set _PACKAGE as package name (full module name minus last part) */ | ||
539 | lua_pushlstring(L, modname, dot - modname); | ||
540 | lua_setfield(L, -2, "_PACKAGE"); | ||
541 | } | 551 | } |
552 | lua_pushvalue(L, -1); | ||
542 | setfenv(L); | 553 | setfenv(L); |
554 | dooptions(L, loaded - 1); | ||
543 | return 0; | 555 | return 0; |
544 | } | 556 | } |
545 | 557 | ||
558 | |||
559 | static int ll_seeall (lua_State *L) { | ||
560 | luaL_checktype(L, 1, LUA_TTABLE); | ||
561 | if (!lua_getmetatable(L, 1)) { | ||
562 | lua_newtable(L); /* create new metatable */ | ||
563 | lua_pushvalue(L, -1); | ||
564 | lua_setmetatable(L, 1); | ||
565 | } | ||
566 | lua_pushvalue(L, LUA_GLOBALSINDEX); | ||
567 | lua_setfield(L, -2, "__index"); /* mt.__index = _G */ | ||
568 | return 0; | ||
569 | } | ||
570 | |||
571 | |||
546 | /* }====================================================== */ | 572 | /* }====================================================== */ |
547 | 573 | ||
548 | 574 | ||
@@ -569,6 +595,7 @@ static void setpath (lua_State *L, const char *fieldname, const char *envname, | |||
569 | 595 | ||
570 | static const luaL_Reg pk_funcs[] = { | 596 | static const luaL_Reg pk_funcs[] = { |
571 | {"loadlib", ll_loadlib}, | 597 | {"loadlib", ll_loadlib}, |
598 | {"seeall", ll_seeall}, | ||
572 | {NULL, NULL} | 599 | {NULL, NULL} |
573 | }; | 600 | }; |
574 | 601 | ||