diff options
| author | Li Jin <dragon-fly@qq.com> | 2020-06-22 16:50:40 +0800 |
|---|---|---|
| committer | Li Jin <dragon-fly@qq.com> | 2020-06-22 16:50:40 +0800 |
| commit | cd2b60b101a398cb9356d746364e70eaed1860f1 (patch) | |
| tree | a1fe71b76faabc4883f16905a94164ce5c23e692 /src/lua/loadlib.c | |
| parent | 88c1052e700f38cf3d8ad82d469da4c487760b7e (diff) | |
| download | yuescript-cd2b60b101a398cb9356d746364e70eaed1860f1.tar.gz yuescript-cd2b60b101a398cb9356d746364e70eaed1860f1.tar.bz2 yuescript-cd2b60b101a398cb9356d746364e70eaed1860f1.zip | |
add support for local variable declared with attribute 'close' and 'const' for Lua 5.4.
Diffstat (limited to '')
| -rw-r--r-- | src/lua/loadlib.c (renamed from src/lua-5.3/loadlib.c) | 261 |
1 files changed, 115 insertions, 146 deletions
diff --git a/src/lua-5.3/loadlib.c b/src/lua/loadlib.c index 45f44d3..c0ec9a1 100644 --- a/src/lua-5.3/loadlib.c +++ b/src/lua/loadlib.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: loadlib.c,v 1.130.1.1 2017/04/19 17:20:42 roberto Exp $ | 2 | ** $Id: loadlib.c $ |
| 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 | ** |
| @@ -56,10 +56,10 @@ | |||
| 56 | 56 | ||
| 57 | 57 | ||
| 58 | /* | 58 | /* |
| 59 | ** unique key for table in the registry that keeps handles | 59 | ** key for table in the registry that keeps handles |
| 60 | ** for all loaded C libraries | 60 | ** for all loaded C libraries |
| 61 | */ | 61 | */ |
| 62 | static const int CLIBS = 0; | 62 | static const char *const CLIBS = "_CLIBS"; |
| 63 | 63 | ||
| 64 | #define LIB_FAIL "open" | 64 | #define LIB_FAIL "open" |
| 65 | 65 | ||
| @@ -68,6 +68,13 @@ static const int CLIBS = 0; | |||
| 68 | 68 | ||
| 69 | 69 | ||
| 70 | /* | 70 | /* |
| 71 | ** Special type equivalent to '(void*)' for functions in gcc | ||
| 72 | ** (to suppress warnings when converting function pointers) | ||
| 73 | */ | ||
| 74 | typedef void (*voidf)(void); | ||
| 75 | |||
| 76 | |||
| 77 | /* | ||
| 71 | ** system-dependent functions | 78 | ** system-dependent functions |
| 72 | */ | 79 | */ |
| 73 | 80 | ||
| @@ -206,7 +213,7 @@ static void *lsys_load (lua_State *L, const char *path, int seeglb) { | |||
| 206 | 213 | ||
| 207 | 214 | ||
| 208 | static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) { | 215 | static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) { |
| 209 | lua_CFunction f = (lua_CFunction)GetProcAddress((HMODULE)lib, sym); | 216 | lua_CFunction f = (lua_CFunction)(voidf)GetProcAddress((HMODULE)lib, sym); |
| 210 | if (f == NULL) pusherror(L); | 217 | if (f == NULL) pusherror(L); |
| 211 | return f; | 218 | return f; |
| 212 | } | 219 | } |
| @@ -269,8 +276,6 @@ static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) { | |||
| 269 | #endif | 276 | #endif |
| 270 | 277 | ||
| 271 | 278 | ||
| 272 | #define AUXMARK "\1" /* auxiliary mark */ | ||
| 273 | |||
| 274 | 279 | ||
| 275 | /* | 280 | /* |
| 276 | ** return registry.LUA_NOENV as a boolean | 281 | ** return registry.LUA_NOENV as a boolean |
| @@ -290,22 +295,33 @@ static int noenv (lua_State *L) { | |||
| 290 | static void setpath (lua_State *L, const char *fieldname, | 295 | static void setpath (lua_State *L, const char *fieldname, |
| 291 | const char *envname, | 296 | const char *envname, |
| 292 | const char *dft) { | 297 | const char *dft) { |
| 298 | const char *dftmark; | ||
| 293 | const char *nver = lua_pushfstring(L, "%s%s", envname, LUA_VERSUFFIX); | 299 | const char *nver = lua_pushfstring(L, "%s%s", envname, LUA_VERSUFFIX); |
| 294 | const char *path = getenv(nver); /* use versioned name */ | 300 | const char *path = getenv(nver); /* try versioned name */ |
| 295 | if (path == NULL) /* no environment variable? */ | 301 | if (path == NULL) /* no versioned environment variable? */ |
| 296 | path = getenv(envname); /* try unversioned name */ | 302 | path = getenv(envname); /* try unversioned name */ |
| 297 | if (path == NULL || noenv(L)) /* no environment variable? */ | 303 | if (path == NULL || noenv(L)) /* no environment variable? */ |
| 298 | lua_pushstring(L, dft); /* use default */ | 304 | lua_pushstring(L, dft); /* use default */ |
| 299 | else { | 305 | else if ((dftmark = strstr(path, LUA_PATH_SEP LUA_PATH_SEP)) == NULL) |
| 300 | /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */ | 306 | lua_pushstring(L, path); /* nothing to change */ |
| 301 | path = luaL_gsub(L, path, LUA_PATH_SEP LUA_PATH_SEP, | 307 | else { /* path contains a ";;": insert default path in its place */ |
| 302 | LUA_PATH_SEP AUXMARK LUA_PATH_SEP); | 308 | size_t len = strlen(path); |
| 303 | luaL_gsub(L, path, AUXMARK, dft); | 309 | luaL_Buffer b; |
| 304 | lua_remove(L, -2); /* remove result from 1st 'gsub' */ | 310 | luaL_buffinit(L, &b); |
| 311 | if (path < dftmark) { /* is there a prefix before ';;'? */ | ||
| 312 | luaL_addlstring(&b, path, dftmark - path); /* add it */ | ||
| 313 | luaL_addchar(&b, *LUA_PATH_SEP); | ||
| 314 | } | ||
| 315 | luaL_addstring(&b, dft); /* add default */ | ||
| 316 | if (dftmark < path + len - 2) { /* is there a suffix after ';;'? */ | ||
| 317 | luaL_addchar(&b, *LUA_PATH_SEP); | ||
| 318 | luaL_addlstring(&b, dftmark + 2, (path + len - 2) - dftmark); | ||
| 319 | } | ||
| 320 | luaL_pushresult(&b); | ||
| 305 | } | 321 | } |
| 306 | setprogdir(L); | 322 | setprogdir(L); |
| 307 | lua_setfield(L, -3, fieldname); /* package[fieldname] = path value */ | 323 | lua_setfield(L, -3, fieldname); /* package[fieldname] = path value */ |
| 308 | lua_pop(L, 1); /* pop versioned variable name */ | 324 | lua_pop(L, 1); /* pop versioned variable name ('nver') */ |
| 309 | } | 325 | } |
| 310 | 326 | ||
| 311 | /* }================================================================== */ | 327 | /* }================================================================== */ |
| @@ -316,7 +332,7 @@ static void setpath (lua_State *L, const char *fieldname, | |||
| 316 | */ | 332 | */ |
| 317 | static void *checkclib (lua_State *L, const char *path) { | 333 | static void *checkclib (lua_State *L, const char *path) { |
| 318 | void *plib; | 334 | void *plib; |
| 319 | lua_rawgetp(L, LUA_REGISTRYINDEX, &CLIBS); | 335 | lua_getfield(L, LUA_REGISTRYINDEX, CLIBS); |
| 320 | lua_getfield(L, -1, path); | 336 | lua_getfield(L, -1, path); |
| 321 | plib = lua_touserdata(L, -1); /* plib = CLIBS[path] */ | 337 | plib = lua_touserdata(L, -1); /* plib = CLIBS[path] */ |
| 322 | lua_pop(L, 2); /* pop CLIBS table and 'plib' */ | 338 | lua_pop(L, 2); /* pop CLIBS table and 'plib' */ |
| @@ -329,7 +345,7 @@ static void *checkclib (lua_State *L, const char *path) { | |||
| 329 | ** registry.CLIBS[#CLIBS + 1] = plib -- also keep a list of all libraries | 345 | ** registry.CLIBS[#CLIBS + 1] = plib -- also keep a list of all libraries |
| 330 | */ | 346 | */ |
| 331 | static void addtoclib (lua_State *L, const char *path, void *plib) { | 347 | static void addtoclib (lua_State *L, const char *path, void *plib) { |
| 332 | lua_rawgetp(L, LUA_REGISTRYINDEX, &CLIBS); | 348 | lua_getfield(L, LUA_REGISTRYINDEX, CLIBS); |
| 333 | lua_pushlightuserdata(L, plib); | 349 | lua_pushlightuserdata(L, plib); |
| 334 | lua_pushvalue(L, -1); | 350 | lua_pushvalue(L, -1); |
| 335 | lua_setfield(L, -3, path); /* CLIBS[path] = plib */ | 351 | lua_setfield(L, -3, path); /* CLIBS[path] = plib */ |
| @@ -397,10 +413,10 @@ static int ll_loadlib (lua_State *L) { | |||
| 397 | if (stat == 0) /* no errors? */ | 413 | if (stat == 0) /* no errors? */ |
| 398 | return 1; /* return the loaded function */ | 414 | return 1; /* return the loaded function */ |
| 399 | else { /* error; error message is on stack top */ | 415 | else { /* error; error message is on stack top */ |
| 400 | lua_pushnil(L); | 416 | luaL_pushfail(L); |
| 401 | lua_insert(L, -2); | 417 | lua_insert(L, -2); |
| 402 | lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init"); | 418 | lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init"); |
| 403 | return 3; /* return nil, error message, and where */ | 419 | return 3; /* return fail, error message, and where */ |
| 404 | } | 420 | } |
| 405 | } | 421 | } |
| 406 | 422 | ||
| @@ -421,14 +437,42 @@ static int readable (const char *filename) { | |||
| 421 | } | 437 | } |
| 422 | 438 | ||
| 423 | 439 | ||
| 424 | static const char *pushnexttemplate (lua_State *L, const char *path) { | 440 | /* |
| 425 | const char *l; | 441 | ** Get the next name in '*path' = 'name1;name2;name3;...', changing |
| 426 | while (*path == *LUA_PATH_SEP) path++; /* skip separators */ | 442 | ** the ending ';' to '\0' to create a zero-terminated string. Return |
| 427 | if (*path == '\0') return NULL; /* no more templates */ | 443 | ** NULL when list ends. |
| 428 | l = strchr(path, *LUA_PATH_SEP); /* find next separator */ | 444 | */ |
| 429 | if (l == NULL) l = path + strlen(path); | 445 | static const char *getnextfilename (char **path, char *end) { |
| 430 | lua_pushlstring(L, path, l - path); /* template */ | 446 | char *sep; |
| 431 | return l; | 447 | char *name = *path; |
| 448 | if (name == end) | ||
| 449 | return NULL; /* no more names */ | ||
| 450 | else if (*name == '\0') { /* from previous iteration? */ | ||
| 451 | *name = *LUA_PATH_SEP; /* restore separator */ | ||
| 452 | name++; /* skip it */ | ||
| 453 | } | ||
| 454 | sep = strchr(name, *LUA_PATH_SEP); /* find next separator */ | ||
| 455 | if (sep == NULL) /* separator not found? */ | ||
| 456 | sep = end; /* name goes until the end */ | ||
| 457 | *sep = '\0'; /* finish file name */ | ||
| 458 | *path = sep; /* will start next search from here */ | ||
| 459 | return name; | ||
| 460 | } | ||
| 461 | |||
| 462 | |||
| 463 | /* | ||
| 464 | ** Given a path such as ";blabla.so;blublu.so", pushes the string | ||
| 465 | ** | ||
| 466 | ** no file 'blabla.so' | ||
| 467 | ** no file 'blublu.so' | ||
| 468 | */ | ||
| 469 | static void pusherrornotfound (lua_State *L, const char *path) { | ||
| 470 | luaL_Buffer b; | ||
| 471 | luaL_buffinit(L, &b); | ||
| 472 | luaL_addstring(&b, "no file '"); | ||
| 473 | luaL_addgsub(&b, path, LUA_PATH_SEP, "'\n\tno file '"); | ||
| 474 | luaL_addstring(&b, "'"); | ||
| 475 | luaL_pushresult(&b); | ||
| 432 | } | 476 | } |
| 433 | 477 | ||
| 434 | 478 | ||
| @@ -436,21 +480,25 @@ static const char *searchpath (lua_State *L, const char *name, | |||
| 436 | const char *path, | 480 | const char *path, |
| 437 | const char *sep, | 481 | const char *sep, |
| 438 | const char *dirsep) { | 482 | const char *dirsep) { |
| 439 | luaL_Buffer msg; /* to build error message */ | 483 | luaL_Buffer buff; |
| 440 | luaL_buffinit(L, &msg); | 484 | char *pathname; /* path with name inserted */ |
| 441 | if (*sep != '\0') /* non-empty separator? */ | 485 | char *endpathname; /* its end */ |
| 486 | const char *filename; | ||
| 487 | /* separator is non-empty and appears in 'name'? */ | ||
| 488 | if (*sep != '\0' && strchr(name, *sep) != NULL) | ||
| 442 | name = luaL_gsub(L, name, sep, dirsep); /* replace it by 'dirsep' */ | 489 | name = luaL_gsub(L, name, sep, dirsep); /* replace it by 'dirsep' */ |
| 443 | while ((path = pushnexttemplate(L, path)) != NULL) { | 490 | luaL_buffinit(L, &buff); |
| 444 | const char *filename = luaL_gsub(L, lua_tostring(L, -1), | 491 | /* add path to the buffer, replacing marks ('?') with the file name */ |
| 445 | LUA_PATH_MARK, name); | 492 | luaL_addgsub(&buff, path, LUA_PATH_MARK, name); |
| 446 | lua_remove(L, -2); /* remove path template */ | 493 | luaL_addchar(&buff, '\0'); |
| 494 | pathname = luaL_buffaddr(&buff); /* writable list of file names */ | ||
| 495 | endpathname = pathname + luaL_bufflen(&buff) - 1; | ||
| 496 | while ((filename = getnextfilename(&pathname, endpathname)) != NULL) { | ||
| 447 | if (readable(filename)) /* does file exist and is readable? */ | 497 | if (readable(filename)) /* does file exist and is readable? */ |
| 448 | return filename; /* return that file name */ | 498 | return lua_pushstring(L, filename); /* save and return name */ |
| 449 | lua_pushfstring(L, "\n\tno file '%s'", filename); | ||
| 450 | lua_remove(L, -2); /* remove file name */ | ||
| 451 | luaL_addvalue(&msg); /* concatenate error msg. entry */ | ||
| 452 | } | 499 | } |
| 453 | luaL_pushresult(&msg); /* create error message */ | 500 | luaL_pushresult(&buff); /* push path to create error message */ |
| 501 | pusherrornotfound(L, lua_tostring(L, -1)); /* create error message */ | ||
| 454 | return NULL; /* not found */ | 502 | return NULL; /* not found */ |
| 455 | } | 503 | } |
| 456 | 504 | ||
| @@ -462,9 +510,9 @@ static int ll_searchpath (lua_State *L) { | |||
| 462 | luaL_optstring(L, 4, LUA_DIRSEP)); | 510 | luaL_optstring(L, 4, LUA_DIRSEP)); |
| 463 | if (f != NULL) return 1; | 511 | if (f != NULL) return 1; |
| 464 | else { /* error message is on top of the stack */ | 512 | else { /* error message is on top of the stack */ |
| 465 | lua_pushnil(L); | 513 | luaL_pushfail(L); |
| 466 | lua_insert(L, -2); | 514 | lua_insert(L, -2); |
| 467 | return 2; /* return nil + error message */ | 515 | return 2; /* return fail + error message */ |
| 468 | } | 516 | } |
| 469 | } | 517 | } |
| 470 | 518 | ||
| @@ -548,7 +596,7 @@ static int searcher_Croot (lua_State *L) { | |||
| 548 | if (stat != ERRFUNC) | 596 | if (stat != ERRFUNC) |
| 549 | return checkload(L, 0, filename); /* real error */ | 597 | return checkload(L, 0, filename); /* real error */ |
| 550 | else { /* open function not found */ | 598 | else { /* open function not found */ |
| 551 | lua_pushfstring(L, "\n\tno module '%s' in file '%s'", name, filename); | 599 | lua_pushfstring(L, "no module '%s' in file '%s'", name, filename); |
| 552 | return 1; | 600 | return 1; |
| 553 | } | 601 | } |
| 554 | } | 602 | } |
| @@ -560,23 +608,30 @@ static int searcher_Croot (lua_State *L) { | |||
| 560 | static int searcher_preload (lua_State *L) { | 608 | static int searcher_preload (lua_State *L) { |
| 561 | const char *name = luaL_checkstring(L, 1); | 609 | const char *name = luaL_checkstring(L, 1); |
| 562 | lua_getfield(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); | 610 | lua_getfield(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); |
| 563 | if (lua_getfield(L, -1, name) == LUA_TNIL) /* not found? */ | 611 | if (lua_getfield(L, -1, name) == LUA_TNIL) { /* not found? */ |
| 564 | lua_pushfstring(L, "\n\tno field package.preload['%s']", name); | 612 | lua_pushfstring(L, "no field package.preload['%s']", name); |
| 565 | return 1; | 613 | return 1; |
| 614 | } | ||
| 615 | else { | ||
| 616 | lua_pushliteral(L, ":preload:"); | ||
| 617 | return 2; | ||
| 618 | } | ||
| 566 | } | 619 | } |
| 567 | 620 | ||
| 568 | 621 | ||
| 569 | static void findloader (lua_State *L, const char *name) { | 622 | static void findloader (lua_State *L, const char *name) { |
| 570 | int i; | 623 | int i; |
| 571 | luaL_Buffer msg; /* to build error message */ | 624 | luaL_Buffer msg; /* to build error message */ |
| 572 | luaL_buffinit(L, &msg); | ||
| 573 | /* push 'package.searchers' to index 3 in the stack */ | 625 | /* push 'package.searchers' to index 3 in the stack */ |
| 574 | if (lua_getfield(L, lua_upvalueindex(1), "searchers") != LUA_TTABLE) | 626 | if (lua_getfield(L, lua_upvalueindex(1), "searchers") != LUA_TTABLE) |
| 575 | luaL_error(L, "'package.searchers' must be a table"); | 627 | luaL_error(L, "'package.searchers' must be a table"); |
| 628 | luaL_buffinit(L, &msg); | ||
| 576 | /* iterate over available searchers to find a loader */ | 629 | /* iterate over available searchers to find a loader */ |
| 577 | for (i = 1; ; i++) { | 630 | for (i = 1; ; i++) { |
| 631 | luaL_addstring(&msg, "\n\t"); /* error-message prefix */ | ||
| 578 | if (lua_rawgeti(L, 3, i) == LUA_TNIL) { /* no more searchers? */ | 632 | if (lua_rawgeti(L, 3, i) == LUA_TNIL) { /* no more searchers? */ |
| 579 | lua_pop(L, 1); /* remove nil */ | 633 | lua_pop(L, 1); /* remove nil */ |
| 634 | luaL_buffsub(&msg, 2); /* remove prefix */ | ||
| 580 | luaL_pushresult(&msg); /* create error message */ | 635 | luaL_pushresult(&msg); /* create error message */ |
| 581 | luaL_error(L, "module '%s' not found:%s", name, lua_tostring(L, -1)); | 636 | luaL_error(L, "module '%s' not found:%s", name, lua_tostring(L, -1)); |
| 582 | } | 637 | } |
| @@ -588,8 +643,10 @@ static void findloader (lua_State *L, const char *name) { | |||
| 588 | lua_pop(L, 1); /* remove extra return */ | 643 | lua_pop(L, 1); /* remove extra return */ |
| 589 | luaL_addvalue(&msg); /* concatenate error message */ | 644 | luaL_addvalue(&msg); /* concatenate error message */ |
| 590 | } | 645 | } |
| 591 | else | 646 | else { /* no error message */ |
| 592 | lua_pop(L, 2); /* remove both returns */ | 647 | lua_pop(L, 2); /* remove both returns */ |
| 648 | luaL_buffsub(&msg, 2); /* remove prefix */ | ||
| 649 | } | ||
| 593 | } | 650 | } |
| 594 | } | 651 | } |
| 595 | 652 | ||
| @@ -604,113 +661,33 @@ static int ll_require (lua_State *L) { | |||
| 604 | /* else must load package */ | 661 | /* else must load package */ |
| 605 | lua_pop(L, 1); /* remove 'getfield' result */ | 662 | lua_pop(L, 1); /* remove 'getfield' result */ |
| 606 | findloader(L, name); | 663 | findloader(L, name); |
| 607 | lua_pushstring(L, name); /* pass name as argument to module loader */ | 664 | lua_rotate(L, -2, 1); /* function <-> loader data */ |
| 608 | lua_insert(L, -2); /* name is 1st argument (before search data) */ | 665 | lua_pushvalue(L, 1); /* name is 1st argument to module loader */ |
| 666 | lua_pushvalue(L, -3); /* loader data is 2nd argument */ | ||
| 667 | /* stack: ...; loader data; loader function; mod. name; loader data */ | ||
| 609 | lua_call(L, 2, 1); /* run loader to load module */ | 668 | lua_call(L, 2, 1); /* run loader to load module */ |
| 669 | /* stack: ...; loader data; result from loader */ | ||
| 610 | if (!lua_isnil(L, -1)) /* non-nil return? */ | 670 | if (!lua_isnil(L, -1)) /* non-nil return? */ |
| 611 | lua_setfield(L, 2, name); /* LOADED[name] = returned value */ | 671 | lua_setfield(L, 2, name); /* LOADED[name] = returned value */ |
| 672 | else | ||
| 673 | lua_pop(L, 1); /* pop nil */ | ||
| 612 | if (lua_getfield(L, 2, name) == LUA_TNIL) { /* module set no value? */ | 674 | if (lua_getfield(L, 2, name) == LUA_TNIL) { /* module set no value? */ |
| 613 | lua_pushboolean(L, 1); /* use true as result */ | 675 | lua_pushboolean(L, 1); /* use true as result */ |
| 614 | lua_pushvalue(L, -1); /* extra copy to be returned */ | 676 | lua_copy(L, -1, -2); /* replace loader result */ |
| 615 | lua_setfield(L, 2, name); /* LOADED[name] = true */ | 677 | lua_setfield(L, 2, name); /* LOADED[name] = true */ |
| 616 | } | 678 | } |
| 617 | return 1; | 679 | lua_rotate(L, -2, 1); /* loader data <-> module result */ |
| 680 | return 2; /* return module result and loader data */ | ||
| 618 | } | 681 | } |
| 619 | 682 | ||
| 620 | /* }====================================================== */ | 683 | /* }====================================================== */ |
| 621 | 684 | ||
| 622 | 685 | ||
| 623 | 686 | ||
| 624 | /* | ||
| 625 | ** {====================================================== | ||
| 626 | ** 'module' function | ||
| 627 | ** ======================================================= | ||
| 628 | */ | ||
| 629 | #if defined(LUA_COMPAT_MODULE) | ||
| 630 | |||
| 631 | /* | ||
| 632 | ** changes the environment variable of calling function | ||
| 633 | */ | ||
| 634 | static void set_env (lua_State *L) { | ||
| 635 | lua_Debug ar; | ||
| 636 | if (lua_getstack(L, 1, &ar) == 0 || | ||
| 637 | lua_getinfo(L, "f", &ar) == 0 || /* get calling function */ | ||
| 638 | lua_iscfunction(L, -1)) | ||
| 639 | luaL_error(L, "'module' not called from a Lua function"); | ||
| 640 | lua_pushvalue(L, -2); /* copy new environment table to top */ | ||
| 641 | lua_setupvalue(L, -2, 1); | ||
| 642 | lua_pop(L, 1); /* remove function */ | ||
| 643 | } | ||
| 644 | |||
| 645 | |||
| 646 | static void dooptions (lua_State *L, int n) { | ||
| 647 | int i; | ||
| 648 | for (i = 2; i <= n; i++) { | ||
| 649 | if (lua_isfunction(L, i)) { /* avoid 'calling' extra info. */ | ||
| 650 | lua_pushvalue(L, i); /* get option (a function) */ | ||
| 651 | lua_pushvalue(L, -2); /* module */ | ||
| 652 | lua_call(L, 1, 0); | ||
| 653 | } | ||
| 654 | } | ||
| 655 | } | ||
| 656 | |||
| 657 | |||
| 658 | static void modinit (lua_State *L, const char *modname) { | ||
| 659 | const char *dot; | ||
| 660 | lua_pushvalue(L, -1); | ||
| 661 | lua_setfield(L, -2, "_M"); /* module._M = module */ | ||
| 662 | lua_pushstring(L, modname); | ||
| 663 | lua_setfield(L, -2, "_NAME"); | ||
| 664 | dot = strrchr(modname, '.'); /* look for last dot in module name */ | ||
| 665 | if (dot == NULL) dot = modname; | ||
| 666 | else dot++; | ||
| 667 | /* set _PACKAGE as package name (full module name minus last part) */ | ||
| 668 | lua_pushlstring(L, modname, dot - modname); | ||
| 669 | lua_setfield(L, -2, "_PACKAGE"); | ||
| 670 | } | ||
| 671 | |||
| 672 | |||
| 673 | static int ll_module (lua_State *L) { | ||
| 674 | const char *modname = luaL_checkstring(L, 1); | ||
| 675 | int lastarg = lua_gettop(L); /* last parameter */ | ||
| 676 | luaL_pushmodule(L, modname, 1); /* get/create module table */ | ||
| 677 | /* check whether table already has a _NAME field */ | ||
| 678 | if (lua_getfield(L, -1, "_NAME") != LUA_TNIL) | ||
| 679 | lua_pop(L, 1); /* table is an initialized module */ | ||
| 680 | else { /* no; initialize it */ | ||
| 681 | lua_pop(L, 1); | ||
| 682 | modinit(L, modname); | ||
| 683 | } | ||
| 684 | lua_pushvalue(L, -1); | ||
| 685 | set_env(L); | ||
| 686 | dooptions(L, lastarg); | ||
| 687 | return 1; | ||
| 688 | } | ||
| 689 | |||
| 690 | |||
| 691 | static int ll_seeall (lua_State *L) { | ||
| 692 | luaL_checktype(L, 1, LUA_TTABLE); | ||
| 693 | if (!lua_getmetatable(L, 1)) { | ||
| 694 | lua_createtable(L, 0, 1); /* create new metatable */ | ||
| 695 | lua_pushvalue(L, -1); | ||
| 696 | lua_setmetatable(L, 1); | ||
| 697 | } | ||
| 698 | lua_pushglobaltable(L); | ||
| 699 | lua_setfield(L, -2, "__index"); /* mt.__index = _G */ | ||
| 700 | return 0; | ||
| 701 | } | ||
| 702 | |||
| 703 | #endif | ||
| 704 | /* }====================================================== */ | ||
| 705 | |||
| 706 | |||
| 707 | 687 | ||
| 708 | static const luaL_Reg pk_funcs[] = { | 688 | static const luaL_Reg pk_funcs[] = { |
| 709 | {"loadlib", ll_loadlib}, | 689 | {"loadlib", ll_loadlib}, |
| 710 | {"searchpath", ll_searchpath}, | 690 | {"searchpath", ll_searchpath}, |
| 711 | #if defined(LUA_COMPAT_MODULE) | ||
| 712 | {"seeall", ll_seeall}, | ||
| 713 | #endif | ||
| 714 | /* placeholders */ | 691 | /* placeholders */ |
| 715 | {"preload", NULL}, | 692 | {"preload", NULL}, |
| 716 | {"cpath", NULL}, | 693 | {"cpath", NULL}, |
| @@ -722,9 +699,6 @@ static const luaL_Reg pk_funcs[] = { | |||
| 722 | 699 | ||
| 723 | 700 | ||
| 724 | static const luaL_Reg ll_funcs[] = { | 701 | static const luaL_Reg ll_funcs[] = { |
| 725 | #if defined(LUA_COMPAT_MODULE) | ||
| 726 | {"module", ll_module}, | ||
| 727 | #endif | ||
| 728 | {"require", ll_require}, | 702 | {"require", ll_require}, |
| 729 | {NULL, NULL} | 703 | {NULL, NULL} |
| 730 | }; | 704 | }; |
| @@ -742,10 +716,6 @@ static void createsearcherstable (lua_State *L) { | |||
| 742 | lua_pushcclosure(L, searchers[i], 1); | 716 | lua_pushcclosure(L, searchers[i], 1); |
| 743 | lua_rawseti(L, -2, i+1); | 717 | lua_rawseti(L, -2, i+1); |
| 744 | } | 718 | } |
| 745 | #if defined(LUA_COMPAT_LOADERS) | ||
| 746 | lua_pushvalue(L, -1); /* make a copy of 'searchers' table */ | ||
| 747 | lua_setfield(L, -3, "loaders"); /* put it in field 'loaders' */ | ||
| 748 | #endif | ||
| 749 | lua_setfield(L, -2, "searchers"); /* put it in field 'searchers' */ | 719 | lua_setfield(L, -2, "searchers"); /* put it in field 'searchers' */ |
| 750 | } | 720 | } |
| 751 | 721 | ||
| @@ -755,12 +725,11 @@ static void createsearcherstable (lua_State *L) { | |||
| 755 | ** setting a finalizer to close all libraries when closing state. | 725 | ** setting a finalizer to close all libraries when closing state. |
| 756 | */ | 726 | */ |
| 757 | static void createclibstable (lua_State *L) { | 727 | static void createclibstable (lua_State *L) { |
| 758 | lua_newtable(L); /* create CLIBS table */ | 728 | luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS); /* create CLIBS table */ |
| 759 | lua_createtable(L, 0, 1); /* create metatable for CLIBS */ | 729 | lua_createtable(L, 0, 1); /* create metatable for CLIBS */ |
| 760 | lua_pushcfunction(L, gctm); | 730 | lua_pushcfunction(L, gctm); |
| 761 | lua_setfield(L, -2, "__gc"); /* set finalizer for CLIBS table */ | 731 | lua_setfield(L, -2, "__gc"); /* set finalizer for CLIBS table */ |
| 762 | lua_setmetatable(L, -2); | 732 | lua_setmetatable(L, -2); |
| 763 | lua_rawsetp(L, LUA_REGISTRYINDEX, &CLIBS); /* set CLIBS table in registry */ | ||
| 764 | } | 733 | } |
| 765 | 734 | ||
| 766 | 735 | ||
