aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2005-08-31 20:17:29 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2005-08-31 20:17:29 -0300
commit351f7dad6b44f05f080e383d81e02b2878048f16 (patch)
tree60b5304c22a560c3c10f30db43af26be597fc2d8
parent3b19af44b05ce5e7f7db3708d052cca25fe6d7d3 (diff)
downloadlua-351f7dad6b44f05f080e383d81e02b2878048f16.tar.gz
lua-351f7dad6b44f05f080e383d81e02b2878048f16.tar.bz2
lua-351f7dad6b44f05f080e383d81e02b2878048f16.zip
default for 'module' is opaque (with option 'seeall')
-rw-r--r--loadlib.c115
1 files changed, 71 insertions, 44 deletions
diff --git a/loadlib.c b/loadlib.c
index d4df06ed..d378fdcc 100644
--- a/loadlib.c
+++ b/loadlib.c
@@ -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
374static void loaderror (lua_State *L) { 374static 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
443static int require_aux (lua_State *L, const char *name) { 443static const int sentinel = 0;
444
445
446static 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 */
479static 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
506static 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
516static 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
506static int ll_module (lua_State *L) { 531static 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
559static 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
570static const luaL_Reg pk_funcs[] = { 596static 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