diff options
-rw-r--r-- | lauxlib.c | 49 | ||||
-rw-r--r-- | lbaselib.c | 72 |
2 files changed, 96 insertions, 25 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lauxlib.c,v 1.124 2004/09/03 13:17:14 roberto Exp roberto $ | 2 | ** $Id: lauxlib.c,v 1.125 2004/09/21 16:54:32 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 | */ |
@@ -239,16 +239,22 @@ LUALIB_API void luaL_openlib (lua_State *L, const char *libname, | |||
239 | const luaL_reg *l, int nup) { | 239 | const luaL_reg *l, int nup) { |
240 | if (libname) { | 240 | if (libname) { |
241 | /* check whether lib already exists */ | 241 | /* check whether lib already exists */ |
242 | lua_getglobal(L, libname); | 242 | luaL_getfield(L, LUA_GLOBALSINDEX, libname); |
243 | if (lua_isnil(L, -1)) { /* no? */ | 243 | if (lua_isnil(L, -1)) { /* not found? */ |
244 | lua_pop(L, 1); | 244 | lua_pop(L, 1); /* remove previous result */ |
245 | lua_newtable(L); /* create it */ | 245 | lua_newtable(L); /* create it */ |
246 | if (lua_getmetatable(L, LUA_GLOBALSINDEX)) | 246 | if (lua_getmetatable(L, LUA_GLOBALSINDEX)) |
247 | lua_setmetatable(L, -2); /* share metatable with global table */ | 247 | lua_setmetatable(L, -2); /* share metatable with global table */ |
248 | lua_pushvalue(L, -1); | ||
249 | /* register it with given name */ | 248 | /* register it with given name */ |
250 | lua_setglobal(L, libname); | 249 | lua_pushvalue(L, -1); |
250 | luaL_setfield(L, LUA_GLOBALSINDEX, libname); | ||
251 | } | 251 | } |
252 | else if (!lua_istable(L, -1)) | ||
253 | luaL_error(L, "name conflict for library `%s'", libname); | ||
254 | lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); | ||
255 | lua_pushvalue(L, -2); | ||
256 | lua_setfield(L, -2, libname); /* _LOADED[modname] = new table */ | ||
257 | lua_pop(L, 1); /* remove _LOADED table */ | ||
252 | lua_insert(L, -(nup+1)); /* move library table to below upvalues */ | 258 | lua_insert(L, -(nup+1)); /* move library table to below upvalues */ |
253 | } | 259 | } |
254 | for (; l->name; l++) { | 260 | for (; l->name; l++) { |
@@ -381,37 +387,45 @@ LUALIB_API const char *luaL_searchpath (lua_State *L, const char *name, | |||
381 | } | 387 | } |
382 | fname = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name); | 388 | fname = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name); |
383 | lua_remove(L, -2); /* remove path template */ | 389 | lua_remove(L, -2); /* remove path template */ |
384 | f = fopen(fname, "r"); /* try to read it */ | 390 | f = fopen(fname, "r"); /* try to open it */ |
385 | if (f) { | 391 | if (f) { |
392 | int err; | ||
393 | getc(f); /* try to read file */ | ||
394 | err = ferror(f); | ||
386 | fclose(f); | 395 | fclose(f); |
387 | return fname; | 396 | if (err == 0) /* open and read sucessful? */ |
397 | return fname; /* return that file name */ | ||
388 | } | 398 | } |
389 | lua_pop(L, 1); /* remove file name */ | 399 | lua_pop(L, 1); /* remove file name */ |
390 | } | 400 | } |
391 | } | 401 | } |
392 | 402 | ||
393 | 403 | ||
394 | LUALIB_API const char *luaL_getfield (lua_State *L, const char *fname) { | 404 | LUALIB_API const char *luaL_getfield (lua_State *L, int idx, |
405 | const char *fname) { | ||
395 | const char *e; | 406 | const char *e; |
407 | lua_pushvalue(L, idx); | ||
396 | while ((e = strchr(fname, '.')) != NULL) { | 408 | while ((e = strchr(fname, '.')) != NULL) { |
397 | lua_pushlstring(L, fname, e - fname); | 409 | lua_pushlstring(L, fname, e - fname); |
398 | lua_gettable(L, -2); | 410 | lua_rawget(L, -2); |
399 | lua_remove(L, -2); /* remove previous table */ | 411 | lua_remove(L, -2); /* remove previous table */ |
400 | fname = e + 1; | 412 | fname = e + 1; |
401 | if (!lua_istable(L, -1)) return fname; | 413 | if (!lua_istable(L, -1)) return fname; |
402 | } | 414 | } |
403 | lua_getfield(L, -1, fname); /* get last field */ | 415 | lua_pushstring(L, fname); |
416 | lua_rawget(L, -2); /* get last field */ | ||
404 | lua_remove(L, -2); /* remove previous table */ | 417 | lua_remove(L, -2); /* remove previous table */ |
405 | return NULL; | 418 | return NULL; |
406 | } | 419 | } |
407 | 420 | ||
408 | 421 | ||
409 | LUALIB_API const char *luaL_setfield (lua_State *L, const char *fname) { | 422 | LUALIB_API const char *luaL_setfield (lua_State *L, int idx, |
423 | const char *fname) { | ||
410 | const char *e; | 424 | const char *e; |
411 | lua_insert(L, -2); /* move value to below table */ | 425 | lua_pushvalue(L, idx); |
412 | while ((e = strchr(fname, '.')) != NULL) { | 426 | while ((e = strchr(fname, '.')) != NULL) { |
413 | lua_pushlstring(L, fname, e - fname); | 427 | lua_pushlstring(L, fname, e - fname); |
414 | lua_gettable(L, -2); | 428 | lua_rawget(L, -2); |
415 | if (lua_isnil(L, -1)) { /* no such field? */ | 429 | if (lua_isnil(L, -1)) { /* no such field? */ |
416 | lua_pop(L, 1); /* remove this nil */ | 430 | lua_pop(L, 1); /* remove this nil */ |
417 | lua_newtable(L); /* create a new table for field */ | 431 | lua_newtable(L); /* create a new table for field */ |
@@ -426,9 +440,10 @@ LUALIB_API const char *luaL_setfield (lua_State *L, const char *fname) { | |||
426 | return fname; | 440 | return fname; |
427 | } | 441 | } |
428 | } | 442 | } |
429 | lua_insert(L, -2); /* move table to below value */ | 443 | lua_pushstring(L, fname); |
430 | lua_setfield(L, -2, fname); /* set last field */ | 444 | lua_pushvalue(L, -3); /* move value to the top */ |
431 | lua_remove(L, -2); /* remove table */ | 445 | lua_rawset(L, -3); /* set last field */ |
446 | lua_pop(L, 2); /* remove value and table */ | ||
432 | return NULL; | 447 | return NULL; |
433 | } | 448 | } |
434 | 449 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lbaselib.c,v 1.157 2004/09/03 13:16:48 roberto Exp roberto $ | 2 | ** $Id: lbaselib.c,v 1.158 2004/09/15 20:39:42 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 | */ |
@@ -463,24 +463,79 @@ static const char *getpath (lua_State *L) { | |||
463 | static int luaB_require (lua_State *L) { | 463 | static int luaB_require (lua_State *L) { |
464 | const char *name = luaL_checkstring(L, 1); | 464 | const char *name = luaL_checkstring(L, 1); |
465 | const char *fname; | 465 | const char *fname; |
466 | lua_getfield(L, lua_upvalueindex(1), name); | 466 | lua_settop(L, 1); |
467 | lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); | ||
468 | lua_getfield(L, 2, name); | ||
467 | if (lua_toboolean(L, -1)) /* is it there? */ | 469 | if (lua_toboolean(L, -1)) /* is it there? */ |
468 | return 1; /* package is already loaded; return its result */ | 470 | return 1; /* package is already loaded; return its result */ |
469 | /* else must load it; first mark it as loaded */ | 471 | /* else must load it; first mark it as loaded */ |
470 | lua_pushboolean(L, 1); | 472 | lua_pushboolean(L, 1); |
471 | lua_setfield(L, lua_upvalueindex(1), name); /* _LOADED[name] = true */ | 473 | lua_setfield(L, 2, name); /* _LOADED[name] = true */ |
472 | fname = luaL_searchpath(L, name, getpath(L)); | 474 | fname = luaL_gsub(L, name, ".", LUA_DIRSEP); |
475 | fname = luaL_searchpath(L, fname, getpath(L)); | ||
473 | if (fname == NULL || luaL_loadfile(L, fname) != 0) | 476 | if (fname == NULL || luaL_loadfile(L, fname) != 0) |
474 | return luaL_error(L, "error loading package `%s' (%s)", name, | 477 | return luaL_error(L, "error loading package `%s' (%s)", name, |
475 | lua_tostring(L, -1)); | 478 | lua_tostring(L, -1)); |
476 | lua_pushvalue(L, 1); /* pass name as argument to module */ | 479 | lua_pushvalue(L, 1); /* pass name as argument to module */ |
477 | lua_call(L, 1, 1); /* run loaded module */ | 480 | lua_call(L, 1, 1); /* run loaded module */ |
478 | if (!lua_isnil(L, -1)) /* nil return? */ | 481 | if (!lua_isnil(L, -1)) /* nil return? */ |
479 | lua_setfield(L, lua_upvalueindex(1), name); | 482 | lua_setfield(L, 2, name); |
480 | lua_getfield(L, lua_upvalueindex(1), name); /* return _LOADED[name] */ | 483 | lua_getfield(L, 2, name); /* return _LOADED[name] */ |
481 | return 1; | 484 | return 1; |
482 | } | 485 | } |
483 | 486 | ||
487 | |||
488 | static void setfenv (lua_State *L) { | ||
489 | lua_Debug ar; | ||
490 | lua_getstack(L, 1, &ar); | ||
491 | lua_getinfo(L, "f", &ar); | ||
492 | lua_pushvalue(L, -2); | ||
493 | lua_setfenv(L, -2); | ||
494 | } | ||
495 | |||
496 | |||
497 | static int luaB_module (lua_State *L) { | ||
498 | const char *modname = luaL_checkstring(L, 1); | ||
499 | const char *dot; | ||
500 | lua_settop(L, 1); | ||
501 | lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); | ||
502 | /* try to find given table */ | ||
503 | luaL_getfield(L, LUA_GLOBALSINDEX, modname); | ||
504 | if (lua_isnil(L, -1)) { /* not found? */ | ||
505 | lua_pop(L, 1); /* remove previous result */ | ||
506 | lua_newtable(L); /* create it */ | ||
507 | /* register it with given name */ | ||
508 | lua_pushvalue(L, -1); | ||
509 | luaL_setfield(L, LUA_GLOBALSINDEX, modname); | ||
510 | } | ||
511 | else if (!lua_istable(L, -1)) | ||
512 | return luaL_error(L, "name conflict for module `%s'", modname); | ||
513 | /* check whether table already has a _NAME field */ | ||
514 | lua_getfield(L, -1, "_NAME"); | ||
515 | if (!lua_isnil(L, -1)) /* is table an initialized module? */ | ||
516 | lua_pop(L, 1); | ||
517 | else { /* no; initialize it */ | ||
518 | lua_pop(L, 1); | ||
519 | lua_newtable(L); /* create new metatable */ | ||
520 | lua_pushvalue(L, LUA_GLOBALSINDEX); | ||
521 | lua_setfield(L, -2, "__index"); /* mt.__index = _G */ | ||
522 | lua_setmetatable(L, -2); | ||
523 | lua_pushstring(L, modname); | ||
524 | lua_setfield(L, -2, "_NAME"); | ||
525 | dot = strrchr(modname, '.'); /* look for last dot in module name */ | ||
526 | if (dot == NULL) dot = modname; | ||
527 | else dot++; | ||
528 | /* set _PACK as package name (full module name minus last part) */ | ||
529 | lua_pushlstring(L, modname, dot - modname); | ||
530 | lua_setfield(L, -2, "_PACK"); | ||
531 | } | ||
532 | lua_pushvalue(L, -1); | ||
533 | lua_setfield(L, 2, modname); /* _LOADED[modname] = new table */ | ||
534 | setfenv(L); | ||
535 | return 0; | ||
536 | } | ||
537 | |||
538 | |||
484 | /* }====================================================== */ | 539 | /* }====================================================== */ |
485 | 540 | ||
486 | 541 | ||
@@ -509,6 +564,8 @@ static const luaL_reg base_funcs[] = { | |||
509 | {"dofile", luaB_dofile}, | 564 | {"dofile", luaB_dofile}, |
510 | {"loadstring", luaB_loadstring}, | 565 | {"loadstring", luaB_loadstring}, |
511 | {"load", luaB_load}, | 566 | {"load", luaB_load}, |
567 | {"require", luaB_require}, | ||
568 | {"module", luaB_module}, | ||
512 | {NULL, NULL} | 569 | {NULL, NULL} |
513 | }; | 570 | }; |
514 | 571 | ||
@@ -676,8 +733,7 @@ static void base_open (lua_State *L) { | |||
676 | lua_newtable(L); | 733 | lua_newtable(L); |
677 | lua_pushvalue(L, -1); | 734 | lua_pushvalue(L, -1); |
678 | lua_setglobal(L, "_LOADED"); | 735 | lua_setglobal(L, "_LOADED"); |
679 | lua_pushcclosure(L, luaB_require, 1); | 736 | lua_setfield(L, LUA_REGISTRYINDEX, "_LOADED"); |
680 | lua_setfield(L, LUA_GLOBALSINDEX, "require"); | ||
681 | /* set global _G */ | 737 | /* set global _G */ |
682 | lua_pushvalue(L, LUA_GLOBALSINDEX); | 738 | lua_pushvalue(L, LUA_GLOBALSINDEX); |
683 | lua_setfield(L, LUA_GLOBALSINDEX, "_G"); | 739 | lua_setfield(L, LUA_GLOBALSINDEX, "_G"); |