diff options
| -rw-r--r-- | loadlib.c | 23 | ||||
| -rw-r--r-- | lundump.c | 4 | ||||
| -rw-r--r-- | manual/manual.of | 38 | ||||
| -rw-r--r-- | testes/attrib.lua | 35 |
4 files changed, 66 insertions, 34 deletions
| @@ -576,9 +576,14 @@ static int searcher_Croot (lua_State *L) { | |||
| 576 | static int searcher_preload (lua_State *L) { | 576 | static int searcher_preload (lua_State *L) { |
| 577 | const char *name = luaL_checkstring(L, 1); | 577 | const char *name = luaL_checkstring(L, 1); |
| 578 | lua_getfield(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); | 578 | lua_getfield(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); |
| 579 | if (lua_getfield(L, -1, name) == LUA_TNIL) /* not found? */ | 579 | if (lua_getfield(L, -1, name) == LUA_TNIL) { /* not found? */ |
| 580 | lua_pushfstring(L, "\n\tno field package.preload['%s']", name); | 580 | lua_pushfstring(L, "\n\tno field package.preload['%s']", name); |
| 581 | return 1; | 581 | return 1; |
| 582 | } | ||
| 583 | else { | ||
| 584 | lua_pushliteral(L, ":preload:"); | ||
| 585 | return 2; | ||
| 586 | } | ||
| 582 | } | 587 | } |
| 583 | 588 | ||
| 584 | 589 | ||
| @@ -620,17 +625,23 @@ static int ll_require (lua_State *L) { | |||
| 620 | /* else must load package */ | 625 | /* else must load package */ |
| 621 | lua_pop(L, 1); /* remove 'getfield' result */ | 626 | lua_pop(L, 1); /* remove 'getfield' result */ |
| 622 | findloader(L, name); | 627 | findloader(L, name); |
| 623 | lua_pushstring(L, name); /* pass name as argument to module loader */ | 628 | lua_rotate(L, -2, 1); /* function <-> loader data */ |
| 624 | lua_insert(L, -2); /* name is 1st argument (before search data) */ | 629 | lua_pushvalue(L, 1); /* name is 1st argument to module loader */ |
| 630 | lua_pushvalue(L, -3); /* loader data is 2nd argument */ | ||
| 631 | /* stack: ...; loader data; loader function; mod. name; loader data */ | ||
| 625 | lua_call(L, 2, 1); /* run loader to load module */ | 632 | lua_call(L, 2, 1); /* run loader to load module */ |
| 633 | /* stack: ...; loader data; result from loader */ | ||
| 626 | if (!lua_isnil(L, -1)) /* non-nil return? */ | 634 | if (!lua_isnil(L, -1)) /* non-nil return? */ |
| 627 | lua_setfield(L, 2, name); /* LOADED[name] = returned value */ | 635 | lua_setfield(L, 2, name); /* LOADED[name] = returned value */ |
| 636 | else | ||
| 637 | lua_pop(L, 1); /* pop nil */ | ||
| 628 | if (lua_getfield(L, 2, name) == LUA_TNIL) { /* module set no value? */ | 638 | if (lua_getfield(L, 2, name) == LUA_TNIL) { /* module set no value? */ |
| 629 | lua_pushboolean(L, 1); /* use true as result */ | 639 | lua_pushboolean(L, 1); /* use true as result */ |
| 630 | lua_pushvalue(L, -1); /* extra copy to be returned */ | 640 | lua_copy(L, -1, -2); /* replace loader result */ |
| 631 | lua_setfield(L, 2, name); /* LOADED[name] = true */ | 641 | lua_setfield(L, 2, name); /* LOADED[name] = true */ |
| 632 | } | 642 | } |
| 633 | return 1; | 643 | lua_rotate(L, -2, 1); /* loader data <-> module result */ |
| 644 | return 2; /* return module result and loader data */ | ||
| 634 | } | 645 | } |
| 635 | 646 | ||
| 636 | /* }====================================================== */ | 647 | /* }====================================================== */ |
| @@ -271,8 +271,8 @@ static void fchecksize (LoadState *S, size_t size, const char *tname) { | |||
| 271 | #define checksize(S,t) fchecksize(S,sizeof(t),#t) | 271 | #define checksize(S,t) fchecksize(S,sizeof(t),#t) |
| 272 | 272 | ||
| 273 | static void checkHeader (LoadState *S) { | 273 | static void checkHeader (LoadState *S) { |
| 274 | /* 1st char already checked */ | 274 | /* skip 1st char (already read and checked) */ |
| 275 | checkliteral(S, LUA_SIGNATURE + 1, "not a binary chunk"); | 275 | checkliteral(S, &LUA_SIGNATURE[1], "not a binary chunk"); |
| 276 | if (LoadInt(S) != LUAC_VERSION) | 276 | if (LoadInt(S) != LUAC_VERSION) |
| 277 | error(S, "version mismatch"); | 277 | error(S, "version mismatch"); |
| 278 | if (LoadByte(S) != LUAC_FORMAT) | 278 | if (LoadByte(S) != LUAC_FORMAT) |
diff --git a/manual/manual.of b/manual/manual.of index fea6922e..24ac45ae 100644 --- a/manual/manual.of +++ b/manual/manual.of | |||
| @@ -6408,11 +6408,15 @@ The function starts by looking into the @Lid{package.loaded} table | |||
| 6408 | to determine whether @id{modname} is already loaded. | 6408 | to determine whether @id{modname} is already loaded. |
| 6409 | If it is, then @id{require} returns the value stored | 6409 | If it is, then @id{require} returns the value stored |
| 6410 | at @T{package.loaded[modname]}. | 6410 | at @T{package.loaded[modname]}. |
| 6411 | (The absence of a second result in this case | ||
| 6412 | signals that this call did not have to load the module.) | ||
| 6411 | Otherwise, it tries to find a @emph{loader} for the module. | 6413 | Otherwise, it tries to find a @emph{loader} for the module. |
| 6412 | 6414 | ||
| 6413 | To find a loader, | 6415 | To find a loader, |
| 6414 | @id{require} is guided by the @Lid{package.searchers} sequence. | 6416 | @id{require} is guided by the table @Lid{package.searchers}. |
| 6415 | By changing this sequence, | 6417 | Each item in this table is a search function, |
| 6418 | that searches for the module in a particular way. | ||
| 6419 | By changing this table, | ||
| 6416 | we can change how @id{require} looks for a module. | 6420 | we can change how @id{require} looks for a module. |
| 6417 | The following explanation is based on the default configuration | 6421 | The following explanation is based on the default configuration |
| 6418 | for @Lid{package.searchers}. | 6422 | for @Lid{package.searchers}. |
| @@ -6429,9 +6433,14 @@ it tries an @emph{all-in-one} loader @seeF{package.searchers}. | |||
| 6429 | 6433 | ||
| 6430 | Once a loader is found, | 6434 | Once a loader is found, |
| 6431 | @id{require} calls the loader with two arguments: | 6435 | @id{require} calls the loader with two arguments: |
| 6432 | @id{modname} and an extra value dependent on how it got the loader. | 6436 | @id{modname} and an extra value, |
| 6433 | (If the loader came from a file, | 6437 | a @emph{loader data}, |
| 6434 | this extra value is the file name.) | 6438 | also returned by the searcher. |
| 6439 | The loader data can be any value useful to the module; | ||
| 6440 | for the default searchers, | ||
| 6441 | it indicates where the loader was found. | ||
| 6442 | (For instance, if the loader came from a file, | ||
| 6443 | this extra value is the file path.) | ||
| 6435 | If the loader returns any non-nil value, | 6444 | If the loader returns any non-nil value, |
| 6436 | @id{require} assigns the returned value to @T{package.loaded[modname]}. | 6445 | @id{require} assigns the returned value to @T{package.loaded[modname]}. |
| 6437 | If the loader does not return a non-nil value and | 6446 | If the loader does not return a non-nil value and |
| @@ -6439,6 +6448,9 @@ has not assigned any value to @T{package.loaded[modname]}, | |||
| 6439 | then @id{require} assigns @Rw{true} to this entry. | 6448 | then @id{require} assigns @Rw{true} to this entry. |
| 6440 | In any case, @id{require} returns the | 6449 | In any case, @id{require} returns the |
| 6441 | final value of @T{package.loaded[modname]}. | 6450 | final value of @T{package.loaded[modname]}. |
| 6451 | Besides that value, @id{require} also returns as a second result | ||
| 6452 | the loader data returned by the searcher, | ||
| 6453 | which indicates how @id{require} found the module. | ||
| 6442 | 6454 | ||
| 6443 | If there is any error loading or running the module, | 6455 | If there is any error loading or running the module, |
| 6444 | or if it cannot find any loader for the module, | 6456 | or if it cannot find any loader for the module, |
| @@ -6558,16 +6570,20 @@ table used by @Lid{require}. | |||
| 6558 | 6570 | ||
| 6559 | @LibEntry{package.searchers| | 6571 | @LibEntry{package.searchers| |
| 6560 | 6572 | ||
| 6561 | A table used by @Lid{require} to control how to load modules. | 6573 | A table used by @Lid{require} to control how to find modules. |
| 6562 | 6574 | ||
| 6563 | Each entry in this table is a @def{searcher function}. | 6575 | Each entry in this table is a @def{searcher function}. |
| 6564 | When looking for a module, | 6576 | When looking for a module, |
| 6565 | @Lid{require} calls each of these searchers in ascending order, | 6577 | @Lid{require} calls each of these searchers in ascending order, |
| 6566 | with the module name (the argument given to @Lid{require}) as its | 6578 | with the module name (the argument given to @Lid{require}) as its |
| 6567 | sole argument. | 6579 | sole argument. |
| 6568 | The function can return another function (the module @def{loader}) | 6580 | If the searcher finds the module, |
| 6569 | plus an extra value that will be passed to that loader, | 6581 | it returns another function, the module @def{loader}, |
| 6570 | or a string explaining why it did not find that module | 6582 | plus an extra value, a @emph{loader data}, |
| 6583 | that will be passed to that loader and | ||
| 6584 | returned as a second result by @Lid{require}. | ||
| 6585 | If it cannot find the module, | ||
| 6586 | it returns a string explaining why | ||
| 6571 | (or @nil if it has nothing to say). | 6587 | (or @nil if it has nothing to say). |
| 6572 | 6588 | ||
| 6573 | Lua initializes this table with four searcher functions. | 6589 | Lua initializes this table with four searcher functions. |
| @@ -6617,9 +6633,9 @@ into one single library, | |||
| 6617 | with each submodule keeping its original open function. | 6633 | with each submodule keeping its original open function. |
| 6618 | 6634 | ||
| 6619 | All searchers except the first one (preload) return as the extra value | 6635 | All searchers except the first one (preload) return as the extra value |
| 6620 | the file name where the module was found, | 6636 | the file path where the module was found, |
| 6621 | as returned by @Lid{package.searchpath}. | 6637 | as returned by @Lid{package.searchpath}. |
| 6622 | The first searcher returns no extra value. | 6638 | The first searcher always returns the string @St{:preload:}. |
| 6623 | 6639 | ||
| 6624 | } | 6640 | } |
| 6625 | 6641 | ||
diff --git a/testes/attrib.lua b/testes/attrib.lua index dcafd634..4adb42e0 100644 --- a/testes/attrib.lua +++ b/testes/attrib.lua | |||
| @@ -122,12 +122,13 @@ local oldpath = package.path | |||
| 122 | 122 | ||
| 123 | package.path = string.gsub("D/?.lua;D/?.lc;D/?;D/??x?;D/L", "D/", DIR) | 123 | package.path = string.gsub("D/?.lua;D/?.lc;D/?;D/??x?;D/L", "D/", DIR) |
| 124 | 124 | ||
| 125 | local try = function (p, n, r) | 125 | local try = function (p, n, r, ext) |
| 126 | NAME = nil | 126 | NAME = nil |
| 127 | local rr = require(p) | 127 | local rr, x = require(p) |
| 128 | assert(NAME == n) | 128 | assert(NAME == n) |
| 129 | assert(REQUIRED == p) | 129 | assert(REQUIRED == p) |
| 130 | assert(rr == r) | 130 | assert(rr == r) |
| 131 | assert(ext == x) | ||
| 131 | end | 132 | end |
| 132 | 133 | ||
| 133 | a = require"names" | 134 | a = require"names" |
| @@ -143,27 +144,27 @@ assert(package.searchpath("C", package.path) == D"C.lua") | |||
| 143 | assert(require"C" == 25) | 144 | assert(require"C" == 25) |
| 144 | assert(require"C" == 25) | 145 | assert(require"C" == 25) |
| 145 | AA = nil | 146 | AA = nil |
| 146 | try('B', 'B.lua', true) | 147 | try('B', 'B.lua', true, "libs/B.lua") |
| 147 | assert(package.loaded.B) | 148 | assert(package.loaded.B) |
| 148 | assert(require"B" == true) | 149 | assert(require"B" == true) |
| 149 | assert(package.loaded.A) | 150 | assert(package.loaded.A) |
| 150 | assert(require"C" == 25) | 151 | assert(require"C" == 25) |
| 151 | package.loaded.A = nil | 152 | package.loaded.A = nil |
| 152 | try('B', nil, true) -- should not reload package | 153 | try('B', nil, true, nil) -- should not reload package |
| 153 | try('A', 'A.lua', true) | 154 | try('A', 'A.lua', true, "libs/A.lua") |
| 154 | package.loaded.A = nil | 155 | package.loaded.A = nil |
| 155 | os.remove(D'A.lua') | 156 | os.remove(D'A.lua') |
| 156 | AA = {} | 157 | AA = {} |
| 157 | try('A', 'A.lc', AA) -- now must find second option | 158 | try('A', 'A.lc', AA, "libs/A.lc") -- now must find second option |
| 158 | assert(package.searchpath("A", package.path) == D"A.lc") | 159 | assert(package.searchpath("A", package.path) == D"A.lc") |
| 159 | assert(require("A") == AA) | 160 | assert(require("A") == AA) |
| 160 | AA = false | 161 | AA = false |
| 161 | try('K', 'L', false) -- default option | 162 | try('K', 'L', false, "libs/L") -- default option |
| 162 | try('K', 'L', false) -- default option (should reload it) | 163 | try('K', 'L', false, "libs/L") -- default option (should reload it) |
| 163 | assert(rawget(_G, "_REQUIREDNAME") == nil) | 164 | assert(rawget(_G, "_REQUIREDNAME") == nil) |
| 164 | 165 | ||
| 165 | AA = "x" | 166 | AA = "x" |
| 166 | try("X", "XXxX", AA) | 167 | try("X", "XXxX", AA, "libs/XXxX") |
| 167 | 168 | ||
| 168 | 169 | ||
| 169 | removefiles(files) | 170 | removefiles(files) |
| @@ -183,14 +184,16 @@ files = { | |||
| 183 | createfiles(files, "_ENV = {}\n", "\nreturn _ENV\n") | 184 | createfiles(files, "_ENV = {}\n", "\nreturn _ENV\n") |
| 184 | AA = 0 | 185 | AA = 0 |
| 185 | 186 | ||
| 186 | local m = assert(require"P1") | 187 | local m, ext = assert(require"P1") |
| 188 | assert(ext == "libs/P1/init.lua") | ||
| 187 | assert(AA == 0 and m.AA == 10) | 189 | assert(AA == 0 and m.AA == 10) |
| 188 | assert(require"P1" == m) | 190 | assert(require"P1" == m) |
| 189 | assert(require"P1" == m) | 191 | assert(require"P1" == m) |
| 190 | 192 | ||
| 191 | assert(package.searchpath("P1.xuxu", package.path) == D"P1/xuxu.lua") | 193 | assert(package.searchpath("P1.xuxu", package.path) == D"P1/xuxu.lua") |
| 192 | m.xuxu = assert(require"P1.xuxu") | 194 | m.xuxu, ext = assert(require"P1.xuxu") |
| 193 | assert(AA == 0 and m.xuxu.AA == 20) | 195 | assert(AA == 0 and m.xuxu.AA == 20) |
| 196 | assert(ext == "libs/P1/xuxu.lua") | ||
| 194 | assert(require"P1.xuxu" == m.xuxu) | 197 | assert(require"P1.xuxu" == m.xuxu) |
| 195 | assert(require"P1.xuxu" == m.xuxu) | 198 | assert(require"P1.xuxu" == m.xuxu) |
| 196 | assert(require"P1" == m and m.AA == 10) | 199 | assert(require"P1" == m and m.AA == 10) |
| @@ -267,15 +270,17 @@ else | |||
| 267 | 270 | ||
| 268 | -- test C modules with prefixes in names | 271 | -- test C modules with prefixes in names |
| 269 | package.cpath = DC"?" | 272 | package.cpath = DC"?" |
| 270 | local lib2 = require"lib2-v2" | 273 | local lib2, ext = require"lib2-v2" |
| 274 | assert(string.find(ext, "libs/lib2-v2", 1, true)) | ||
| 271 | -- check correct access to global environment and correct | 275 | -- check correct access to global environment and correct |
| 272 | -- parameters | 276 | -- parameters |
| 273 | assert(_ENV.x == "lib2-v2" and _ENV.y == DC"lib2-v2") | 277 | assert(_ENV.x == "lib2-v2" and _ENV.y == DC"lib2-v2") |
| 274 | assert(lib2.id("x") == "x") | 278 | assert(lib2.id("x") == "x") |
| 275 | 279 | ||
| 276 | -- test C submodules | 280 | -- test C submodules |
| 277 | local fs = require"lib1.sub" | 281 | local fs, ext = require"lib1.sub" |
| 278 | assert(_ENV.x == "lib1.sub" and _ENV.y == DC"lib1") | 282 | assert(_ENV.x == "lib1.sub" and _ENV.y == DC"lib1") |
| 283 | assert(string.find(ext, "libs/lib1", 1, true)) | ||
| 279 | assert(fs.id(45) == 45) | 284 | assert(fs.id(45) == 45) |
| 280 | end | 285 | end |
| 281 | 286 | ||
| @@ -293,10 +298,10 @@ do | |||
| 293 | return _ENV | 298 | return _ENV |
| 294 | end | 299 | end |
| 295 | 300 | ||
| 296 | local pl = require"pl" | 301 | local pl, ext = require"pl" |
| 297 | assert(require"pl" == pl) | 302 | assert(require"pl" == pl) |
| 298 | assert(pl.xuxu(10) == 30) | 303 | assert(pl.xuxu(10) == 30) |
| 299 | assert(pl[1] == "pl" and pl[2] == nil) | 304 | assert(pl[1] == "pl" and pl[2] == ":preload:" and ext == ":preload:") |
| 300 | 305 | ||
| 301 | package = p | 306 | package = p |
| 302 | assert(type(package.path) == "string") | 307 | assert(type(package.path) == "string") |
