Merge lp:~widelands-dev/widelands/bug-1543001-eris into lp:widelands
- bug-1543001-eris
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Merged at revision: | 7954 | ||||
Proposed branch: | lp:~widelands-dev/widelands/bug-1543001-eris | ||||
Merge into: | lp:widelands | ||||
Diff against target: |
20384 lines (+8124/-4571) 75 files modified
src/logic/cmd_luacoroutine.cc (+4/-2) src/logic/map_objects/tribes/soldier.cc (+2/-2) src/logic/map_objects/tribes/worker.cc (+1/-1) src/map_io/map_scripting_packet.cc (+1/-1) src/scripting/logic.cc (+3/-3) src/scripting/lua.h (+2/-0) src/scripting/lua_coroutine.cc (+2/-2) src/scripting/lua_globals.cc (+4/-7) src/scripting/lua_map.cc (+19/-19) src/scripting/lua_ui.cc (+4/-4) src/third_party/CMakeLists.txt (+4/-0) src/third_party/eris/README.eris (+2/-2) src/third_party/eris/eris.c (+337/-209) src/third_party/eris/eris.h (+7/-2) src/third_party/eris/lapi.c (+277/-291) src/third_party/eris/lapi.h (+3/-3) src/third_party/eris/lauxlib.c (+167/-154) src/third_party/eris/lauxlib.h (+69/-25) src/third_party/eris/lbaselib.c (+194/-119) src/third_party/eris/lbitlib.c (+49/-31) src/third_party/eris/lcode.c (+151/-78) src/third_party/eris/lcode.h (+8/-4) src/third_party/eris/lcorolib.c (+23/-10) src/third_party/eris/lctype.c (+4/-1) src/third_party/eris/lctype.h (+1/-1) src/third_party/eris/ldblib.c (+126/-87) src/third_party/eris/ldebug.c (+109/-59) src/third_party/eris/ldebug.h (+10/-4) src/third_party/eris/ldo.c (+116/-80) src/third_party/eris/ldo.h (+2/-2) src/third_party/eris/ldump.c (+192/-151) src/third_party/eris/lfunc.c (+61/-71) src/third_party/eris/lfunc.h (+26/-5) src/third_party/eris/lgc.c (+425/-486) src/third_party/eris/lgc.h (+43/-62) src/third_party/eris/linit.c (+22/-21) src/third_party/eris/liolib.c (+195/-104) src/third_party/eris/llex.c (+178/-106) src/third_party/eris/llex.h (+12/-4) src/third_party/eris/llimits.h (+80/-147) src/third_party/eris/lmathlib.c (+236/-111) src/third_party/eris/lmem.c (+13/-13) src/third_party/eris/lmem.h (+21/-9) src/third_party/eris/loadlib.c (+163/-102) src/third_party/eris/lobject.c (+245/-62) src/third_party/eris/lobject.h (+147/-214) src/third_party/eris/lopcodes.c (+21/-4) src/third_party/eris/lopcodes.h (+23/-16) src/third_party/eris/loslib.c (+69/-36) src/third_party/eris/lparser.c (+95/-86) src/third_party/eris/lparser.h (+14/-13) src/third_party/eris/lprefix.h (+45/-0) src/third_party/eris/lstate.c (+60/-37) src/third_party/eris/lstate.h (+73/-78) src/third_party/eris/lstring.c (+68/-71) src/third_party/eris/lstring.h (+9/-9) src/third_party/eris/lstrlib.c (+526/-115) src/third_party/eris/ltable.c (+202/-140) src/third_party/eris/ltable.h (+14/-6) src/third_party/eris/ltablib.c (+155/-81) src/third_party/eris/ltm.c (+76/-10) src/third_party/eris/ltm.h (+23/-5) src/third_party/eris/lua.c (+611/-0) src/third_party/eris/lua.h (+105/-64) src/third_party/eris/luac.c (+449/-0) src/third_party/eris/luaconf.h (+496/-312) src/third_party/eris/lualib.h (+4/-2) src/third_party/eris/lundump.c (+251/-232) src/third_party/eris/lundump.h (+17/-12) src/third_party/eris/lutf8lib.c (+255/-0) src/third_party/eris/lvm.c (+659/-344) src/third_party/eris/lvm.h (+32/-18) src/third_party/eris/lzio.c (+6/-4) src/third_party/eris/lzio.h (+6/-4) test/maps/lua_testsuite.wmf/scripting/string_bformat.lua (+0/-1) |
||||
To merge this branch: | bzr merge lp:~widelands-dev/widelands/bug-1543001-eris | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Miroslav Remák | code | Approve | |
kaputtnik (community) | testing | Approve | |
GunChleoc | Needs Resubmitting | ||
Review via email: mp+291294@code.launchpad.net |
Commit message
Updated Eris to version 1.1.0.
Description of the change
I just dumped the files and updated the readme. As long as we don't change to a newer Lua version, savegames should be compatible. I did a quick test with my long Trident of Fire savegame, and it loaded with no issues.
Miroslav Remák (miroslavr256) wrote : | # |
GunChleoc (gunchleoc) wrote : | # |
The highest Lua version available on my system is 5.2. Ubuntu introduced Lua with version 15.04, but I usually only use long term releases, which means that I will have to wait until 16.04 comes out in order to switch to Lua 5.3.
SirVer (sirver) wrote : | # |
I think Eris is lua 5.3 - Eris bundles all of lua with it since it needs the private headers for serialization. So by updating Eris, we switch to lua 5.3.
This is from my memory. I cannot check right now, but it should be documented on the GitHub project page or the commit history of Eris.
> Am 08.04.2016 um 07:54 schrieb GunChleoc <email address hidden>:
>
> The highest Lua version available on my system is 5.2. Ubuntu introduced Lua with version 15.04, but I usually only use long term releases, which means that I will have to wait until 16.04 comes out in order to switch to Lua 5.3.
> --
> https:/
> Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/bug-1543001-eris into lp:widelands.
>
> _______
> Mailing list: https:/
> Post to : <email address hidden>
> Unsubscribe : https:/
> More help : https:/
Miroslav Remák (miroslavr256) wrote : | # |
SirVer is correct. Here's an explanation:
https:/
You don't need to have Lua installed on your system at all.
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 984. State: failed. Details: https:/
Appveyor build 817. State: success. Details: https:/
Klaus Halfmann (klaus-halfmann) wrote : | # |
On OSX (with macports) I have 'lua @5.3.1_2 (lang)'. hope this helps
GunChleoc (gunchleoc) wrote : | # |
OK, I'll try the Lua 5.3 version then to see if it will run on my system :)
GunChleoc (gunchleoc) wrote : | # |
Seems to be working - I could even load some savegames, so I haven't upgraded any packet numbers.
Miroslav Remák (miroslavr256) wrote : | # |
Tutorials and campaigns seem to be crashing:
Error in Lua Coroutine
[/home/
Send message to all players and pause gameFatal exception: [/home/
Game: Writing Preload Data ... The program has unexpectedly finished.
/home/miroslavr
Miroslav Remák (miroslavr256) wrote : | # |
Besides the obvious error in Lua coroutine, there seems to be another issue with the message that is supposed to show up, which ultimately leads to a crash. This message (in CmdLuaCoroutine
Miroslav Remák (miroslavr256) wrote : | # |
Regarding the "number has no integer representation" error: Since Lua 5.3 added integer support, luaL_checkinteger does not seem to accept floating-point numbers anymore. We need to make sure to pass integers from Lua where required.
These changes seem to do the trick:
=== modified file 'data/scripting
--- data/scripting/
+++ data/scripting/
@@ -99,8 +99,8 @@
wl.
for idx,p in ipairs(points) do
- mv.viewpoint_x = p.x
- mv.viewpoint_y = p.y
+ mv.viewpoint_x = math.floor(p.x)
+ mv.viewpoint_y = math.floor(p.y)
sleep(dt)
end
@@ -196,8 +196,8 @@
wl.
for idx,p in ipairs(points) do
- mv.mouse_position_x = p.x
- mv.mouse_position_y = p.y
+ mv.mouse_position_x = math.floor(p.x)
+ mv.mouse_position_y = math.floor(p.y)
sleep(dt)
end
GunChleoc (gunchleoc) wrote : | # |
I can't reproduce the crash. Where were you exactly when it happened? What is your screen resolution?
Miroslav Remák (miroslavr256) wrote : | # |
My in-game resolution is 1024x768, 60 fps. It happens anytime the view or mouse pointer moves automatically (see diff). For example, the first tutorial mission errors just after activating build spaces.
Can you try running 'wl.ui.
Miroslav Remák (miroslavr256) wrote : | # |
Also, what does 'print(_VERSION)' output on your end? It should be 'Lua+Eris 5.3'.
kaputtnik (franku) wrote : | # |
I just get a crash in Economy tutorial. The crash happens after clicking the "OK" button of first text screen:
Error in Lua Coroutine
[/home/
Send message to all players and pause gameFatal exception: [/home/
Game: Writing Preload Data ... Speicherzugriff
The same crash happens when playing the warefare tutorial after the Citadel has been build.
kaputtnik (franku) wrote : | # |
Another crash with a savegame saved with current trunk:
Reading Scripting Data ... PANIC: unprotected error in call to Lua API (incompatible integer type)
I attach the savegame to the bug.
Miroslav Remák (miroslavr256) wrote : | # |
@kaputtnik: You won't be able to load older savegames because the save format of Eris is not compatible. I'm not sure if we can catch the error and display a message box instead of aborting, though.
kaputtnik (franku) wrote : | # |
I just mentioned this because GunChleoc says:
> I could even load some savegames, so I haven't upgraded any packet numbers.
If the packet numbers are upgraded a message box is displayed automatically when trying to load an incompatible save game :-)
Miroslav Remák (miroslavr256) wrote : | # |
Right, I see. We should definitely up the MapScriptingPacket version.
SirVer (sirver) wrote : | # |
Theoretically, this should invalidate all savegames. Also non scenario ones. Since every game as a win condition (be it an empty one), all savegames contain Lua serialized coroutines. If they load it is by luck, there is no guarantee in Eris for compatibility. We should up the version for all savegames imho.
GunChleoc (gunchleoc) wrote : | # |
> Also, what does 'print(_VERSION)' output on your end? It should be 'Lua+Eris
> 5.3'.
That was it. I had to delete the build directory to get the correct version. I can reproduce the crashes now.
I'll put this merge request on hold now, since there is obviously work to be done.
GunChleoc (gunchleoc) wrote : | # |
This should be ready now :)
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 989. State: failed. Details: https:/
Appveyor build 822. State: success. Details: https:/
Miroslav Remák (miroslavr256) wrote : | # |
Can you also fix the issue I mentioned here: https:/
This is what lead to the crash in the first place...
GunChleoc (gunchleoc) wrote : | # |
Sorry, I overlooked this one. Which message do you mean by "this message"? I played the first tutorial through without any crashes.
> Besides the obvious error in Lua coroutine, there seems to be another issue
> with the message that is supposed to show up, which ultimately leads to a
> crash. This message (in CmdLuaCoroutine
> title parameters swapped.
Miroslav Remák (miroslavr256) wrote : | # |
When a coroutine errors, an in-game message is supposed to be sent to all of the players:
http://
bunnybot (widelandsofficial) wrote : | # |
Bunnybot encountered an error while working on this merge proposal:
Running 'bzr pull --overwrite' failed. Output:
ssh: Could not resolve hostname bazaar.
ConnectionReset reading response for 'BzrDir.open_2.1', retrying
ssh: Could not resolve hostname bazaar.
bzr: ERROR: Connection closed: Unexpected end of message. Please check connectivity and permissions, and report a bug if problems persist.
Using saved parent location: bzr+ssh:
kaputtnik (franku) wrote : | # |
I have played some Tutorials and Campaigns, played a new game and also played with the editor.
Works fine i think :-)
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 993. State: passed. Details: https:/
Appveyor build 826. State: success. Details: https:/
GunChleoc (gunchleoc) wrote : | # |
This should now be fixed as well. It has been broken for ages.
> When a coroutine errors, an in-game message is supposed to be sent to all of
> the players:
> http://
> dev/widelands/bug-1543001-eris/view/
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 994. State: passed. Details: https:/
Appveyor build 827. State: failed. Details: https:/
Miroslav Remák (miroslavr256) wrote : | # |
LGTM.
GunChleoc (gunchleoc) wrote : | # |
Thanks!
@bunnybot merge
Preview Diff
1 | === modified file 'src/logic/cmd_luacoroutine.cc' |
2 | --- src/logic/cmd_luacoroutine.cc 2016-02-15 23:26:42 +0000 |
3 | +++ src/logic/cmd_luacoroutine.cc 2016-04-10 16:54:20 +0000 |
4 | @@ -19,6 +19,8 @@ |
5 | |
6 | #include "logic/cmd_luacoroutine.h" |
7 | |
8 | +#include <boost/format.hpp> |
9 | + |
10 | #include "base/log.h" |
11 | #include "base/macros.h" |
12 | #include "io/fileread.h" |
13 | @@ -52,10 +54,10 @@ |
14 | *new Widelands::Message |
15 | (Message::Type::kGameLogic, |
16 | game.get_gametime(), |
17 | + "Coroutine", |
18 | "images/ui_basic/menu_help.png", |
19 | - "Coroutine", |
20 | "Lua Coroutine Failed", |
21 | - e.what()); |
22 | + (boost::format("<rt><p font-size=12>%s</p></rt>") % e.what()).str()); |
23 | game.player(i).add_message(game, msg, true); |
24 | } |
25 | game.game_controller()->set_desired_speed(0); |
26 | |
27 | === modified file 'src/logic/map_objects/tribes/soldier.cc' |
28 | --- src/logic/map_objects/tribes/soldier.cc 2016-04-03 16:18:24 +0000 |
29 | +++ src/logic/map_objects/tribes/soldier.cc 2016-04-10 16:54:20 +0000 |
30 | @@ -1483,7 +1483,7 @@ |
31 | descr().descname(), |
32 | "images/ui_basic/menu_help.png", |
33 | _("Logic error"), |
34 | - messagetext, |
35 | + (boost::format("<rt><p font-size=12>%s</p></rt>") % messagetext).str(), |
36 | get_position(), |
37 | serial_)); |
38 | opponent.owner().add_message |
39 | @@ -1494,7 +1494,7 @@ |
40 | descr().descname(), |
41 | "images/ui_basic/menu_help.png", |
42 | _("Logic error"), |
43 | - messagetext, |
44 | + (boost::format("<rt><p font-size=12>%s</p></rt>") % messagetext).str(), |
45 | opponent.get_position(), |
46 | serial_)); |
47 | game.game_controller()->set_desired_speed(0); |
48 | |
49 | === modified file 'src/logic/map_objects/tribes/worker.cc' |
50 | --- src/logic/map_objects/tribes/worker.cc 2016-03-08 15:21:41 +0000 |
51 | +++ src/logic/map_objects/tribes/worker.cc 2016-04-10 16:54:20 +0000 |
52 | @@ -1844,7 +1844,7 @@ |
53 | _("Worker"), |
54 | "images/ui_basic/menu_help.png", |
55 | _("Worker got lost!"), |
56 | - message, |
57 | + (boost::format("<rt><p font-size=12>%s</p></rt>") % message).str(), |
58 | get_position()), |
59 | serial_); |
60 | set_location(nullptr); |
61 | |
62 | === modified file 'src/map_io/map_scripting_packet.cc' |
63 | --- src/map_io/map_scripting_packet.cc 2015-11-28 22:29:26 +0000 |
64 | +++ src/map_io/map_scripting_packet.cc 2016-04-10 16:54:20 +0000 |
65 | @@ -37,7 +37,7 @@ |
66 | namespace Widelands { |
67 | |
68 | namespace { |
69 | -constexpr uint32_t kCurrentPacketVersion = 2; |
70 | +constexpr uint32_t kCurrentPacketVersion = 3; |
71 | } // namespace |
72 | /* |
73 | * ======================================================================== |
74 | |
75 | === modified file 'src/scripting/logic.cc' |
76 | --- src/scripting/logic.cc 2016-02-12 16:58:41 +0000 |
77 | +++ src/scripting/logic.cc 2016-04-10 16:54:20 +0000 |
78 | @@ -99,14 +99,14 @@ |
79 | switch (lua_gettop(L)) { /* check number of arguments */ |
80 | case 0: |
81 | { /* no arguments */ |
82 | - lua_pushnumber(L, r); /* Number between 0 and 1 */ |
83 | + lua_pushdouble(L, r); /* Number between 0 and 1 */ |
84 | break; |
85 | } |
86 | case 1: |
87 | { /* only upper limit */ |
88 | int32_t u = luaL_checkint32(L, 1); |
89 | luaL_argcheck(L, 1 <= u, 1, "interval is empty"); |
90 | - lua_pushnumber(L, floor(r * u) + 1); /* int between 1 and `u' */ |
91 | + lua_pushuint32(L, floor(r * u) + 1); /* int between 1 and `u' */ |
92 | break; |
93 | } |
94 | case 2: |
95 | @@ -115,7 +115,7 @@ |
96 | int32_t u = luaL_checkint32(L, 2); |
97 | luaL_argcheck(L, l <= u, 2, "interval is empty"); |
98 | /* int between `l' and `u' */ |
99 | - lua_pushnumber(L, floor(r * (u - l + 1)) + l); |
100 | + lua_pushint32(L, floor(r * (u - l + 1)) + l); |
101 | break; |
102 | } |
103 | default: return luaL_error(L, "wrong number of arguments"); |
104 | |
105 | === modified file 'src/scripting/lua.h' |
106 | --- src/scripting/lua.h 2016-02-12 16:58:41 +0000 |
107 | +++ src/scripting/lua.h 2016-04-10 16:54:20 +0000 |
108 | @@ -26,9 +26,11 @@ |
109 | |
110 | #define luaL_checkint32(L, n) static_cast<int32_t>(luaL_checkinteger(L, (n))) |
111 | #define luaL_checkuint32(L, n) static_cast<uint32_t>(luaL_checkinteger(L, (n))) |
112 | +#define luaL_checkdouble(L, n) static_cast<double>(luaL_checknumber(L, (n))) |
113 | |
114 | #define lua_pushint32(L, n) (lua_pushinteger(L, static_cast<int32_t>(n))) |
115 | #define lua_pushuint32(L, n) (lua_pushinteger(L, static_cast<uint32_t>(n))) |
116 | +#define lua_pushdouble(L, n) (lua_pushnumber(L, static_cast<double>(n))) |
117 | |
118 | void lua_pushstring (lua_State * L, const std::string & s); |
119 | |
120 | |
121 | === modified file 'src/scripting/lua_coroutine.cc' |
122 | --- src/scripting/lua_coroutine.cc 2016-03-21 08:06:33 +0000 |
123 | +++ src/scripting/lua_coroutine.cc 2016-04-10 16:54:20 +0000 |
124 | @@ -124,7 +124,7 @@ |
125 | if (!nreturn_values_) { |
126 | return 0; |
127 | } |
128 | - if (!lua_isnumber(lua_state_, -1)) { |
129 | + if (!lua_isinteger(lua_state_, -1)) { |
130 | throw LuaError("pop_uint32(), but no integer on the stack."); |
131 | } |
132 | const uint32_t return_value = luaL_checkuint32(lua_state_, -1); |
133 | @@ -144,7 +144,7 @@ |
134 | return result; |
135 | } |
136 | |
137 | -constexpr uint8_t kCoroutineDataPacketVersion = 3; |
138 | +constexpr uint8_t kCoroutineDataPacketVersion = 4; |
139 | void LuaCoroutine::write(FileWrite& fw) { |
140 | fw.unsigned_8(kCoroutineDataPacketVersion); |
141 | |
142 | |
143 | === modified file 'src/scripting/lua_globals.cc' |
144 | --- src/scripting/lua_globals.cc 2016-04-03 12:35:43 +0000 |
145 | +++ src/scripting/lua_globals.cc 2016-04-10 16:54:20 +0000 |
146 | @@ -80,13 +80,10 @@ |
147 | break; |
148 | |
149 | case LUA_TNUMBER: |
150 | - { |
151 | - const int d = lua_tointeger(L, i); |
152 | - if (d == 0 && !lua_isnumber(L, 1)) { |
153 | - fmt % d; |
154 | - } else { |
155 | - fmt % luaL_checknumber(L, i); |
156 | - } |
157 | + if (lua_isinteger(L, i)) { |
158 | + fmt % luaL_checkint32(L, i); |
159 | + } else { |
160 | + fmt % luaL_checknumber(L, i); |
161 | } |
162 | break; |
163 | |
164 | |
165 | === modified file 'src/scripting/lua_map.cc' |
166 | --- src/scripting/lua_map.cc 2016-04-05 07:51:48 +0000 |
167 | +++ src/scripting/lua_map.cc 2016-04-10 16:54:20 +0000 |
168 | @@ -98,11 +98,11 @@ |
169 | lua_newtable(L); |
170 | int counter = 0; |
171 | for (const std::vector<std::string>& foodlist : table) { |
172 | - lua_pushnumber(L, ++counter); |
173 | + lua_pushuint32(L, ++counter); |
174 | lua_newtable(L); |
175 | int counter2 = 0; |
176 | for (const std::string& foodname : foodlist) { |
177 | - lua_pushnumber(L, ++counter2); |
178 | + lua_pushuint32(L, ++counter2); |
179 | lua_pushstring(L, foodname); |
180 | lua_settable(L, -3); |
181 | } |
182 | @@ -1506,8 +1506,8 @@ |
183 | /* RST |
184 | .. attribute:: returns the terrain affinity values for this immovable |
185 | |
186 | - (RO) a table containing numbers labeled as pickiness, preferred_fertility, |
187 | - preferred_humidity, and preferred_temperature, |
188 | + (RO) a table containing numbers labeled as pickiness (double), preferred_fertility (double), |
189 | + preferred_humidity (double), and preferred_temperature (uint), |
190 | or nil if the immovable has no terrain affinity. |
191 | */ |
192 | int LuaImmovableDescription::get_terrain_affinity(lua_State * L) { |
193 | @@ -1515,16 +1515,16 @@ |
194 | const TerrainAffinity& affinity = get()->terrain_affinity(); |
195 | lua_newtable(L); |
196 | lua_pushstring(L, "pickiness"); |
197 | - lua_pushnumber(L, affinity.pickiness()); |
198 | + lua_pushdouble(L, affinity.pickiness()); |
199 | lua_settable(L, -3); |
200 | lua_pushstring(L, "preferred_fertility"); |
201 | - lua_pushnumber(L, affinity.preferred_fertility()); |
202 | + lua_pushdouble(L, affinity.preferred_fertility()); |
203 | lua_settable(L, -3); |
204 | lua_pushstring(L, "preferred_humidity"); |
205 | - lua_pushnumber(L, affinity.preferred_humidity()); |
206 | + lua_pushdouble(L, affinity.preferred_humidity()); |
207 | lua_settable(L, -3); |
208 | lua_pushstring(L, "preferred_temperature"); |
209 | - lua_pushnumber(L, affinity.preferred_temperature()); |
210 | + lua_pushuint32(L, affinity.preferred_temperature()); |
211 | lua_settable(L, -3); |
212 | } else { |
213 | lua_pushnil(L); |
214 | @@ -1620,7 +1620,7 @@ |
215 | } |
216 | if (get()->has_terrain_affinity()) { |
217 | const TerrainDescription* terrain = (*get_user_class<LuaMaps::LuaTerrainDescription>(L, 2))->get(); |
218 | - lua_pushnumber(L, Widelands::probability_to_grow(get()->terrain_affinity(), *terrain)); |
219 | + lua_pushdouble(L, Widelands::probability_to_grow(get()->terrain_affinity(), *terrain)); |
220 | } else { |
221 | lua_pushnil(L); |
222 | } |
223 | @@ -2062,11 +2062,11 @@ |
224 | lua_newtable(L); |
225 | int counter = 0; |
226 | for (const auto& group: program.consumed_wares()) { |
227 | - lua_pushnumber(L, ++counter); |
228 | + lua_pushuint32(L, ++counter); |
229 | lua_newtable(L); |
230 | for (const DescriptionIndex& ware_index : group.first) { |
231 | lua_pushstring(L, get_egbase(L).tribes().get_ware_descr(ware_index)->name()); |
232 | - lua_pushnumber(L, group.second); |
233 | + lua_pushuint32(L, group.second); |
234 | lua_settable(L, -3); |
235 | } |
236 | lua_settable(L, -3); |
237 | @@ -2380,7 +2380,7 @@ |
238 | lua_newtable(L); |
239 | int counter = 0; |
240 | for (const std::string& weaponname : get()->get_weapons_attack()) { |
241 | - lua_pushnumber(L, ++counter); |
242 | + lua_pushuint32(L, ++counter); |
243 | lua_pushstring(L, weaponname); |
244 | lua_settable(L, -3); |
245 | } |
246 | @@ -2396,7 +2396,7 @@ |
247 | lua_newtable(L); |
248 | int counter = 0; |
249 | for (const std::string& weaponname : get()->get_weapons_defense()) { |
250 | - lua_pushnumber(L, ++counter); |
251 | + lua_pushuint32(L, ++counter); |
252 | lua_pushstring(L, weaponname); |
253 | lua_settable(L, -3); |
254 | } |
255 | @@ -2412,7 +2412,7 @@ |
256 | lua_newtable(L); |
257 | int counter = 0; |
258 | for (const std::string& weaponname : get()->get_weapons_evade()) { |
259 | - lua_pushnumber(L, ++counter); |
260 | + lua_pushuint32(L, ++counter); |
261 | lua_pushstring(L, weaponname); |
262 | lua_settable(L, -3); |
263 | } |
264 | @@ -2428,7 +2428,7 @@ |
265 | lua_newtable(L); |
266 | int counter = 0; |
267 | for (const std::string& weaponname : get()->get_weapons_health()) { |
268 | - lua_pushnumber(L, ++counter); |
269 | + lua_pushuint32(L, ++counter); |
270 | lua_pushstring(L, weaponname); |
271 | lua_settable(L, -3); |
272 | } |
273 | @@ -3128,7 +3128,7 @@ |
274 | */ |
275 | |
276 | int LuaTerrainDescription::get_fertility(lua_State * L) { |
277 | - lua_pushnumber(L, get()->fertility()); |
278 | + lua_pushdouble(L, get()->fertility()); |
279 | return 1; |
280 | } |
281 | |
282 | @@ -3139,7 +3139,7 @@ |
283 | */ |
284 | |
285 | int LuaTerrainDescription::get_humidity(lua_State * L) { |
286 | - lua_pushnumber(L, get()->humidity()); |
287 | + lua_pushdouble(L, get()->humidity()); |
288 | return 1; |
289 | } |
290 | |
291 | @@ -3157,11 +3157,11 @@ |
292 | /* RST |
293 | .. attribute:: temperature |
294 | |
295 | - (RO) the :class:`double` temperature value for this terrain |
296 | + (RO) the :class:`uint` temperature value for this terrain |
297 | */ |
298 | |
299 | int LuaTerrainDescription::get_temperature(lua_State * L) { |
300 | - lua_pushnumber(L, get()->temperature()); |
301 | + lua_pushuint32(L, get()->temperature()); |
302 | return 1; |
303 | } |
304 | |
305 | |
306 | === modified file 'src/scripting/lua_ui.cc' |
307 | --- src/scripting/lua_ui.cc 2016-02-14 14:09:29 +0000 |
308 | +++ src/scripting/lua_ui.cc 2016-04-10 16:54:20 +0000 |
309 | @@ -206,7 +206,7 @@ |
310 | int LuaPanel::set_mouse_position_x(lua_State * L) { |
311 | assert(panel_); |
312 | Point p = panel_->get_mouse_position(); |
313 | - p.x = luaL_checkint32(L, -1); |
314 | + p.x = floor(luaL_checkdouble(L, -1)); |
315 | panel_->set_mouse_pos(p); |
316 | return 1; |
317 | } |
318 | @@ -218,7 +218,7 @@ |
319 | int LuaPanel::set_mouse_position_y(lua_State * L) { |
320 | assert(panel_); |
321 | Point p = panel_->get_mouse_position(); |
322 | - p.y = luaL_checkint32(L, -1); |
323 | + p.y = floor(luaL_checkdouble(L, -1)); |
324 | panel_->set_mouse_pos(p); |
325 | return 1; |
326 | } |
327 | @@ -554,7 +554,7 @@ |
328 | |
329 | MapView * mv = get(); |
330 | Point p = mv->get_viewpoint(); |
331 | - p.x = luaL_checkuint32(L, -1); |
332 | + p.x = floor(luaL_checkdouble(L, -1)); |
333 | mv->set_viewpoint(p, true); |
334 | return 0; |
335 | } |
336 | @@ -571,7 +571,7 @@ |
337 | |
338 | MapView * mv = get(); |
339 | Point p = mv->get_viewpoint(); |
340 | - p.y = luaL_checkuint32(L, -1); |
341 | + p.y = floor(luaL_checkdouble(L, -1)); |
342 | mv->set_viewpoint(p, true); |
343 | return 0; |
344 | } |
345 | |
346 | === modified file 'src/third_party/CMakeLists.txt' |
347 | --- src/third_party/CMakeLists.txt 2015-07-05 11:05:23 +0000 |
348 | +++ src/third_party/CMakeLists.txt 2016-04-10 16:54:20 +0000 |
349 | @@ -51,6 +51,7 @@ |
350 | eris/loslib.c |
351 | eris/lparser.c |
352 | eris/lparser.h |
353 | + eris/lprefix.h |
354 | eris/lstate.c |
355 | eris/lstate.h |
356 | eris/lstring.c |
357 | @@ -63,10 +64,13 @@ |
358 | eris/ltm.h |
359 | eris/lua.h |
360 | eris/lua.hpp |
361 | + eris/lua.c |
362 | + eris/luac.c |
363 | eris/luaconf.h |
364 | eris/lualib.h |
365 | eris/lundump.c |
366 | eris/lundump.h |
367 | + eris/lutf8lib.c |
368 | eris/lvm.c |
369 | eris/lvm.h |
370 | eris/lzio.c |
371 | |
372 | === modified file 'src/third_party/eris/README.eris' |
373 | --- src/third_party/eris/README.eris 2014-02-22 14:47:28 +0000 |
374 | +++ src/third_party/eris/README.eris 2016-04-10 16:54:20 +0000 |
375 | @@ -1,11 +1,11 @@ |
376 | This directory contains a verbatim copy of Eris by Florian Nücke. |
377 | |
378 | URL: https://github.com/fnuecke/eris |
379 | -VERSION: 2e39ecc7dcb73120dde775929227fa661fbc6bc0 |
380 | +VERSION: 1.1.0 for Lua 5.3 |
381 | |
382 | We use this for heavy persistence and it also brings with it the Lua version |
383 | that we use in Widelands. The Widelands Team wishes to expresses total and |
384 | complete gratitude to the authors of Eris for making it available under the MIT |
385 | -License. |
386 | +License. |
387 | |
388 | -- SirVer, in behalf of the Widelands Team |
389 | |
390 | === modified file 'src/third_party/eris/eris.c' |
391 | --- src/third_party/eris/eris.c 2014-07-25 11:14:03 +0000 |
392 | +++ src/third_party/eris/eris.c 2016-04-10 16:54:20 +0000 |
393 | @@ -1,6 +1,6 @@ |
394 | /* |
395 | -Eris - Heavy-duty persistence for Lua 5.2.2 - Based on Pluto |
396 | -Copyright (c) 2013 by Florian Nuecke. |
397 | +Eris - Heavy-duty persistence for Lua 5.3.0 - Based on Pluto |
398 | +Copyright (c) 2013-2015 by Florian Nuecke. |
399 | |
400 | Permission is hereby granted, free of charge, to any person obtaining a copy |
401 | of this software and associated documentation files (the "Software"), to deal |
402 | @@ -113,14 +113,13 @@ |
403 | /* lfunc.h */ |
404 | #define eris_newproto luaF_newproto |
405 | #define eris_newLclosure luaF_newLclosure |
406 | -#define eris_newupval luaF_newupval |
407 | +#define eris_initupvals luaF_initupvals |
408 | #define eris_findupval luaF_findupval |
409 | -/* lgc.h */ |
410 | -#define eris_barrierproto luaC_barrierproto |
411 | /* lmem.h */ |
412 | #define eris_reallocvector luaM_reallocvector |
413 | /* lobject.h */ |
414 | -#define eris_ttypenv ttypenv |
415 | +#define eris_ttnov ttnov |
416 | +#define eris_clLvalue clLvalue |
417 | #define eris_setnilvalue setnilvalue |
418 | #define eris_setclLvalue setclLvalue |
419 | #define eris_setobj setobj |
420 | @@ -176,15 +175,60 @@ |
421 | |
422 | /* |
423 | ** ============================================================================ |
424 | +** Language strings for errors. |
425 | +** ============================================================================ |
426 | +*/ |
427 | + |
428 | +#define ERIS_ERR_CFUNC "attempt to persist a light C function (%p)" |
429 | +#define ERIS_ERR_COMPLEXITY "object too complex" |
430 | +#define ERIS_ERR_HOOK "cannot persist yielded hooks" |
431 | +#define ERIS_ERR_METATABLE "bad metatable, not nil or table" |
432 | +#define ERIS_ERR_NOFUNC "attempt to persist unknown function type" |
433 | +#define ERIS_ERR_READ "could not read data" |
434 | +#define ERIS_ERR_SPER_FUNC "%s did not return a function" |
435 | +#define ERIS_ERR_SPER_LOAD "bad unpersist function (%s expected, returned %s)" |
436 | +#define ERIS_ERR_SPER_PROT "attempt to persist forbidden table" |
437 | +#define ERIS_ERR_SPER_TYPE "%d not nil, boolean, or function" |
438 | +#define ERIS_ERR_SPER_UFUNC "invalid restore function" |
439 | +#define ERIS_ERR_SPER_UPERM "bad permanent value (%s expected, got %s)" |
440 | +#define ERIS_ERR_SPER_UPERMNIL "bad permanent value (no value)" |
441 | +#define ERIS_ERR_STACKBOUNDS "stack index out of bounds" |
442 | +#define ERIS_ERR_TABLE "bad table value, got a nil value" |
443 | +#define ERIS_ERR_THREAD "cannot persist currently running thread" |
444 | +#define ERIS_ERR_THREADCI "invalid callinfo" |
445 | +#define ERIS_ERR_THREADCTX "bad C continuation function" |
446 | +#define ERIS_ERR_THREADERRF "invalid errfunc" |
447 | +#define ERIS_ERR_THREADPC "saved program counter out of bounds" |
448 | +#define ERIS_ERR_TRUNC_INT "int value would get truncated" |
449 | +#define ERIS_ERR_TRUNC_SIZE "size_t value would get truncated" |
450 | +#define ERIS_ERR_TYPE_FLOAT "unsupported lua_Number type" |
451 | +#define ERIS_ERR_TYPE_INT "unsupported int type" |
452 | +#define ERIS_ERR_TYPE_SIZE "unsupported size_t type" |
453 | +#define ERIS_ERR_TYPEP "trying to persist unknown type %d" |
454 | +#define ERIS_ERR_TYPEU "trying to unpersist unknown type %d" |
455 | +#define ERIS_ERR_UCFUNC "bad C closure (C function expected, got %s)" |
456 | +#define ERIS_ERR_UCFUNCNULL "bad C closure (C function expected, got null)" |
457 | +#define ERIS_ERR_USERDATA "attempt to literally persist userdata" |
458 | +#define ERIS_ERR_WRITE "could not write data" |
459 | +#define ERIS_ERR_REF "invalid reference #%d. this usually means a special "\ |
460 | + "persistence callback of a table referenced said table "\ |
461 | + "(directly or indirectly via an upvalue)." |
462 | + |
463 | +/* |
464 | +** ============================================================================ |
465 | ** Constants, settings, types and forward declarations. |
466 | ** ============================================================================ |
467 | */ |
468 | |
469 | +/* The upvalue tag type was removed in Lua 5.3, but we still need it for |
470 | + * special handling of upvalues, so we redeclare it for internal use. */ |
471 | +#define LUA_TUPVAL (LUA_TOTALTAGS + 1) |
472 | + |
473 | /* The "type" we write when we persist a value via a replacement from the |
474 | * permanents table. This is just an arbitrary number, but it must we lower |
475 | * than the reference offset (below) and outside the range Lua uses for its |
476 | * types (> LUA_TOTALTAGS). */ |
477 | -#define ERIS_PERMANENT (LUA_TOTALTAGS + 1) |
478 | +#define ERIS_PERMANENT (LUA_TOTALTAGS + 2) |
479 | |
480 | /* This is essentially the first reference we'll use. We do this to save one |
481 | * field in our persisted data: if the value is smaller than this, the object |
482 | @@ -266,6 +310,12 @@ |
483 | #define BUFFIDX 3 |
484 | #define PATHIDX 4 |
485 | |
486 | +/* Table indices for upvalue tables, keeping track of upvals to open. */ |
487 | +#define UVTOCL 1 |
488 | +#define UVTONU 2 |
489 | +#define UVTVAL 3 |
490 | +#define UVTREF 4 |
491 | + |
492 | /* }======================================================================== */ |
493 | |
494 | /* |
495 | @@ -405,12 +455,13 @@ |
496 | } |
497 | |
498 | /* Used as a callback for luaL_opt to check boolean setting values. */ |
499 | -static void |
500 | +static bool |
501 | checkboolean(lua_State *L, int narg) { /* ... bool? ... */ |
502 | if (!lua_isboolean(L, narg)) { /* ... :( ... */ |
503 | - luaL_argerror(L, narg, lua_pushfstring(L, |
504 | + return luaL_argerror(L, narg, lua_pushfstring(L, |
505 | "boolean expected, got %s", lua_typename(L, lua_type(L, narg)))); |
506 | } /* ... bool ... */ |
507 | + return lua_toboolean(L, narg); |
508 | } |
509 | |
510 | /* }======================================================================== */ |
511 | @@ -427,7 +478,7 @@ |
512 | /* Writes a raw memory block with the specified size. */ |
513 | #define WRITE_RAW(value, size) {\ |
514 | if (info->u.pi.writer(info->L, (value), (size), info->u.pi.ud)) \ |
515 | - eris_error(info, "could not write data"); } |
516 | + eris_error(info, ERIS_ERR_WRITE); } |
517 | |
518 | /* Writes a single value with the specified type. */ |
519 | #define WRITE_VALUE(value, type) write_##type(info, value) |
520 | @@ -441,7 +492,7 @@ |
521 | /* Reads a raw block of memory with the specified size. */ |
522 | #define READ_RAW(value, size) {\ |
523 | if (eris_read(&info->u.upi.zio, (value), (size))) \ |
524 | - eris_error(info, "could not read data"); } |
525 | + eris_error(info, ERIS_ERR_READ); } |
526 | |
527 | /* Reads a single value with the specified type. */ |
528 | #define READ_VALUE(type) read_##type(info) |
529 | @@ -527,7 +578,7 @@ |
530 | write_int64_t(info, value); |
531 | } |
532 | else { |
533 | - eris_error(info, "unsupported int type"); |
534 | + eris_error(info, ERIS_ERR_TYPE_INT); |
535 | } |
536 | } |
537 | |
538 | @@ -543,7 +594,7 @@ |
539 | write_uint64_t(info, value); |
540 | } |
541 | else { |
542 | - eris_error(info, "unsupported size_t type"); |
543 | + eris_error(info, ERIS_ERR_TYPE_SIZE); |
544 | } |
545 | } |
546 | |
547 | @@ -556,7 +607,20 @@ |
548 | write_float64(info, value); |
549 | } |
550 | else { |
551 | - eris_error(info, "unsupported lua_Number type"); |
552 | + eris_error(info, ERIS_ERR_TYPE_FLOAT); |
553 | + } |
554 | +} |
555 | + |
556 | +static void |
557 | +write_lua_Integer(Info *info, lua_Integer value) { |
558 | + if (sizeof(lua_Integer) == sizeof(uint32_t)) { |
559 | + write_uint32_t(info, value); |
560 | + } |
561 | + else if (sizeof(lua_Integer) == sizeof(uint64_t)) { |
562 | + write_uint64_t(info, value); |
563 | + } |
564 | + else { |
565 | + eris_error(info, ERIS_ERR_TYPE_INT); |
566 | } |
567 | } |
568 | |
569 | @@ -657,25 +721,25 @@ |
570 | int16_t pvalue = read_int16_t(info); |
571 | value = (int)pvalue; |
572 | if ((int32_t)value != pvalue) { |
573 | - eris_error(info, "int value would get truncated"); |
574 | + eris_error(info, ERIS_ERR_TRUNC_INT); |
575 | } |
576 | } |
577 | else if (info->u.upi.sizeof_int == sizeof(int32_t)) { |
578 | int32_t pvalue = read_int32_t(info); |
579 | value = (int)pvalue; |
580 | if ((int32_t)value != pvalue) { |
581 | - eris_error(info, "int value would get truncated"); |
582 | + eris_error(info, ERIS_ERR_TRUNC_INT); |
583 | } |
584 | } |
585 | else if (info->u.upi.sizeof_int == sizeof(int64_t)) { |
586 | int64_t pvalue = read_int64_t(info); |
587 | value = (int)pvalue; |
588 | if ((int64_t)value != pvalue) { |
589 | - eris_error(info, "int value would get truncated"); |
590 | + eris_error(info, ERIS_ERR_TRUNC_INT); |
591 | } |
592 | } |
593 | else { |
594 | - eris_error(info, "unsupported int type"); |
595 | + eris_error(info, ERIS_ERR_TYPE_INT); |
596 | value = 0; /* not reached */ |
597 | } |
598 | return value; |
599 | @@ -688,25 +752,25 @@ |
600 | uint16_t pvalue = read_uint16_t(info); |
601 | value = (size_t)pvalue; |
602 | if ((uint32_t)value != pvalue) { |
603 | - eris_error(info, "size_t value would get truncated"); |
604 | + eris_error(info, ERIS_ERR_TRUNC_SIZE); |
605 | } |
606 | } |
607 | else if (info->u.upi.sizeof_size_t == sizeof(uint32_t)) { |
608 | uint32_t pvalue = read_uint32_t(info); |
609 | value = (size_t)pvalue; |
610 | if ((uint32_t)value != pvalue) { |
611 | - eris_error(info, "size_t value would get truncated"); |
612 | + eris_error(info, ERIS_ERR_TRUNC_SIZE); |
613 | } |
614 | } |
615 | else if (info->u.upi.sizeof_size_t == sizeof(uint64_t)) { |
616 | uint64_t pvalue = read_uint64_t(info); |
617 | value = (size_t)pvalue; |
618 | if ((uint64_t)value != pvalue) { |
619 | - eris_error(info, "size_t value would get truncated"); |
620 | + eris_error(info, ERIS_ERR_TRUNC_SIZE); |
621 | } |
622 | } |
623 | else { |
624 | - eris_error(info, "unsupported size_t type"); |
625 | + eris_error(info, ERIS_ERR_TYPE_SIZE); |
626 | value = 0; /* not reached */ |
627 | } |
628 | return value; |
629 | @@ -721,7 +785,21 @@ |
630 | return read_float64(info); |
631 | } |
632 | else { |
633 | - eris_error(info, "unsupported lua_Number type"); |
634 | + eris_error(info, ERIS_ERR_TYPE_FLOAT); |
635 | + return 0; /* not reached */ |
636 | + } |
637 | +} |
638 | + |
639 | +static lua_Integer |
640 | +read_lua_Integer(Info *info) { |
641 | + if (sizeof(lua_Integer) == sizeof(uint32_t)) { |
642 | + return (lua_Integer) read_uint32_t(info); |
643 | + } |
644 | + else if (sizeof(lua_Integer) == sizeof(uint64_t)) { |
645 | + return (lua_Integer) read_uint64_t(info); |
646 | + } |
647 | + else { |
648 | + eris_error(info, ERIS_ERR_TYPE_INT); |
649 | return 0; /* not reached */ |
650 | } |
651 | } |
652 | @@ -776,13 +854,25 @@ |
653 | |
654 | static void |
655 | p_number(Info *info) { /* ... num */ |
656 | - WRITE_VALUE(lua_tonumber(info->L, -1), lua_Number); |
657 | + if (lua_isinteger(info->L, -1)) { |
658 | + WRITE_VALUE(true, uint8_t); |
659 | + WRITE_VALUE(lua_tointeger(info->L, -1), lua_Integer); |
660 | + } |
661 | + else { |
662 | + WRITE_VALUE(false, uint8_t); |
663 | + WRITE_VALUE(lua_tonumber(info->L, -1), lua_Number); |
664 | + } |
665 | } |
666 | |
667 | static void |
668 | u_number(Info *info) { /* ... */ |
669 | eris_checkstack(info->L, 1); |
670 | - lua_pushnumber(info->L, READ_VALUE(lua_Number)); /* ... num */ |
671 | + if (READ_VALUE(uint8_t)) { |
672 | + lua_pushinteger(info->L, READ_VALUE(lua_Integer)); |
673 | + } |
674 | + else { |
675 | + lua_pushnumber(info->L, READ_VALUE(lua_Number)); /* ... num */ |
676 | + } |
677 | |
678 | eris_assert(lua_type(info->L, -1) == LUA_TNUMBER); |
679 | } |
680 | @@ -801,7 +891,7 @@ |
681 | u_string(Info *info) { /* ... */ |
682 | eris_checkstack(info->L, 2); |
683 | { |
684 | - // TODO(unknown): Can we avoid this copy somehow? (Without it getting too nasty) |
685 | + /* TODO Can we avoid this copy somehow? (Without it getting too nasty) */ |
686 | const size_t length = READ_VALUE(size_t); |
687 | char *value = lua_newuserdata(info->L, length * sizeof(char)); /* ... tmp */ |
688 | READ_RAW(value, length); |
689 | @@ -843,7 +933,7 @@ |
690 | lua_pop(info->L, 1); /* ... tbl */ |
691 | } |
692 | else { /* tbl :( */ |
693 | - eris_error(info, "bad metatable, not nil or table"); |
694 | + eris_error(info, ERIS_ERR_METATABLE); |
695 | } |
696 | poppath(info); |
697 | } |
698 | @@ -923,7 +1013,7 @@ |
699 | lua_rawset(info->L, -3); /* ... tbl */ |
700 | } |
701 | else { |
702 | - eris_error(info, "bad table value, got a nil value"); |
703 | + eris_error(info, ERIS_ERR_TABLE); |
704 | } |
705 | |
706 | poppath(info); |
707 | @@ -996,8 +1086,7 @@ |
708 | lua_call(info->L, 1, 1); /* ... obj func? */ |
709 | } |
710 | if (!lua_isfunction(info->L, -1)) { /* ... obj :( */ |
711 | - eris_error(info, "%s did not return a function", |
712 | - info->u.pi.metafield); |
713 | + eris_error(info, ERIS_ERR_SPER_FUNC, info->u.pi.metafield); |
714 | } /* ... obj func */ |
715 | |
716 | /* Special persistence, call this function when unpersisting. */ |
717 | @@ -1006,8 +1095,7 @@ |
718 | lua_pop(info->L, 1); /* ... obj */ |
719 | return; |
720 | default: /* ... obj mt :( */ |
721 | - eris_error(info, "%d not nil, boolean, or function", |
722 | - info->u.pi.metafield); |
723 | + eris_error(info, ERIS_ERR_SPER_TYPE, info->u.pi.metafield); |
724 | return; /* not reached */ |
725 | } |
726 | } |
727 | @@ -1018,10 +1106,10 @@ |
728 | literal(info); /* ... obj */ |
729 | } |
730 | else if (lua_type(info->L, -1) == LUA_TTABLE) { |
731 | - eris_error(info, "attempt to persist forbidden table"); |
732 | + eris_error(info, ERIS_ERR_SPER_PROT); |
733 | } |
734 | else { |
735 | - eris_error(info, "attempt to literally persist userdata"); |
736 | + eris_error(info, ERIS_ERR_USERDATA); |
737 | } |
738 | } |
739 | |
740 | @@ -1040,7 +1128,7 @@ |
741 | * persisting a special object. */ |
742 | unpersist(info); /* ... spfunc? */ |
743 | if (!lua_isfunction(info->L, -1)) { /* ... :( */ |
744 | - eris_error(info, "invalid restore function"); |
745 | + eris_error(info, ERIS_ERR_SPER_UFUNC); |
746 | } /* ... spfunc */ |
747 | |
748 | if (info->passIOToPersist) { |
749 | @@ -1051,8 +1139,9 @@ |
750 | } |
751 | |
752 | if (lua_type(info->L, -1) != type) { /* ... :( */ |
753 | - eris_error(info, "bad unpersist function (%s expected, returned %s)", |
754 | - kTypenames[type], kTypenames[lua_type(info->L, -1)]); |
755 | + const char *want = kTypenames[type]; |
756 | + const char *have = kTypenames[lua_type(info->L, -1)]; |
757 | + eris_error(info, ERIS_ERR_SPER_LOAD, want, have); |
758 | } /* ... obj */ |
759 | |
760 | /* Update the reftable entry. */ |
761 | @@ -1326,12 +1415,14 @@ |
762 | u_upval(Info *info) { /* ... */ |
763 | eris_checkstack(info->L, 2); |
764 | |
765 | - /* Create the table we use to store the pointer to the actual upval (1), the |
766 | - * value of the upval (2) and any pointers to the pointer to the upval (3+).*/ |
767 | - lua_createtable(info->L, 3, 0); /* ... tbl */ |
768 | + /* Create the table we use to store the stack location to the upval (1+2), |
769 | + * the value of the upval (3) and any references to the upvalue's value (4+). |
770 | + * References are stored as two entries each, the actual closure holding the |
771 | + * upvalue, and the index of the upvalue in that closure. */ |
772 | + lua_createtable(info->L, 5, 0); /* ... tbl */ |
773 | registerobject(info); |
774 | unpersist(info); /* ... tbl obj */ |
775 | - lua_rawseti(info->L, -2, 1); /* ... tbl */ |
776 | + lua_rawseti(info->L, -2, UVTVAL); /* ... tbl */ |
777 | |
778 | eris_assert(lua_type(info->L, -1) == LUA_TTABLE); |
779 | } |
780 | @@ -1354,8 +1445,7 @@ |
781 | switch (ttype(info->L->top - 1)) { |
782 | case LUA_TLCF: /* light C function */ |
783 | /* We cannot persist these, they have to be handled via the permtable. */ |
784 | - eris_error(info, "attempt to persist a light C function (%p)", |
785 | - lua_tocfunction(info->L, -1)); |
786 | + eris_error(info, ERIS_ERR_CFUNC, lua_tocfunction(info->L, -1)); |
787 | return; /* not reached */ |
788 | case LUA_TCCL: /* C closure */ { /* perms reftbl ... ccl */ |
789 | CClosure *cl = clCvalue(info->L->top - 1); |
790 | @@ -1387,7 +1477,7 @@ |
791 | break; |
792 | } |
793 | case LUA_TLCL: /* Lua function */ { /* perms reftbl ... lcl */ |
794 | - LClosure *cl = clLvalue(info->L->top - 1); |
795 | + LClosure *cl = eris_clLvalue(info->L->top - 1); |
796 | /* Mark it as a Lua closure. */ |
797 | WRITE_VALUE(false, uint8_t); |
798 | /* Write the upvalue count first, since we have to know it when creating |
799 | @@ -1421,7 +1511,7 @@ |
800 | break; |
801 | } |
802 | default: |
803 | - eris_error(info, "attempt to persist unknown function type"); |
804 | + eris_error(info, ERIS_ERR_NOFUNC); |
805 | return; /* not reached */ |
806 | } |
807 | } |
808 | @@ -1444,12 +1534,11 @@ |
809 | /* Read the C function from the permanents table. */ |
810 | unpersist(info); /* ... cfunc */ |
811 | if (!lua_iscfunction(info->L, -1)) { |
812 | - eris_error(info, "bad C closure (C function expected, got %s)", |
813 | - kTypenames[lua_type(info->L, -1)]); |
814 | + eris_error(info, ERIS_ERR_UCFUNC, kTypenames[lua_type(info->L, -1)]); |
815 | } |
816 | f = lua_tocfunction(info->L, -1); |
817 | if (!f) { |
818 | - eris_error(info, "bad C closure (C function expected, got null)"); |
819 | + eris_error(info, ERIS_ERR_UCFUNCNULL); |
820 | } |
821 | lua_pop(info->L, 1); /* ... */ |
822 | |
823 | @@ -1476,7 +1565,7 @@ |
824 | poppath(info); |
825 | } |
826 | else { |
827 | - Closure *cl; |
828 | + LClosure *cl; |
829 | Proto *p; |
830 | |
831 | eris_checkstack(info->L, 4); |
832 | @@ -1494,27 +1583,28 @@ |
833 | * unpersist function. This way the instance is safely hooked up to an |
834 | * object, so we don't have to worry about it getting GCed. */ |
835 | pushpath(info, ".proto"); |
836 | - cl->l.p = eris_newproto(info->L); |
837 | + cl->p = eris_newproto(info->L); |
838 | /* Push the proto into which to unpersist as a parameter to u_proto. */ |
839 | - lua_pushlightuserdata(info->L, cl->l.p); /* ... lcl nproto */ |
840 | + lua_pushlightuserdata(info->L, cl->p); /* ... lcl nproto */ |
841 | unpersist(info); /* ... lcl nproto nproto/oproto */ |
842 | eris_assert(lua_type(info->L, -1) == LUA_TLIGHTUSERDATA); |
843 | /* The proto we have now may differ, if we already unpersisted it before. |
844 | * In that case we now have a reference to the originally unpersisted |
845 | * proto so we'll use that. */ |
846 | p = lua_touserdata(info->L, -1); |
847 | - if (p != cl->l.p) { /* ... lcl nproto oproto */ |
848 | + if (p != cl->p) { /* ... lcl nproto oproto */ |
849 | /* Just overwrite the old one, GC will clean this up. */ |
850 | - cl->l.p = p; |
851 | + cl->p = p; |
852 | } |
853 | lua_pop(info->L, 2); /* ... lcl */ |
854 | - eris_assert(cl->l.p->sizeupvalues == nups); |
855 | + eris_assert(cl->nupvalues == cl->p->sizeupvalues); |
856 | + eris_initupvals(info->L, cl); /* Init to all closed, fill in later. */ |
857 | poppath(info); |
858 | |
859 | /* Unpersist all upvalues. */ |
860 | pushpath(info, ".upvalues"); |
861 | for (nup = 1; nup <= nups; ++nup) { |
862 | - UpVal **uv = &cl->l.upvals[nup - 1]; |
863 | + UpVal **uv = &cl->upvals[nup - 1]; |
864 | /* Get the actual name of the upvalue, if possible. */ |
865 | if (p->upvalues[nup - 1].name) { |
866 | pushpath(info, "[%s]", getstr(p->upvalues[nup - 1].name)); |
867 | @@ -1524,50 +1614,60 @@ |
868 | } |
869 | unpersist(info); /* ... lcl tbl */ |
870 | eris_assert(lua_type(info->L, -1) == LUA_TTABLE); |
871 | - lua_rawgeti(info->L, -1, 2); /* ... lcl tbl upval/nil */ |
872 | + lua_rawgeti(info->L, -1, UVTOCL); /* ... lcl tbl olcl/nil */ |
873 | if (lua_isnil(info->L, -1)) { /* ... lcl tbl nil */ |
874 | lua_pop(info->L, 1); /* ... lcl tbl */ |
875 | - *uv = eris_newupval(info->L); |
876 | - lua_pushlightuserdata(info->L, *uv); /* ... lcl tbl upval */ |
877 | - lua_rawseti(info->L, -2, 2); /* ... lcl tbl */ |
878 | + lua_pushvalue(info->L, -2); /* ... lcl tbl lcl */ |
879 | + lua_rawseti(info->L, -2, UVTOCL); /* ... lcl tbl */ |
880 | + lua_pushinteger(info->L, nup); /* ... lcl tbl nup */ |
881 | + lua_rawseti(info->L, -2, UVTONU); /* ... lcl tbl */ |
882 | } |
883 | - else { /* ... lcl tbl upval */ |
884 | - eris_assert(lua_type(info->L, -1) == LUA_TLIGHTUSERDATA); |
885 | - *uv = (UpVal*)lua_touserdata(info->L, -1); |
886 | + else { /* ... lcl tbl olcl */ |
887 | + int onup; |
888 | + eris_assert(lua_type(info->L, -1) == LUA_TFUNCTION); |
889 | + lua_rawgeti(info->L, -2, UVTONU); /* ... lcl tbl olcl onup */ |
890 | + eris_assert(lua_type(info->L, -1) == LUA_TNUMBER); |
891 | + onup = lua_tointeger(info->L, -1); |
892 | + lua_pop(info->L, 1); /* ... lcl tbl olcl */ |
893 | + lua_upvaluejoin(info->L, -3, nup, -1, onup); |
894 | lua_pop(info->L, 1); /* ... lcl tbl */ |
895 | } |
896 | |
897 | /* Set the upvalue's actual value and add our reference to the upvalue to |
898 | - * the list, for pointer patching if we have to open the upvalue in |
899 | + * the list, for reference patching if we have to open the upvalue in |
900 | * u_thread. Either is only necessary if the upvalue is still closed. */ |
901 | - if ((*uv)->v == &(*uv)->u.value) { |
902 | + if (!upisopen(*uv)) { |
903 | + int i; |
904 | /* Always update the value of the upvalue's value for closed upvalues, |
905 | * even if we re-used one - if we had a cycle, it might have been |
906 | - * incorrectly initialized to nil before. */ |
907 | - lua_rawgeti(info->L, -1, 1); /* ... lcl tbl obj */ |
908 | + * incorrectly initialized to nil before (or rather, not yet set). */ |
909 | + lua_rawgeti(info->L, -1, UVTVAL); /* ... lcl tbl obj */ |
910 | eris_setobj(info->L, &(*uv)->u.value, info->L->top - 1); |
911 | lua_pop(info->L, 1); /* ... lcl tbl */ |
912 | |
913 | - lua_pushlightuserdata(info->L, uv); /* ... lcl tbl upvalp */ |
914 | - if (luaL_len(info->L, -2) >= 2) { |
915 | - /* Got a valid sequence, insert at the end. */ |
916 | - lua_rawseti(info->L, -2, luaL_len(info->L, -2) + 1); /* ... lcl tbl */ |
917 | + lua_pushinteger(info->L, nup); /* ... lcl tbl nup */ |
918 | + lua_pushvalue(info->L, -3); /* ... lcl tbl nup lcl */ |
919 | + if (luaL_len(info->L, -3) >= UVTVAL) { |
920 | + /* Got a valid sequence (value already set), insert at the end. */ |
921 | + i = luaL_len(info->L, -3); |
922 | + lua_rawseti(info->L, -3, i + 1); /* ... lcl tbl nup */ |
923 | + lua_rawseti(info->L, -2, i + 2); /* ... lcl tbl */ |
924 | } |
925 | - else { /* ... lcl tbl upvalp */ |
926 | - int i; |
927 | + else { /* ... lcl tbl nup lcl */ |
928 | /* Find where to insert. This can happen if we have cycles, in which |
929 | * case the table is not fully initialized at this point, i.e. the |
930 | * value is not in it, yet (we work around that by always setting it, |
931 | * as seen above). */ |
932 | - for (i = 3;; ++i) { |
933 | - lua_rawgeti(info->L, -2, i); /* ... lcl tbl upvalp upvalp/nil */ |
934 | - if (lua_isnil(info->L, -1)) { /* ... lcl tbl upvalp nil */ |
935 | - lua_pop(info->L, 1); /* ... lcl tbl upvalp */ |
936 | - lua_rawseti(info->L, -2, i); /* ... lcl tbl */ |
937 | + for (i = UVTREF;; i += 2) { |
938 | + lua_rawgeti(info->L, -3, i); /* ... lcl tbl nup lcl lcl/nil */ |
939 | + if (lua_isnil(info->L, -1)) { /* ... lcl tbl nup lcl nil */ |
940 | + lua_pop(info->L, 1); /* ... lcl tbl nup lcl */ |
941 | + lua_rawseti(info->L, -3, i); /* ... lcl tbl nup */ |
942 | + lua_rawseti(info->L, -2, i + 1); /* ... lcl tbl */ |
943 | break; |
944 | } |
945 | else { |
946 | - lua_pop(info->L, 1); /* ... lcl tbl upvalp */ |
947 | + lua_pop(info->L, 1); /* ... lcl tbl nup lcl */ |
948 | } |
949 | } /* ... lcl tbl */ |
950 | } |
951 | @@ -1578,8 +1678,9 @@ |
952 | } |
953 | poppath(info); |
954 | |
955 | - eris_barrierproto(info->L, p, cl); |
956 | - p->cache = cl; /* save it in cache for reuse, see lvm.c:416 */ |
957 | + /* save it in cache for reuse, see lvm.c:416 */ |
958 | + if (!isblack(p)) |
959 | + p->cache = cl; |
960 | } |
961 | |
962 | eris_assert(lua_type(info->L, -1) == LUA_TFUNCTION); |
963 | @@ -1590,8 +1691,7 @@ |
964 | static void |
965 | p_thread(Info *info) { /* ... thread */ |
966 | lua_State* thread = lua_tothread(info->L, -1); |
967 | - size_t level; |
968 | - StkId o; |
969 | + size_t level = 0, total = thread->top - thread->stack; |
970 | CallInfo *ci; |
971 | UpVal *uv; |
972 | |
973 | @@ -1600,13 +1700,13 @@ |
974 | /* We cannot persist any running threads, because by definition we *are* that |
975 | * running thread. And we use the stack. So yeah, really not a good idea. */ |
976 | if (thread == info->L) { |
977 | - eris_error(info, "cannot persist currently running thread"); |
978 | + eris_error(info, ERIS_ERR_THREAD); |
979 | return; /* not reached */ |
980 | } |
981 | |
982 | /* Persist the stack. Save the total size and used space first. */ |
983 | WRITE_VALUE(thread->stacksize, int); |
984 | - WRITE_VALUE(thread->top - thread->stack, size_t); |
985 | + WRITE_VALUE(total, size_t); |
986 | |
987 | /* The Lua stack looks like this: |
988 | * stack ... top ... stack_last |
989 | @@ -1614,10 +1714,15 @@ |
990 | * element, i.e. there's nothing stored there. So we stop one below that. */ |
991 | pushpath(info, ".stack"); |
992 | lua_pushnil(info->L); /* ... thread nil */ |
993 | - level = 0; |
994 | - for (o = thread->stack; o < thread->top; ++o) { |
995 | - pushpath(info, "[%d]", level++); |
996 | - eris_setobj(info->L, info->L->top - 1, o); /* ... thread obj */ |
997 | + /* Since the thread's stack may be re-allocated in the meantime, we cannot |
998 | + * use pointer arithmetic here (i.e. o = thread->stack; ...; ++o). Instead we |
999 | + * have to keep track of our position in the stack directly (which we do for |
1000 | + * the path info anyway) and compute the actual address each time. |
1001 | + */ |
1002 | + for (; level < total; ++level) { |
1003 | + pushpath(info, "[%d]", level); |
1004 | + eris_setobj(info->L, info->L->top - 1, thread->stack + level); |
1005 | + /* ... thread obj */ |
1006 | persist(info); /* ... thread obj */ |
1007 | poppath(info); |
1008 | } |
1009 | @@ -1647,7 +1752,7 @@ |
1010 | WRITE_VALUE(thread->hookcount, int); */ |
1011 | |
1012 | if (thread->hook) { |
1013 | - // TODO(unknown): Warn that hooks are not persisted? |
1014 | + /* TODO Warn that hooks are not persisted? */ |
1015 | } |
1016 | |
1017 | /* Write call information (stack frames). In 5.2 CallInfo is stored in a |
1018 | @@ -1665,42 +1770,46 @@ |
1019 | WRITE_VALUE(eris_savestackidx(thread, ci->top), size_t); |
1020 | WRITE_VALUE(ci->nresults, int16_t); |
1021 | WRITE_VALUE(ci->callstatus, uint8_t); |
1022 | - /* CallInfo.extra is used in two contexts: if L->status == LUA_YIELD and |
1023 | - * CallInfo is the one stored as L->ci, in which case ci->extra refers to |
1024 | - * the original value of L->ci->func, and when we have a yieldable pcall |
1025 | - * (ci->callstatus & CIST_YPCALL) where ci->extra holds the stack level |
1026 | - * of the function being called (see lua_pcallk). We save the ci->extra |
1027 | - * for L->ci after the loop, because we won't know which one it is when |
1028 | - * unpersisting. */ |
1029 | - if (ci->callstatus & CIST_YPCALL) { |
1030 | - WRITE_VALUE(eris_savestackidx(thread, |
1031 | - eris_restorestack(thread, ci->extra)), size_t); |
1032 | - } |
1033 | - |
1034 | - eris_assert(eris_isLua(ci) || (ci->callstatus & CIST_TAIL) == 0); |
1035 | - if (ci->callstatus & CIST_HOOKYIELD) { |
1036 | - eris_error(info, "cannot persist yielded hooks"); |
1037 | - } |
1038 | - |
1039 | - if (eris_isLua(ci)) { |
1040 | - const LClosure *lcl = eris_ci_func(ci); |
1041 | - WRITE_VALUE(eris_savestackidx(thread, ci->u.l.base), size_t); |
1042 | - WRITE_VALUE(ci->u.l.savedpc - lcl->p->code, size_t); |
1043 | - } |
1044 | - else { |
1045 | - WRITE_VALUE(ci->u.c.status, uint8_t); |
1046 | - |
1047 | - /* These are only used while a thread is being executed: |
1048 | - WRITE_VALUE(ci->u.c.old_errfunc, ptrdiff_t); |
1049 | - WRITE_VALUE(ci->u.c.old_allowhook, uint8_t); */ |
1050 | - |
1051 | - // TODO(unknown): Is this really right? Hooks may be a problem? |
1052 | - if (ci->callstatus & (CIST_YPCALL | CIST_YIELDED)) { |
1053 | - WRITE_VALUE(ci->u.c.ctx, int); |
1054 | - eris_assert(ci->u.c.k); |
1055 | - lua_pushcfunction(info->L, ci->u.c.k); /* ... thread func */ |
1056 | - persist(info); /* ... thread func/nil */ |
1057 | - lua_pop(info->L, 1); /* ... thread */ |
1058 | + if (ci->callstatus) { |
1059 | + /* CallInfo.extra is used in two contexts: if L->status == LUA_YIELD and |
1060 | + * CallInfo is the one stored as L->ci, in which case ci->extra refers to |
1061 | + * the original value of L->ci->func, and when we have a yieldable pcall |
1062 | + * (ci->callstatus & CIST_YPCALL) where ci->extra holds the stack level |
1063 | + * of the function being called (see lua_pcallk). We save the ci->extra |
1064 | + * for L->ci after the loop, because we won't know which one it is when |
1065 | + * unpersisting. */ |
1066 | + if (ci->callstatus & CIST_YPCALL) { |
1067 | + WRITE_VALUE(eris_savestackidx(thread, |
1068 | + eris_restorestack(thread, ci->extra)), size_t); |
1069 | + } |
1070 | + |
1071 | + eris_assert(eris_isLua(ci) || (ci->callstatus & CIST_TAIL) == 0); |
1072 | + if (ci->callstatus & CIST_HOOKYIELD) { |
1073 | + eris_error(info, ERIS_ERR_HOOK); |
1074 | + } |
1075 | + |
1076 | + if (eris_isLua(ci)) { |
1077 | + const LClosure *lcl = eris_ci_func(ci); |
1078 | + WRITE_VALUE(eris_savestackidx(thread, ci->u.l.base), size_t); |
1079 | + WRITE_VALUE(ci->u.l.savedpc - lcl->p->code, size_t); |
1080 | + } |
1081 | + else { |
1082 | + /* These are only used while a thread is being executed: |
1083 | + WRITE_VALUE(ci->u.c.old_errfunc, ptrdiff_t); */ |
1084 | + if (thread->status == LUA_YIELD && ci->u.c.k) { |
1085 | + WRITE_VALUE(true, uint8_t); |
1086 | + WRITE_VALUE(ci->u.c.ctx, int); |
1087 | + /* NOTE Ugly hack. We have to push the continuation function as a C |
1088 | + * function to properly track it in our ref table. It's never called, |
1089 | + * so we can get away with this. */ |
1090 | + lua_pushcfunction(info->L, (lua_CFunction) ci->u.c.k); |
1091 | + /* ... thread func */ |
1092 | + persist(info); /* ... thread func/nil */ |
1093 | + lua_pop(info->L, 1); /* ... thread */ |
1094 | + } |
1095 | + else { |
1096 | + WRITE_VALUE(false, uint8_t); |
1097 | + } |
1098 | } |
1099 | } |
1100 | |
1101 | @@ -1719,11 +1828,11 @@ |
1102 | pushpath(info, ".openupval"); |
1103 | lua_pushnil(info->L); /* ... thread nil */ |
1104 | level = 0; |
1105 | - for (uv = eris_gco2uv(thread->openupval); |
1106 | + for (uv = thread->openupval; |
1107 | uv != NULL; |
1108 | - uv = eris_gco2uv(eris_gch(eris_obj2gco(uv))->next)) |
1109 | + uv = uv->u.open.next) |
1110 | { |
1111 | - pushpath(info, "[%d]", level); |
1112 | + pushpath(info, "[%d]", level++); |
1113 | WRITE_VALUE(eris_savestackidx(thread, uv->v) + 1, size_t); |
1114 | eris_setobj(info->L, info->L->top - 1, uv->v); /* ... thread obj */ |
1115 | lua_pushlightuserdata(info->L, uv); /* ... thread obj id */ |
1116 | @@ -1739,7 +1848,7 @@ |
1117 | #define validate(stackpos, inclmax) \ |
1118 | if ((stackpos) < thread->stack || stackpos > (inclmax)) { \ |
1119 | (stackpos) = thread->stack; \ |
1120 | - eris_error(info, "stack index out of bounds"); } |
1121 | + eris_error(info, ERIS_ERR_STACKBOUNDS); } |
1122 | |
1123 | /* I had so hoped to get by without any 'hacks', but I surrender. We mark the |
1124 | * thread as incomplete to avoid the GC messing with it while we're building |
1125 | @@ -1805,8 +1914,8 @@ |
1126 | if (thread->errfunc) { |
1127 | o = eris_restorestack(thread, thread->errfunc); |
1128 | validate(o, thread->top); |
1129 | - if (eris_ttypenv(o) != LUA_TFUNCTION) { |
1130 | - eris_error(info, "invalid errfunc"); |
1131 | + if (eris_ttnov(o) != LUA_TFUNCTION) { |
1132 | + eris_error(info, ERIS_ERR_THREADERRF); |
1133 | } |
1134 | } |
1135 | /* These are only used while a thread is being executed or can be deduced: |
1136 | @@ -1835,61 +1944,64 @@ |
1137 | validate(thread->ci->top, thread->stack_last); |
1138 | thread->ci->nresults = READ_VALUE(int16_t); |
1139 | thread->ci->callstatus = READ_VALUE(uint8_t); |
1140 | - /** See comment in p_thread. */ |
1141 | - if (thread->ci->callstatus & CIST_YPCALL) { |
1142 | - thread->ci->extra = eris_savestack(thread, |
1143 | - eris_restorestackidx(thread, READ_VALUE(size_t))); |
1144 | - o = eris_restorestack(thread, thread->ci->extra); |
1145 | - validate(o, thread->top); |
1146 | - if (eris_ttypenv(o) != LUA_TFUNCTION) { |
1147 | - eris_error(info, "invalid callinfo"); |
1148 | - } |
1149 | - } |
1150 | - |
1151 | - if (eris_isLua(thread->ci)) { |
1152 | - LClosure *lcl = eris_ci_func(thread->ci); |
1153 | - thread->ci->u.l.base = eris_restorestackidx(thread, READ_VALUE(size_t)); |
1154 | - validate(thread->ci->u.l.base, thread->top); |
1155 | - thread->ci->u.l.savedpc = lcl->p->code + READ_VALUE(size_t); |
1156 | - if (thread->ci->u.l.savedpc < lcl->p->code || |
1157 | - thread->ci->u.l.savedpc > lcl->p->code + lcl->p->sizecode) |
1158 | - { |
1159 | - thread->ci->u.l.savedpc = lcl->p->code; /* Just to be safe. */ |
1160 | - eris_error(info, "saved program counter out of bounds"); |
1161 | - } |
1162 | + if (thread->ci->callstatus) { |
1163 | + /** See comment in p_thread. */ |
1164 | + if (thread->ci->callstatus & CIST_YPCALL) { |
1165 | + thread->ci->extra = eris_savestack(thread, |
1166 | + eris_restorestackidx(thread, READ_VALUE(size_t))); |
1167 | + o = eris_restorestack(thread, thread->ci->extra); |
1168 | + validate(o, thread->top); |
1169 | + if (eris_ttnov(o) != LUA_TFUNCTION) { |
1170 | + eris_error(info, ERIS_ERR_THREADCI); |
1171 | + } |
1172 | + } |
1173 | + |
1174 | + if (eris_isLua(thread->ci)) { |
1175 | + LClosure *lcl = eris_ci_func(thread->ci); |
1176 | + thread->ci->u.l.base = eris_restorestackidx(thread, READ_VALUE(size_t)); |
1177 | + validate(thread->ci->u.l.base, thread->top); |
1178 | + thread->ci->u.l.savedpc = lcl->p->code + READ_VALUE(size_t); |
1179 | + if (thread->ci->u.l.savedpc < lcl->p->code || |
1180 | + thread->ci->u.l.savedpc > lcl->p->code + lcl->p->sizecode) |
1181 | + { |
1182 | + thread->ci->u.l.savedpc = lcl->p->code; /* Just to be safe. */ |
1183 | + eris_error(info, ERIS_ERR_THREADPC); |
1184 | + } |
1185 | + } |
1186 | + else { |
1187 | + /* These are only used while a thread is being executed: |
1188 | + thread->ci->u.c.old_errfunc = READ_VALUE(ptrdiff_t); */ |
1189 | + thread->ci->u.c.old_errfunc = 0; |
1190 | + |
1191 | + if (thread->status == LUA_YIELD && READ_VALUE(uint8_t)) { |
1192 | + thread->ci->u.c.ctx = READ_VALUE(int); |
1193 | + LOCK(thread); |
1194 | + unpersist(info); /* ... thread func? */ |
1195 | + UNLOCK(thread); |
1196 | + if (lua_iscfunction(info->L, -1)) { /* ... thread func */ |
1197 | + /* NOTE Ugly hack. See p_thread. */ |
1198 | + thread->ci->u.c.k = (lua_KFunction) lua_tocfunction(info->L, -1); |
1199 | + } |
1200 | + else { |
1201 | + eris_error(info, ERIS_ERR_THREADCTX); |
1202 | + return; /* not reached */ |
1203 | + } |
1204 | + lua_pop(info->L, 1); /* ... thread */ |
1205 | + } |
1206 | + else { |
1207 | + thread->ci->u.c.ctx = 0; |
1208 | + thread->ci->u.c.k = NULL; |
1209 | + } |
1210 | + } |
1211 | + LOCK(thread); |
1212 | + poppath(info); |
1213 | + UNLOCK(thread); |
1214 | } |
1215 | else { |
1216 | - thread->ci->u.c.status = READ_VALUE(uint8_t); |
1217 | - |
1218 | - /* These are only used while a thread is being executed: |
1219 | - thread->ci->u.c.old_errfunc = READ_VALUE(ptrdiff_t); |
1220 | - thread->ci->u.c.old_allowhook = READ_VALUE(uint8_t); */ |
1221 | + thread->ci->u.c.k = NULL; |
1222 | thread->ci->u.c.old_errfunc = 0; |
1223 | - thread->ci->u.c.old_allowhook = 0; |
1224 | - |
1225 | - // TODO(unknown): Is this really right? |
1226 | - if (thread->ci->callstatus & (CIST_YPCALL | CIST_YIELDED)) { |
1227 | - thread->ci->u.c.ctx = READ_VALUE(int); |
1228 | - LOCK(thread); |
1229 | - unpersist(info); /* ... thread func? */ |
1230 | - UNLOCK(thread); |
1231 | - if (lua_iscfunction(info->L, -1)) { /* ... thread func */ |
1232 | - thread->ci->u.c.k = lua_tocfunction(info->L, -1); |
1233 | - } |
1234 | - else { |
1235 | - eris_error(info, "bad C continuation function"); |
1236 | - return; /* not reached */ |
1237 | - } |
1238 | - lua_pop(info->L, 1); /* ... thread */ |
1239 | - } |
1240 | - else { |
1241 | - thread->ci->u.c.ctx = 0; |
1242 | - thread->ci->u.c.k = NULL; |
1243 | - } |
1244 | + thread->ci->u.c.ctx = 0; |
1245 | } |
1246 | - LOCK(thread); |
1247 | - poppath(info); |
1248 | - UNLOCK(thread); |
1249 | |
1250 | /* Read in value for check for next iteration. */ |
1251 | if (READ_VALUE(uint8_t)) { |
1252 | @@ -1904,8 +2016,8 @@ |
1253 | eris_restorestackidx(thread, READ_VALUE(size_t))); |
1254 | o = eris_restorestack(thread, thread->ci->extra); |
1255 | validate(o, thread->top); |
1256 | - if (eris_ttypenv(o) != LUA_TFUNCTION) { |
1257 | - eris_error(info, "invalid callinfo"); |
1258 | + if (eris_ttnov(o) != LUA_TFUNCTION) { |
1259 | + eris_error(info, ERIS_ERR_THREADCI); |
1260 | } |
1261 | } |
1262 | LOCK(thread); |
1263 | @@ -1919,7 +2031,7 @@ |
1264 | * functions using them having been unpersisted (they'll usually be in the |
1265 | * stack of the thread). For this reason we store all previous references to |
1266 | * the upvalue in a table that is returned when we try to unpersist an |
1267 | - * upvalue, so that we can adjust these pointers in here. */ |
1268 | + * upvalue, so that we can adjust these references in here. */ |
1269 | LOCK(thread); |
1270 | pushpath(info, ".openupval"); |
1271 | UNLOCK(thread); |
1272 | @@ -1948,19 +2060,27 @@ |
1273 | nuv = eris_findupval(thread, stk); |
1274 | UNLOCK(thread); |
1275 | |
1276 | - /* Then check if we need to patch some pointers. */ |
1277 | - lua_rawgeti(info->L, -1, 2); /* ... thread tbl upval/nil */ |
1278 | - if (!lua_isnil(info->L, -1)) { /* ... thread tbl upval */ |
1279 | + /* Then check if we need to patch some references. */ |
1280 | + lua_rawgeti(info->L, -1, UVTREF); /* ... thread tbl lcl/nil */ |
1281 | + if (!lua_isnil(info->L, -1)) { /* ... thread tbl lcl */ |
1282 | int i, n; |
1283 | - eris_assert(lua_type(info->L, -1) == LUA_TLIGHTUSERDATA); |
1284 | + eris_assert(lua_type(info->L, -1) == LUA_TFUNCTION); |
1285 | /* Already exists, replace it. To do this we have to patch all the |
1286 | - * pointers to the already existing one, which we added to the table in |
1287 | - * u_closure, starting at index 3. */ |
1288 | + * references to the already existing one, which we added to the table in |
1289 | + * u_closure. */ |
1290 | lua_pop(info->L, 1); /* ... thread tbl */ |
1291 | - for (i = 3, n = luaL_len(info->L, -1); i <= n; ++i) { |
1292 | - lua_rawgeti(info->L, -1, i); /* ... thread tbl upvalp */ |
1293 | - (*(UpVal**)lua_touserdata(info->L, -1)) = nuv; |
1294 | - lua_pop(info->L, 1); /* ... thread tbl */ |
1295 | + for (i = UVTREF, n = luaL_len(info->L, -1); i <= n; i += 2) { |
1296 | + LClosure *cl; |
1297 | + int nup; |
1298 | + lua_rawgeti(info->L, -1, i); /* ... thread tbl lcl */ |
1299 | + cl = eris_clLvalue(info->L->top - 1); |
1300 | + lua_pop(info->L, 1); /* ... thread tbl */ |
1301 | + lua_rawgeti(info->L, -1, i + 1); /* ... thread tbl nup */ |
1302 | + nup = lua_tointeger(info->L, -1); |
1303 | + lua_pop(info->L, 1); /* ... thread tbl */ |
1304 | + /* Open the upvalue by pointing to the stack and register in GC. */ |
1305 | + cl->upvals[nup - 1] = nuv; |
1306 | + cl->upvals[nup - 1]->refcount++; |
1307 | } |
1308 | } |
1309 | else { /* ... thread tbl nil */ |
1310 | @@ -1970,8 +2090,6 @@ |
1311 | |
1312 | /* Store open upvalue in table for future references. */ |
1313 | LOCK(thread); |
1314 | - lua_pushlightuserdata(info->L, nuv); /* ... thread tbl upval */ |
1315 | - lua_rawseti(info->L, -2, 2); /* ... thread tbl */ |
1316 | lua_pop(info->L, 1); /* ... thread */ |
1317 | poppath(info); |
1318 | UNLOCK(thread); |
1319 | @@ -1996,7 +2114,7 @@ |
1320 | persist_typed(Info *info, int type) { /* perms reftbl ... obj */ |
1321 | eris_ifassert(const int top = lua_gettop(info->L)); |
1322 | if (info->level >= info->maxComplexity) { |
1323 | - eris_error(info, "object too complex"); |
1324 | + eris_error(info, ERIS_ERR_COMPLEXITY); |
1325 | } |
1326 | ++info->level; |
1327 | |
1328 | @@ -2033,7 +2151,7 @@ |
1329 | p_upval(info); |
1330 | break; |
1331 | default: |
1332 | - eris_error(info, "trying to persist unknown type"); |
1333 | + eris_error(info, ERIS_ERR_TYPEP, type); |
1334 | } /* perms reftbl ... obj */ |
1335 | |
1336 | --info->level; |
1337 | @@ -2130,13 +2248,14 @@ |
1338 | if (lua_isnil(info->L, -1)) { /* perms reftbl ... nil */ |
1339 | /* Since we may need permanent values to rebuild other structures, namely |
1340 | * closures and threads, we cannot allow perms to fail unpersisting. */ |
1341 | - eris_error(info, "bad permanent value (no value)"); |
1342 | + eris_error(info, ERIS_ERR_SPER_UPERMNIL); |
1343 | } |
1344 | else if (lua_type(info->L, -1) != type) { /* perms reftbl ... :( */ |
1345 | /* For the same reason that we cannot allow nil we must also require the |
1346 | * unpersisted value to be of the correct type. */ |
1347 | - eris_error(info, "bad permanent value (%s expected, got %s)", |
1348 | - kTypenames[type], kTypenames[lua_type(info->L, -1)]); |
1349 | + const char *want = kTypenames[type]; |
1350 | + const char *have = kTypenames[lua_type(info->L, -1)]; |
1351 | + eris_error(info, ERIS_ERR_SPER_UPERM, want, have); |
1352 | } /* perms reftbl ... obj */ |
1353 | /* Create the entry in the reftable. */ |
1354 | lua_pushvalue(info->L, -1); /* perms reftbl ... obj obj */ |
1355 | @@ -2147,7 +2266,7 @@ |
1356 | unpersist(Info *info) { /* perms reftbl ... */ |
1357 | eris_ifassert(const int top = lua_gettop(info->L)); |
1358 | if (info->level >= info->maxComplexity) { |
1359 | - eris_error(info, "object too complex"); |
1360 | + eris_error(info, ERIS_ERR_COMPLEXITY); |
1361 | } |
1362 | ++info->level; |
1363 | |
1364 | @@ -2158,7 +2277,7 @@ |
1365 | const int reference = typeOrReference - ERIS_REFERENCE_OFFSET; |
1366 | lua_rawgeti(info->L, REFTIDX, reference); /* perms reftbl ud ... obj? */ |
1367 | if (lua_isnil(info->L, -1)) { /* perms reftbl ud ... :( */ |
1368 | - eris_error(info, "invalid reference #%d", reference); |
1369 | + eris_error(info, ERIS_ERR_REF, reference); |
1370 | } /* perms reftbl ud ... obj */ |
1371 | } |
1372 | else { |
1373 | @@ -2201,7 +2320,7 @@ |
1374 | u_permanent(info); |
1375 | break; |
1376 | default: |
1377 | - eris_error(info, "trying to unpersist unknown type %d", type); |
1378 | + eris_error(info, ERIS_ERR_TYPEU, type); |
1379 | } /* perms reftbl ... obj? */ |
1380 | } |
1381 | } |
1382 | @@ -2289,6 +2408,7 @@ |
1383 | WRITE_RAW(kHeader, HEADER_LENGTH); |
1384 | WRITE_VALUE(sizeof(lua_Number), uint8_t); |
1385 | WRITE_VALUE(kHeaderNumber, lua_Number); |
1386 | + WRITE_VALUE(sizeof(lua_Integer), uint8_t); |
1387 | WRITE_VALUE(sizeof(int), uint8_t); |
1388 | WRITE_VALUE(sizeof(size_t), uint8_t); |
1389 | } |
1390 | @@ -2317,6 +2437,9 @@ |
1391 | if (READ_VALUE(lua_Number) != kHeaderNumber) { |
1392 | luaL_error(info->L, "incompatible floating point representation"); |
1393 | } |
1394 | + if (READ_VALUE(uint8_t) != sizeof(lua_Integer)) { |
1395 | + luaL_error(info->L, "incompatible integer type"); |
1396 | + } |
1397 | info->u.upi.sizeof_int = READ_VALUE(uint8_t); |
1398 | info->u.upi.sizeof_size_t = READ_VALUE(uint8_t); |
1399 | } |
1400 | @@ -2339,7 +2462,7 @@ |
1401 | |
1402 | if (get_setting(L, (void*)&kSettingMaxComplexity)) { |
1403 | /* perms buff rootobj value */ |
1404 | - info.maxComplexity = lua_tounsigned(L, -1); |
1405 | + info.maxComplexity = lua_tointeger(L, -1); |
1406 | lua_pop(L, 1); /* perms buff rootobj */ |
1407 | } |
1408 | if (get_setting(L, (void*)&kSettingGeneratePath)) { |
1409 | @@ -2399,7 +2522,7 @@ |
1410 | |
1411 | if (get_setting(L, (void*)&kSettingMaxComplexity)) { |
1412 | /* perms buff rootobj value */ |
1413 | - info.maxComplexity = lua_tounsigned(L, -1); |
1414 | + info.maxComplexity = lua_tointeger(L, -1); |
1415 | lua_pop(L, 1); /* perms buff rootobj */ |
1416 | } |
1417 | if (get_setting(L, (void*)&kSettingGeneratePath)) { |
1418 | @@ -2533,7 +2656,7 @@ |
1419 | } |
1420 | else if (IS(kSettingMaxComplexity)) { |
1421 | if (!get_setting(L, (void*)&kSettingMaxComplexity)) { |
1422 | - lua_pushunsigned(L, kMaxComplexity); |
1423 | + lua_pushinteger(L, kMaxComplexity); |
1424 | } |
1425 | } |
1426 | else { |
1427 | @@ -2561,7 +2684,7 @@ |
1428 | set_setting(L, (void*)&kSettingGeneratePath); |
1429 | } |
1430 | else if (IS(kSettingMaxComplexity)) { |
1431 | - luaL_optunsigned(L, 2, 0); |
1432 | + luaL_optinteger(L, 2, 0); |
1433 | set_setting(L, (void*)&kSettingMaxComplexity); |
1434 | } |
1435 | else { |
1436 | @@ -2621,6 +2744,8 @@ |
1437 | |
1438 | LUA_API void |
1439 | eris_persist(lua_State *L, int perms, int value) { /* ...? */ |
1440 | + perms = lua_absindex(L, perms); |
1441 | + value = lua_absindex(L, value); |
1442 | eris_checkstack(L, 3); |
1443 | lua_pushcfunction(L, l_persist); /* ... l_persist */ |
1444 | lua_pushvalue(L, perms); /* ... l_persist perms */ |
1445 | @@ -2630,6 +2755,8 @@ |
1446 | |
1447 | LUA_API void |
1448 | eris_unpersist(lua_State *L, int perms, int value) { /* ... */ |
1449 | + perms = lua_absindex(L, perms); |
1450 | + value = lua_absindex(L, value); |
1451 | eris_checkstack(L, 3); |
1452 | lua_pushcfunction(L, l_unpersist); /* ... l_unpersist */ |
1453 | lua_pushvalue(L, perms); /* ... l_unpersist perms */ |
1454 | @@ -2647,6 +2774,7 @@ |
1455 | |
1456 | LUA_API void |
1457 | eris_set_setting(lua_State *L, const char *name, int value) { /* ... */ |
1458 | + value = lua_absindex(L, value); |
1459 | eris_checkstack(L, 3); |
1460 | lua_pushcfunction(L, l_settings); /* ... l_settings */ |
1461 | lua_pushstring(L, name); /* ... l_settings name */ |
1462 | |
1463 | === modified file 'src/third_party/eris/eris.h' |
1464 | --- src/third_party/eris/eris.h 2013-10-17 07:22:46 +0000 |
1465 | +++ src/third_party/eris/eris.h 2016-04-10 16:54:20 +0000 |
1466 | @@ -1,6 +1,6 @@ |
1467 | /* |
1468 | -Eris - Heavy-duty persistence for Lua 5.2.2 - Based on Pluto |
1469 | -Copyright (c) 2013 by Florian Nuecke. |
1470 | +Eris - Heavy-duty persistence for Lua 5.3.0 - Based on Pluto |
1471 | +Copyright (c) 2013-2015 by Florian Nuecke. |
1472 | |
1473 | Permission is hereby granted, free of charge, to any person obtaining a copy |
1474 | of this software and associated documentation files (the "Software"), to deal |
1475 | @@ -26,6 +26,11 @@ |
1476 | #ifndef ERIS_H |
1477 | #define ERIS_H |
1478 | |
1479 | +#define ERIS_VERSION_MAJOR "1" |
1480 | +#define ERIS_VERSION_MINOR "1" |
1481 | +#define ERIS_VERSION_NUM 101 |
1482 | +#define ERIS_VERSION_RELEASE "0" |
1483 | + |
1484 | /* |
1485 | ** ================================================================== |
1486 | ** API |
1487 | |
1488 | === modified file 'src/third_party/eris/lapi.c' |
1489 | --- src/third_party/eris/lapi.c 2014-02-22 14:47:28 +0000 |
1490 | +++ src/third_party/eris/lapi.c 2016-04-10 16:54:20 +0000 |
1491 | @@ -1,16 +1,18 @@ |
1492 | /* |
1493 | -** $Id: lapi.c,v 2.171.1.1 2013/04/12 18:48:47 roberto Exp $ |
1494 | +** $Id: lapi.c,v 2.244 2014/12/26 14:43:45 roberto Exp $ |
1495 | ** Lua API |
1496 | ** See Copyright Notice in lua.h |
1497 | */ |
1498 | |
1499 | +#define lapi_c |
1500 | +#define LUA_CORE |
1501 | + |
1502 | +#include "lprefix.h" |
1503 | + |
1504 | |
1505 | #include <stdarg.h> |
1506 | #include <string.h> |
1507 | |
1508 | -#define lapi_c |
1509 | -#define LUA_CORE |
1510 | - |
1511 | #include "lua.h" |
1512 | |
1513 | #include "lapi.h" |
1514 | @@ -43,32 +45,35 @@ |
1515 | /* test for pseudo index */ |
1516 | #define ispseudo(i) ((i) <= LUA_REGISTRYINDEX) |
1517 | |
1518 | +/* test for upvalue */ |
1519 | +#define isupvalue(i) ((i) < LUA_REGISTRYINDEX) |
1520 | + |
1521 | /* test for valid but not pseudo index */ |
1522 | #define isstackindex(i, o) (isvalid(o) && !ispseudo(i)) |
1523 | |
1524 | -#define api_checkvalidindex(L, o) api_check(L, isvalid(o), "invalid index") |
1525 | +#define api_checkvalidindex(o) api_check(isvalid(o), "invalid index") |
1526 | |
1527 | -#define api_checkstackindex(L, i, o) \ |
1528 | - api_check(L, isstackindex(i, o), "index not in the stack") |
1529 | +#define api_checkstackindex(i, o) \ |
1530 | + api_check(isstackindex(i, o), "index not in the stack") |
1531 | |
1532 | |
1533 | static TValue *index2addr (lua_State *L, int idx) { |
1534 | CallInfo *ci = L->ci; |
1535 | if (idx > 0) { |
1536 | TValue *o = ci->func + idx; |
1537 | - api_check(L, idx <= ci->top - (ci->func + 1), "unacceptable index"); |
1538 | + api_check(idx <= ci->top - (ci->func + 1), "unacceptable index"); |
1539 | if (o >= L->top) return NONVALIDVALUE; |
1540 | else return o; |
1541 | } |
1542 | else if (!ispseudo(idx)) { /* negative index */ |
1543 | - api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index"); |
1544 | + api_check(idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index"); |
1545 | return L->top + idx; |
1546 | } |
1547 | else if (idx == LUA_REGISTRYINDEX) |
1548 | return &G(L)->l_registry; |
1549 | else { /* upvalues */ |
1550 | idx = LUA_REGISTRYINDEX - idx; |
1551 | - api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large"); |
1552 | + api_check(idx <= MAXUPVAL + 1, "upvalue index too large"); |
1553 | if (ttislcf(ci->func)) /* light C function? */ |
1554 | return NONVALIDVALUE; /* it has no upvalues */ |
1555 | else { |
1556 | @@ -89,21 +94,22 @@ |
1557 | } |
1558 | |
1559 | |
1560 | -LUA_API int lua_checkstack (lua_State *L, int size) { |
1561 | +LUA_API int lua_checkstack (lua_State *L, int n) { |
1562 | int res; |
1563 | CallInfo *ci = L->ci; |
1564 | lua_lock(L); |
1565 | - if (L->stack_last - L->top > size) /* stack large enough? */ |
1566 | + api_check(n >= 0, "negative 'n'"); |
1567 | + if (L->stack_last - L->top > n) /* stack large enough? */ |
1568 | res = 1; /* yes; check is OK */ |
1569 | else { /* no; need to grow stack */ |
1570 | int inuse = cast_int(L->top - L->stack) + EXTRA_STACK; |
1571 | - if (inuse > LUAI_MAXSTACK - size) /* can grow without overflow? */ |
1572 | + if (inuse > LUAI_MAXSTACK - n) /* can grow without overflow? */ |
1573 | res = 0; /* no */ |
1574 | else /* try to grow stack */ |
1575 | - res = (luaD_rawrunprotected(L, &growstack, &size) == LUA_OK); |
1576 | + res = (luaD_rawrunprotected(L, &growstack, &n) == LUA_OK); |
1577 | } |
1578 | - if (res && ci->top < L->top + size) |
1579 | - ci->top = L->top + size; /* adjust frame top */ |
1580 | + if (res && ci->top < L->top + n) |
1581 | + ci->top = L->top + n; /* adjust frame top */ |
1582 | lua_unlock(L); |
1583 | return res; |
1584 | } |
1585 | @@ -114,8 +120,8 @@ |
1586 | if (from == to) return; |
1587 | lua_lock(to); |
1588 | api_checknelems(from, n); |
1589 | - api_check(from, G(from) == G(to), "moving among independent states"); |
1590 | - api_check(from, to->ci->top - to->top >= n, "not enough elements to move"); |
1591 | + api_check(G(from) == G(to), "moving among independent states"); |
1592 | + api_check(to->ci->top - to->top >= n, "not enough elements to move"); |
1593 | from->top -= n; |
1594 | for (i = 0; i < n; i++) { |
1595 | setobj2s(to, to->top++, from->top + i); |
1596 | @@ -166,68 +172,63 @@ |
1597 | StkId func = L->ci->func; |
1598 | lua_lock(L); |
1599 | if (idx >= 0) { |
1600 | - api_check(L, idx <= L->stack_last - (func + 1), "new top too large"); |
1601 | + api_check(idx <= L->stack_last - (func + 1), "new top too large"); |
1602 | while (L->top < (func + 1) + idx) |
1603 | setnilvalue(L->top++); |
1604 | L->top = (func + 1) + idx; |
1605 | } |
1606 | else { |
1607 | - api_check(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top"); |
1608 | - L->top += idx+1; /* `subtract' index (index is negative) */ |
1609 | - } |
1610 | - lua_unlock(L); |
1611 | -} |
1612 | - |
1613 | - |
1614 | -LUA_API void lua_remove (lua_State *L, int idx) { |
1615 | - StkId p; |
1616 | - lua_lock(L); |
1617 | - p = index2addr(L, idx); |
1618 | - api_checkstackindex(L, idx, p); |
1619 | - while (++p < L->top) setobjs2s(L, p-1, p); |
1620 | - L->top--; |
1621 | - lua_unlock(L); |
1622 | -} |
1623 | - |
1624 | - |
1625 | -LUA_API void lua_insert (lua_State *L, int idx) { |
1626 | - StkId p; |
1627 | - StkId q; |
1628 | - lua_lock(L); |
1629 | - p = index2addr(L, idx); |
1630 | - api_checkstackindex(L, idx, p); |
1631 | - for (q = L->top; q > p; q--) /* use L->top as a temporary */ |
1632 | - setobjs2s(L, q, q - 1); |
1633 | - setobjs2s(L, p, L->top); |
1634 | - lua_unlock(L); |
1635 | -} |
1636 | - |
1637 | - |
1638 | -static void moveto (lua_State *L, TValue *fr, int idx) { |
1639 | - TValue *to = index2addr(L, idx); |
1640 | - api_checkvalidindex(L, to); |
1641 | + api_check(-(idx+1) <= (L->top - (func + 1)), "invalid new top"); |
1642 | + L->top += idx+1; /* 'subtract' index (index is negative) */ |
1643 | + } |
1644 | + lua_unlock(L); |
1645 | +} |
1646 | + |
1647 | + |
1648 | +/* |
1649 | +** Reverse the stack segment from 'from' to 'to' |
1650 | +** (auxiliary to 'lua_rotate') |
1651 | +*/ |
1652 | +static void reverse (lua_State *L, StkId from, StkId to) { |
1653 | + for (; from < to; from++, to--) { |
1654 | + TValue temp; |
1655 | + setobj(L, &temp, from); |
1656 | + setobjs2s(L, from, to); |
1657 | + setobj2s(L, to, &temp); |
1658 | + } |
1659 | +} |
1660 | + |
1661 | + |
1662 | +/* |
1663 | +** Let x = AB, where A is a prefix of length 'n'. Then, |
1664 | +** rotate x n == BA. But BA == (A^r . B^r)^r. |
1665 | +*/ |
1666 | +LUA_API void lua_rotate (lua_State *L, int idx, int n) { |
1667 | + StkId p, t, m; |
1668 | + lua_lock(L); |
1669 | + t = L->top - 1; /* end of stack segment being rotated */ |
1670 | + p = index2addr(L, idx); /* start of segment */ |
1671 | + api_checkstackindex(idx, p); |
1672 | + api_check((n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'"); |
1673 | + m = (n >= 0 ? t - n : p - n - 1); /* end of prefix */ |
1674 | + reverse(L, p, m); /* reverse the prefix with length 'n' */ |
1675 | + reverse(L, m + 1, t); /* reverse the suffix */ |
1676 | + reverse(L, p, t); /* reverse the entire segment */ |
1677 | + lua_unlock(L); |
1678 | +} |
1679 | + |
1680 | + |
1681 | +LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) { |
1682 | + TValue *fr, *to; |
1683 | + lua_lock(L); |
1684 | + fr = index2addr(L, fromidx); |
1685 | + to = index2addr(L, toidx); |
1686 | + api_checkvalidindex(to); |
1687 | setobj(L, to, fr); |
1688 | - if (idx < LUA_REGISTRYINDEX) /* function upvalue? */ |
1689 | + if (isupvalue(toidx)) /* function upvalue? */ |
1690 | luaC_barrier(L, clCvalue(L->ci->func), fr); |
1691 | /* LUA_REGISTRYINDEX does not need gc barrier |
1692 | (collector revisits it before finishing collection) */ |
1693 | -} |
1694 | - |
1695 | - |
1696 | -LUA_API void lua_replace (lua_State *L, int idx) { |
1697 | - lua_lock(L); |
1698 | - api_checknelems(L, 1); |
1699 | - moveto(L, L->top - 1, idx); |
1700 | - L->top--; |
1701 | - lua_unlock(L); |
1702 | -} |
1703 | - |
1704 | - |
1705 | -LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) { |
1706 | - TValue *fr; |
1707 | - lua_lock(L); |
1708 | - fr = index2addr(L, fromidx); |
1709 | - moveto(L, fr, toidx); |
1710 | lua_unlock(L); |
1711 | } |
1712 | |
1713 | @@ -248,12 +249,13 @@ |
1714 | |
1715 | LUA_API int lua_type (lua_State *L, int idx) { |
1716 | StkId o = index2addr(L, idx); |
1717 | - return (isvalid(o) ? ttypenv(o) : LUA_TNONE); |
1718 | + return (isvalid(o) ? ttnov(o) : LUA_TNONE); |
1719 | } |
1720 | |
1721 | |
1722 | LUA_API const char *lua_typename (lua_State *L, int t) { |
1723 | UNUSED(L); |
1724 | + api_check(LUA_TNONE <= t && t < LUA_NUMTAGS, "invalid tag"); |
1725 | return ttypename(t); |
1726 | } |
1727 | |
1728 | @@ -264,22 +266,28 @@ |
1729 | } |
1730 | |
1731 | |
1732 | +LUA_API int lua_isinteger (lua_State *L, int idx) { |
1733 | + StkId o = index2addr(L, idx); |
1734 | + return ttisinteger(o); |
1735 | +} |
1736 | + |
1737 | + |
1738 | LUA_API int lua_isnumber (lua_State *L, int idx) { |
1739 | - TValue n; |
1740 | + lua_Number n; |
1741 | const TValue *o = index2addr(L, idx); |
1742 | return tonumber(o, &n); |
1743 | } |
1744 | |
1745 | |
1746 | LUA_API int lua_isstring (lua_State *L, int idx) { |
1747 | - int t = lua_type(L, idx); |
1748 | - return (t == LUA_TSTRING || t == LUA_TNUMBER); |
1749 | + const TValue *o = index2addr(L, idx); |
1750 | + return (ttisstring(o) || cvt2str(o)); |
1751 | } |
1752 | |
1753 | |
1754 | LUA_API int lua_isuserdata (lua_State *L, int idx) { |
1755 | const TValue *o = index2addr(L, idx); |
1756 | - return (ttisuserdata(o) || ttislightuserdata(o)); |
1757 | + return (ttisfulluserdata(o) || ttislightuserdata(o)); |
1758 | } |
1759 | |
1760 | |
1761 | @@ -291,24 +299,17 @@ |
1762 | |
1763 | |
1764 | LUA_API void lua_arith (lua_State *L, int op) { |
1765 | - StkId o1; /* 1st operand */ |
1766 | - StkId o2; /* 2nd operand */ |
1767 | lua_lock(L); |
1768 | - if (op != LUA_OPUNM) /* all other operations expect two operands */ |
1769 | - api_checknelems(L, 2); |
1770 | - else { /* for unary minus, add fake 2nd operand */ |
1771 | + if (op != LUA_OPUNM && op != LUA_OPBNOT) |
1772 | + api_checknelems(L, 2); /* all other operations expect two operands */ |
1773 | + else { /* for unary operations, add fake 2nd operand */ |
1774 | api_checknelems(L, 1); |
1775 | setobjs2s(L, L->top, L->top - 1); |
1776 | L->top++; |
1777 | } |
1778 | - o1 = L->top - 2; |
1779 | - o2 = L->top - 1; |
1780 | - if (ttisnumber(o1) && ttisnumber(o2)) { |
1781 | - setnvalue(o1, luaO_arith(op, nvalue(o1), nvalue(o2))); |
1782 | - } |
1783 | - else |
1784 | - luaV_arith(L, o1, o1, o2, cast(TMS, op - LUA_OPADD + TM_ADD)); |
1785 | - L->top--; |
1786 | + /* first operand at top - 2, second at top - 1; result go to top - 2 */ |
1787 | + luaO_arith(L, op, L->top - 2, L->top - 1, L->top - 2); |
1788 | + L->top--; /* remove second operand */ |
1789 | lua_unlock(L); |
1790 | } |
1791 | |
1792 | @@ -321,10 +322,10 @@ |
1793 | o2 = index2addr(L, index2); |
1794 | if (isvalid(o1) && isvalid(o2)) { |
1795 | switch (op) { |
1796 | - case LUA_OPEQ: i = equalobj(L, o1, o2); break; |
1797 | + case LUA_OPEQ: i = luaV_equalobj(L, o1, o2); break; |
1798 | case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break; |
1799 | case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break; |
1800 | - default: api_check(L, 0, "invalid option"); |
1801 | + default: api_check(0, "invalid option"); |
1802 | } |
1803 | } |
1804 | lua_unlock(L); |
1805 | @@ -332,51 +333,33 @@ |
1806 | } |
1807 | |
1808 | |
1809 | -LUA_API lua_Number lua_tonumberx (lua_State *L, int idx, int *isnum) { |
1810 | - TValue n; |
1811 | - const TValue *o = index2addr(L, idx); |
1812 | - if (tonumber(o, &n)) { |
1813 | - if (isnum) *isnum = 1; |
1814 | - return nvalue(o); |
1815 | - } |
1816 | - else { |
1817 | - if (isnum) *isnum = 0; |
1818 | - return 0; |
1819 | - } |
1820 | -} |
1821 | - |
1822 | - |
1823 | -LUA_API lua_Integer lua_tointegerx (lua_State *L, int idx, int *isnum) { |
1824 | - TValue n; |
1825 | - const TValue *o = index2addr(L, idx); |
1826 | - if (tonumber(o, &n)) { |
1827 | - lua_Integer res; |
1828 | - lua_Number num = nvalue(o); |
1829 | - lua_number2integer(res, num); |
1830 | - if (isnum) *isnum = 1; |
1831 | - return res; |
1832 | - } |
1833 | - else { |
1834 | - if (isnum) *isnum = 0; |
1835 | - return 0; |
1836 | - } |
1837 | -} |
1838 | - |
1839 | - |
1840 | -LUA_API lua_Unsigned lua_tounsignedx (lua_State *L, int idx, int *isnum) { |
1841 | - TValue n; |
1842 | - const TValue *o = index2addr(L, idx); |
1843 | - if (tonumber(o, &n)) { |
1844 | - lua_Unsigned res; |
1845 | - lua_Number num = nvalue(o); |
1846 | - lua_number2unsigned(res, num); |
1847 | - if (isnum) *isnum = 1; |
1848 | - return res; |
1849 | - } |
1850 | - else { |
1851 | - if (isnum) *isnum = 0; |
1852 | - return 0; |
1853 | - } |
1854 | +LUA_API size_t lua_stringtonumber (lua_State *L, const char *s) { |
1855 | + size_t sz = luaO_str2num(s, L->top); |
1856 | + if (sz != 0) |
1857 | + api_incr_top(L); |
1858 | + return sz; |
1859 | +} |
1860 | + |
1861 | + |
1862 | +LUA_API lua_Number lua_tonumberx (lua_State *L, int idx, int *pisnum) { |
1863 | + lua_Number n; |
1864 | + const TValue *o = index2addr(L, idx); |
1865 | + int isnum = tonumber(o, &n); |
1866 | + if (!isnum) |
1867 | + n = 0; /* call to 'tonumber' may change 'n' even if it fails */ |
1868 | + if (pisnum) *pisnum = isnum; |
1869 | + return n; |
1870 | +} |
1871 | + |
1872 | + |
1873 | +LUA_API lua_Integer lua_tointegerx (lua_State *L, int idx, int *pisnum) { |
1874 | + lua_Integer res; |
1875 | + const TValue *o = index2addr(L, idx); |
1876 | + int isnum = tointeger(o, &res); |
1877 | + if (!isnum) |
1878 | + res = 0; /* call to 'tointeger' may change 'n' even if it fails */ |
1879 | + if (pisnum) *pisnum = isnum; |
1880 | + return res; |
1881 | } |
1882 | |
1883 | |
1884 | @@ -389,14 +372,14 @@ |
1885 | LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { |
1886 | StkId o = index2addr(L, idx); |
1887 | if (!ttisstring(o)) { |
1888 | - lua_lock(L); /* `luaV_tostring' may create a new string */ |
1889 | - if (!luaV_tostring(L, o)) { /* conversion failed? */ |
1890 | + if (!cvt2str(o)) { /* not convertible? */ |
1891 | if (len != NULL) *len = 0; |
1892 | - lua_unlock(L); |
1893 | return NULL; |
1894 | } |
1895 | + lua_lock(L); /* 'luaO_tostring' may create a new string */ |
1896 | luaC_checkGC(L); |
1897 | o = index2addr(L, idx); /* previous call may reallocate the stack */ |
1898 | + luaO_tostring(L, o); |
1899 | lua_unlock(L); |
1900 | } |
1901 | if (len != NULL) *len = tsvalue(o)->len; |
1902 | @@ -406,7 +389,7 @@ |
1903 | |
1904 | LUA_API size_t lua_rawlen (lua_State *L, int idx) { |
1905 | StkId o = index2addr(L, idx); |
1906 | - switch (ttypenv(o)) { |
1907 | + switch (ttnov(o)) { |
1908 | case LUA_TSTRING: return tsvalue(o)->len; |
1909 | case LUA_TUSERDATA: return uvalue(o)->len; |
1910 | case LUA_TTABLE: return luaH_getn(hvalue(o)); |
1911 | @@ -426,8 +409,8 @@ |
1912 | |
1913 | LUA_API void *lua_touserdata (lua_State *L, int idx) { |
1914 | StkId o = index2addr(L, idx); |
1915 | - switch (ttypenv(o)) { |
1916 | - case LUA_TUSERDATA: return (rawuvalue(o) + 1); |
1917 | + switch (ttnov(o)) { |
1918 | + case LUA_TUSERDATA: return getudatamem(uvalue(o)); |
1919 | case LUA_TLIGHTUSERDATA: return pvalue(o); |
1920 | default: return NULL; |
1921 | } |
1922 | @@ -472,9 +455,7 @@ |
1923 | |
1924 | LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { |
1925 | lua_lock(L); |
1926 | - setnvalue(L->top, n); |
1927 | - luai_checknum(L, L->top, |
1928 | - luaG_runerror(L, "C API - attempt to push a signaling NaN")); |
1929 | + setfltvalue(L->top, n); |
1930 | api_incr_top(L); |
1931 | lua_unlock(L); |
1932 | } |
1933 | @@ -482,17 +463,7 @@ |
1934 | |
1935 | LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { |
1936 | lua_lock(L); |
1937 | - setnvalue(L->top, cast_num(n)); |
1938 | - api_incr_top(L); |
1939 | - lua_unlock(L); |
1940 | -} |
1941 | - |
1942 | - |
1943 | -LUA_API void lua_pushunsigned (lua_State *L, lua_Unsigned u) { |
1944 | - lua_Number n; |
1945 | - lua_lock(L); |
1946 | - n = lua_unsigned2number(u); |
1947 | - setnvalue(L->top, n); |
1948 | + setivalue(L->top, n); |
1949 | api_incr_top(L); |
1950 | lua_unlock(L); |
1951 | } |
1952 | @@ -558,15 +529,17 @@ |
1953 | setfvalue(L->top, fn); |
1954 | } |
1955 | else { |
1956 | - Closure *cl; |
1957 | + CClosure *cl; |
1958 | api_checknelems(L, n); |
1959 | - api_check(L, n <= MAXUPVAL, "upvalue index too large"); |
1960 | + api_check(n <= MAXUPVAL, "upvalue index too large"); |
1961 | luaC_checkGC(L); |
1962 | cl = luaF_newCclosure(L, n); |
1963 | - cl->c.f = fn; |
1964 | + cl->f = fn; |
1965 | L->top -= n; |
1966 | - while (n--) |
1967 | - setobj2n(L, &cl->c.upvalue[n], L->top + n); |
1968 | + while (n--) { |
1969 | + setobj2n(L, &cl->upvalue[n], L->top + n); |
1970 | + /* does not need barrier because closure is white */ |
1971 | + } |
1972 | setclCvalue(L, L->top, cl); |
1973 | } |
1974 | api_incr_top(L); |
1975 | @@ -605,27 +578,29 @@ |
1976 | */ |
1977 | |
1978 | |
1979 | -LUA_API void lua_getglobal (lua_State *L, const char *var) { |
1980 | +LUA_API int lua_getglobal (lua_State *L, const char *name) { |
1981 | Table *reg = hvalue(&G(L)->l_registry); |
1982 | const TValue *gt; /* global table */ |
1983 | lua_lock(L); |
1984 | gt = luaH_getint(reg, LUA_RIDX_GLOBALS); |
1985 | - setsvalue2s(L, L->top++, luaS_new(L, var)); |
1986 | + setsvalue2s(L, L->top++, luaS_new(L, name)); |
1987 | luaV_gettable(L, gt, L->top - 1, L->top - 1); |
1988 | lua_unlock(L); |
1989 | + return ttnov(L->top - 1); |
1990 | } |
1991 | |
1992 | |
1993 | -LUA_API void lua_gettable (lua_State *L, int idx) { |
1994 | +LUA_API int lua_gettable (lua_State *L, int idx) { |
1995 | StkId t; |
1996 | lua_lock(L); |
1997 | t = index2addr(L, idx); |
1998 | luaV_gettable(L, t, L->top - 1, L->top - 1); |
1999 | lua_unlock(L); |
2000 | + return ttnov(L->top - 1); |
2001 | } |
2002 | |
2003 | |
2004 | -LUA_API void lua_getfield (lua_State *L, int idx, const char *k) { |
2005 | +LUA_API int lua_getfield (lua_State *L, int idx, const char *k) { |
2006 | StkId t; |
2007 | lua_lock(L); |
2008 | t = index2addr(L, idx); |
2009 | @@ -633,40 +608,56 @@ |
2010 | api_incr_top(L); |
2011 | luaV_gettable(L, t, L->top - 1, L->top - 1); |
2012 | lua_unlock(L); |
2013 | -} |
2014 | - |
2015 | - |
2016 | -LUA_API void lua_rawget (lua_State *L, int idx) { |
2017 | - StkId t; |
2018 | - lua_lock(L); |
2019 | - t = index2addr(L, idx); |
2020 | - api_check(L, ttistable(t), "table expected"); |
2021 | + return ttnov(L->top - 1); |
2022 | +} |
2023 | + |
2024 | + |
2025 | +LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) { |
2026 | + StkId t; |
2027 | + lua_lock(L); |
2028 | + t = index2addr(L, idx); |
2029 | + setivalue(L->top, n); |
2030 | + api_incr_top(L); |
2031 | + luaV_gettable(L, t, L->top - 1, L->top - 1); |
2032 | + lua_unlock(L); |
2033 | + return ttnov(L->top - 1); |
2034 | +} |
2035 | + |
2036 | + |
2037 | +LUA_API int lua_rawget (lua_State *L, int idx) { |
2038 | + StkId t; |
2039 | + lua_lock(L); |
2040 | + t = index2addr(L, idx); |
2041 | + api_check(ttistable(t), "table expected"); |
2042 | setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1)); |
2043 | lua_unlock(L); |
2044 | + return ttnov(L->top - 1); |
2045 | } |
2046 | |
2047 | |
2048 | -LUA_API void lua_rawgeti (lua_State *L, int idx, int n) { |
2049 | +LUA_API int lua_rawgeti (lua_State *L, int idx, lua_Integer n) { |
2050 | StkId t; |
2051 | lua_lock(L); |
2052 | t = index2addr(L, idx); |
2053 | - api_check(L, ttistable(t), "table expected"); |
2054 | + api_check(ttistable(t), "table expected"); |
2055 | setobj2s(L, L->top, luaH_getint(hvalue(t), n)); |
2056 | api_incr_top(L); |
2057 | lua_unlock(L); |
2058 | + return ttnov(L->top - 1); |
2059 | } |
2060 | |
2061 | |
2062 | -LUA_API void lua_rawgetp (lua_State *L, int idx, const void *p) { |
2063 | +LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) { |
2064 | StkId t; |
2065 | TValue k; |
2066 | lua_lock(L); |
2067 | t = index2addr(L, idx); |
2068 | - api_check(L, ttistable(t), "table expected"); |
2069 | + api_check(ttistable(t), "table expected"); |
2070 | setpvalue(&k, cast(void *, p)); |
2071 | setobj2s(L, L->top, luaH_get(hvalue(t), &k)); |
2072 | api_incr_top(L); |
2073 | lua_unlock(L); |
2074 | + return ttnov(L->top - 1); |
2075 | } |
2076 | |
2077 | |
2078 | @@ -685,11 +676,11 @@ |
2079 | |
2080 | LUA_API int lua_getmetatable (lua_State *L, int objindex) { |
2081 | const TValue *obj; |
2082 | - Table *mt = NULL; |
2083 | - int res; |
2084 | + Table *mt; |
2085 | + int res = 0; |
2086 | lua_lock(L); |
2087 | obj = index2addr(L, objindex); |
2088 | - switch (ttypenv(obj)) { |
2089 | + switch (ttnov(obj)) { |
2090 | case LUA_TTABLE: |
2091 | mt = hvalue(obj)->metatable; |
2092 | break; |
2093 | @@ -697,12 +688,10 @@ |
2094 | mt = uvalue(obj)->metatable; |
2095 | break; |
2096 | default: |
2097 | - mt = G(L)->mt[ttypenv(obj)]; |
2098 | + mt = G(L)->mt[ttnov(obj)]; |
2099 | break; |
2100 | } |
2101 | - if (mt == NULL) |
2102 | - res = 0; |
2103 | - else { |
2104 | + if (mt != NULL) { |
2105 | sethvalue(L, L->top, mt); |
2106 | api_incr_top(L); |
2107 | res = 1; |
2108 | @@ -712,17 +701,15 @@ |
2109 | } |
2110 | |
2111 | |
2112 | -LUA_API void lua_getuservalue (lua_State *L, int idx) { |
2113 | +LUA_API int lua_getuservalue (lua_State *L, int idx) { |
2114 | StkId o; |
2115 | lua_lock(L); |
2116 | o = index2addr(L, idx); |
2117 | - api_check(L, ttisuserdata(o), "userdata expected"); |
2118 | - if (uvalue(o)->env) { |
2119 | - sethvalue(L, L->top, uvalue(o)->env); |
2120 | - } else |
2121 | - setnilvalue(L->top); |
2122 | + api_check(ttisfulluserdata(o), "full userdata expected"); |
2123 | + getuservalue(L, uvalue(o), L->top); |
2124 | api_incr_top(L); |
2125 | lua_unlock(L); |
2126 | + return ttnov(L->top - 1); |
2127 | } |
2128 | |
2129 | |
2130 | @@ -731,13 +718,13 @@ |
2131 | */ |
2132 | |
2133 | |
2134 | -LUA_API void lua_setglobal (lua_State *L, const char *var) { |
2135 | +LUA_API void lua_setglobal (lua_State *L, const char *name) { |
2136 | Table *reg = hvalue(&G(L)->l_registry); |
2137 | const TValue *gt; /* global table */ |
2138 | lua_lock(L); |
2139 | api_checknelems(L, 1); |
2140 | gt = luaH_getint(reg, LUA_RIDX_GLOBALS); |
2141 | - setsvalue2s(L, L->top++, luaS_new(L, var)); |
2142 | + setsvalue2s(L, L->top++, luaS_new(L, name)); |
2143 | luaV_settable(L, gt, L->top - 1, L->top - 2); |
2144 | L->top -= 2; /* pop value and key */ |
2145 | lua_unlock(L); |
2146 | @@ -767,43 +754,61 @@ |
2147 | } |
2148 | |
2149 | |
2150 | +LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) { |
2151 | + StkId t; |
2152 | + lua_lock(L); |
2153 | + api_checknelems(L, 1); |
2154 | + t = index2addr(L, idx); |
2155 | + setivalue(L->top++, n); |
2156 | + luaV_settable(L, t, L->top - 1, L->top - 2); |
2157 | + L->top -= 2; /* pop value and key */ |
2158 | + lua_unlock(L); |
2159 | +} |
2160 | + |
2161 | + |
2162 | LUA_API void lua_rawset (lua_State *L, int idx) { |
2163 | - StkId t; |
2164 | + StkId o; |
2165 | + Table *t; |
2166 | lua_lock(L); |
2167 | api_checknelems(L, 2); |
2168 | - t = index2addr(L, idx); |
2169 | - api_check(L, ttistable(t), "table expected"); |
2170 | - setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1); |
2171 | - invalidateTMcache(hvalue(t)); |
2172 | - luaC_barrierback(L, gcvalue(t), L->top-1); |
2173 | + o = index2addr(L, idx); |
2174 | + api_check(ttistable(o), "table expected"); |
2175 | + t = hvalue(o); |
2176 | + setobj2t(L, luaH_set(L, t, L->top-2), L->top-1); |
2177 | + invalidateTMcache(t); |
2178 | + luaC_barrierback(L, t, L->top-1); |
2179 | L->top -= 2; |
2180 | lua_unlock(L); |
2181 | } |
2182 | |
2183 | |
2184 | -LUA_API void lua_rawseti (lua_State *L, int idx, int n) { |
2185 | - StkId t; |
2186 | +LUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) { |
2187 | + StkId o; |
2188 | + Table *t; |
2189 | lua_lock(L); |
2190 | api_checknelems(L, 1); |
2191 | - t = index2addr(L, idx); |
2192 | - api_check(L, ttistable(t), "table expected"); |
2193 | - luaH_setint(L, hvalue(t), n, L->top - 1); |
2194 | - luaC_barrierback(L, gcvalue(t), L->top-1); |
2195 | + o = index2addr(L, idx); |
2196 | + api_check(ttistable(o), "table expected"); |
2197 | + t = hvalue(o); |
2198 | + luaH_setint(L, t, n, L->top - 1); |
2199 | + luaC_barrierback(L, t, L->top-1); |
2200 | L->top--; |
2201 | lua_unlock(L); |
2202 | } |
2203 | |
2204 | |
2205 | LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) { |
2206 | - StkId t; |
2207 | + StkId o; |
2208 | + Table *t; |
2209 | TValue k; |
2210 | lua_lock(L); |
2211 | api_checknelems(L, 1); |
2212 | - t = index2addr(L, idx); |
2213 | - api_check(L, ttistable(t), "table expected"); |
2214 | + o = index2addr(L, idx); |
2215 | + api_check(ttistable(o), "table expected"); |
2216 | + t = hvalue(o); |
2217 | setpvalue(&k, cast(void *, p)); |
2218 | - setobj2t(L, luaH_set(L, hvalue(t), &k), L->top - 1); |
2219 | - luaC_barrierback(L, gcvalue(t), L->top - 1); |
2220 | + setobj2t(L, luaH_set(L, t, &k), L->top - 1); |
2221 | + luaC_barrierback(L, t, L->top - 1); |
2222 | L->top--; |
2223 | lua_unlock(L); |
2224 | } |
2225 | @@ -818,14 +823,14 @@ |
2226 | if (ttisnil(L->top - 1)) |
2227 | mt = NULL; |
2228 | else { |
2229 | - api_check(L, ttistable(L->top - 1), "table expected"); |
2230 | + api_check(ttistable(L->top - 1), "table expected"); |
2231 | mt = hvalue(L->top - 1); |
2232 | } |
2233 | - switch (ttypenv(obj)) { |
2234 | + switch (ttnov(obj)) { |
2235 | case LUA_TTABLE: { |
2236 | hvalue(obj)->metatable = mt; |
2237 | if (mt) { |
2238 | - luaC_objbarrierback(L, gcvalue(obj), mt); |
2239 | + luaC_objbarrier(L, gcvalue(obj), mt); |
2240 | luaC_checkfinalizer(L, gcvalue(obj), mt); |
2241 | } |
2242 | break; |
2243 | @@ -833,13 +838,13 @@ |
2244 | case LUA_TUSERDATA: { |
2245 | uvalue(obj)->metatable = mt; |
2246 | if (mt) { |
2247 | - luaC_objbarrier(L, rawuvalue(obj), mt); |
2248 | + luaC_objbarrier(L, uvalue(obj), mt); |
2249 | luaC_checkfinalizer(L, gcvalue(obj), mt); |
2250 | } |
2251 | break; |
2252 | } |
2253 | default: { |
2254 | - G(L)->mt[ttypenv(obj)] = mt; |
2255 | + G(L)->mt[ttnov(obj)] = mt; |
2256 | break; |
2257 | } |
2258 | } |
2259 | @@ -854,46 +859,32 @@ |
2260 | lua_lock(L); |
2261 | api_checknelems(L, 1); |
2262 | o = index2addr(L, idx); |
2263 | - api_check(L, ttisuserdata(o), "userdata expected"); |
2264 | - if (ttisnil(L->top - 1)) |
2265 | - uvalue(o)->env = NULL; |
2266 | - else { |
2267 | - api_check(L, ttistable(L->top - 1), "table expected"); |
2268 | - uvalue(o)->env = hvalue(L->top - 1); |
2269 | - luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1)); |
2270 | - } |
2271 | + api_check(ttisfulluserdata(o), "full userdata expected"); |
2272 | + setuservalue(L, uvalue(o), L->top - 1); |
2273 | + luaC_barrier(L, gcvalue(o), L->top - 1); |
2274 | L->top--; |
2275 | lua_unlock(L); |
2276 | } |
2277 | |
2278 | |
2279 | /* |
2280 | -** `load' and `call' functions (run Lua code) |
2281 | +** 'load' and 'call' functions (run Lua code) |
2282 | */ |
2283 | |
2284 | |
2285 | #define checkresults(L,na,nr) \ |
2286 | - api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \ |
2287 | + api_check((nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \ |
2288 | "results from function overflow current stack size") |
2289 | |
2290 | |
2291 | -LUA_API int lua_getctx (lua_State *L, int *ctx) { |
2292 | - if (L->ci->callstatus & CIST_YIELDED) { |
2293 | - if (ctx) *ctx = L->ci->u.c.ctx; |
2294 | - return L->ci->u.c.status; |
2295 | - } |
2296 | - else return LUA_OK; |
2297 | -} |
2298 | - |
2299 | - |
2300 | -LUA_API void lua_callk (lua_State *L, int nargs, int nresults, int ctx, |
2301 | - lua_CFunction k) { |
2302 | +LUA_API void lua_callk (lua_State *L, int nargs, int nresults, |
2303 | + lua_KContext ctx, lua_KFunction k) { |
2304 | StkId func; |
2305 | lua_lock(L); |
2306 | - api_check(L, k == NULL || !isLua(L->ci), |
2307 | + api_check(k == NULL || !isLua(L->ci), |
2308 | "cannot use continuations inside hooks"); |
2309 | api_checknelems(L, nargs+1); |
2310 | - api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); |
2311 | + api_check(L->status == LUA_OK, "cannot do calls on non-normal thread"); |
2312 | checkresults(L, nargs, nresults); |
2313 | func = L->top - (nargs+1); |
2314 | if (k != NULL && L->nny == 0) { /* need to prepare continuation? */ |
2315 | @@ -912,7 +903,7 @@ |
2316 | /* |
2317 | ** Execute a protected call. |
2318 | */ |
2319 | -struct CallS { /* data to `f_call' */ |
2320 | +struct CallS { /* data to 'f_call' */ |
2321 | StkId func; |
2322 | int nresults; |
2323 | }; |
2324 | @@ -926,21 +917,21 @@ |
2325 | |
2326 | |
2327 | LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc, |
2328 | - int ctx, lua_CFunction k) { |
2329 | + lua_KContext ctx, lua_KFunction k) { |
2330 | struct CallS c; |
2331 | int status; |
2332 | ptrdiff_t func; |
2333 | lua_lock(L); |
2334 | - api_check(L, k == NULL || !isLua(L->ci), |
2335 | + api_check(k == NULL || !isLua(L->ci), |
2336 | "cannot use continuations inside hooks"); |
2337 | api_checknelems(L, nargs+1); |
2338 | - api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); |
2339 | + api_check(L->status == LUA_OK, "cannot do calls on non-normal thread"); |
2340 | checkresults(L, nargs, nresults); |
2341 | if (errfunc == 0) |
2342 | func = 0; |
2343 | else { |
2344 | StkId o = index2addr(L, errfunc); |
2345 | - api_checkstackindex(L, errfunc, o); |
2346 | + api_checkstackindex(errfunc, o); |
2347 | func = savestack(L, o); |
2348 | } |
2349 | c.func = L->top - (nargs+1); /* function to be called */ |
2350 | @@ -954,11 +945,10 @@ |
2351 | ci->u.c.ctx = ctx; /* save context */ |
2352 | /* save information for error recovery */ |
2353 | ci->extra = savestack(L, c.func); |
2354 | - ci->u.c.old_allowhook = L->allowhook; |
2355 | ci->u.c.old_errfunc = L->errfunc; |
2356 | L->errfunc = func; |
2357 | - /* mark that function may do error recovery */ |
2358 | - ci->callstatus |= CIST_YPCALL; |
2359 | + setoah(ci->callstatus, L->allowhook); /* save value of 'allowhook' */ |
2360 | + ci->callstatus |= CIST_YPCALL; /* function can do error recovery */ |
2361 | luaD_call(L, c.func, nresults, 1); /* do the call */ |
2362 | ci->callstatus &= ~CIST_YPCALL; |
2363 | L->errfunc = ci->u.c.old_errfunc; |
2364 | @@ -980,13 +970,13 @@ |
2365 | status = luaD_protectedparser(L, &z, chunkname, mode); |
2366 | if (status == LUA_OK) { /* no errors? */ |
2367 | LClosure *f = clLvalue(L->top - 1); /* get newly created function */ |
2368 | - if (f->nupvalues == 1) { /* does it have one upvalue? */ |
2369 | + if (f->nupvalues >= 1) { /* does it have an upvalue? */ |
2370 | /* get global table from registry */ |
2371 | Table *reg = hvalue(&G(L)->l_registry); |
2372 | const TValue *gt = luaH_getint(reg, LUA_RIDX_GLOBALS); |
2373 | /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */ |
2374 | setobj(L, f->upvals[0]->v, gt); |
2375 | - luaC_barrier(L, f->upvals[0], gt); |
2376 | + luaC_upvalbarrier(L, f->upvals[0]); |
2377 | } |
2378 | } |
2379 | lua_unlock(L); |
2380 | @@ -994,14 +984,14 @@ |
2381 | } |
2382 | |
2383 | |
2384 | -LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) { |
2385 | +LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data, int strip) { |
2386 | int status; |
2387 | TValue *o; |
2388 | lua_lock(L); |
2389 | api_checknelems(L, 1); |
2390 | o = L->top - 1; |
2391 | if (isLfunction(o)) |
2392 | - status = luaU_dump(L, getproto(o), writer, data, 0); |
2393 | + status = luaU_dump(L, getproto(o), writer, data, strip); |
2394 | else |
2395 | status = 1; |
2396 | lua_unlock(L); |
2397 | @@ -1047,19 +1037,21 @@ |
2398 | break; |
2399 | } |
2400 | case LUA_GCSTEP: { |
2401 | - if (g->gckind == KGC_GEN) { /* generational mode? */ |
2402 | - res = (g->GCestimate == 0); /* true if it will do major collection */ |
2403 | - luaC_forcestep(L); /* do a single step */ |
2404 | - } |
2405 | - else { |
2406 | - lu_mem debt = cast(lu_mem, data) * 1024 - GCSTEPSIZE; |
2407 | - if (g->gcrunning) |
2408 | - debt += g->GCdebt; /* include current debt */ |
2409 | - luaE_setdebt(g, debt); |
2410 | - luaC_forcestep(L); |
2411 | - if (g->gcstate == GCSpause) /* end of cycle? */ |
2412 | - res = 1; /* signal it */ |
2413 | - } |
2414 | + l_mem debt = 1; /* =1 to signal that it did an actual step */ |
2415 | + int oldrunning = g->gcrunning; |
2416 | + g->gcrunning = 1; /* allow GC to run */ |
2417 | + if (data == 0) { |
2418 | + luaE_setdebt(g, -GCSTEPSIZE); /* to do a "small" step */ |
2419 | + luaC_step(L); |
2420 | + } |
2421 | + else { /* add 'data' to total debt */ |
2422 | + debt = cast(l_mem, data) * 1024 + g->GCdebt; |
2423 | + luaE_setdebt(g, debt); |
2424 | + luaC_checkGC(L); |
2425 | + } |
2426 | + g->gcrunning = oldrunning; /* restore previous state */ |
2427 | + if (debt > 0 && g->gcstate == GCSpause) /* end of cycle? */ |
2428 | + res = 1; /* signal it */ |
2429 | break; |
2430 | } |
2431 | case LUA_GCSETPAUSE: { |
2432 | @@ -1067,13 +1059,9 @@ |
2433 | g->gcpause = data; |
2434 | break; |
2435 | } |
2436 | - case LUA_GCSETMAJORINC: { |
2437 | - res = g->gcmajorinc; |
2438 | - g->gcmajorinc = data; |
2439 | - break; |
2440 | - } |
2441 | case LUA_GCSETSTEPMUL: { |
2442 | res = g->gcstepmul; |
2443 | + if (data < 40) data = 40; /* avoid ridiculous low values (and 0) */ |
2444 | g->gcstepmul = data; |
2445 | break; |
2446 | } |
2447 | @@ -1081,14 +1069,6 @@ |
2448 | res = g->gcrunning; |
2449 | break; |
2450 | } |
2451 | - case LUA_GCGEN: { /* change collector to generational mode */ |
2452 | - luaC_changemode(L, KGC_GEN); |
2453 | - break; |
2454 | - } |
2455 | - case LUA_GCINC: { /* change collector to incremental mode */ |
2456 | - luaC_changemode(L, KGC_NORMAL); |
2457 | - break; |
2458 | - } |
2459 | default: res = -1; /* invalid option */ |
2460 | } |
2461 | lua_unlock(L); |
2462 | @@ -1116,7 +1096,7 @@ |
2463 | int more; |
2464 | lua_lock(L); |
2465 | t = index2addr(L, idx); |
2466 | - api_check(L, ttistable(t), "table expected"); |
2467 | + api_check(ttistable(t), "table expected"); |
2468 | more = luaH_next(L, hvalue(t), L->top - 1); |
2469 | if (more) { |
2470 | api_incr_top(L); |
2471 | @@ -1176,23 +1156,23 @@ |
2472 | Udata *u; |
2473 | lua_lock(L); |
2474 | luaC_checkGC(L); |
2475 | - u = luaS_newudata(L, size, NULL); |
2476 | + u = luaS_newudata(L, size); |
2477 | setuvalue(L, L->top, u); |
2478 | api_incr_top(L); |
2479 | lua_unlock(L); |
2480 | - return u + 1; |
2481 | + return getudatamem(u); |
2482 | } |
2483 | |
2484 | |
2485 | |
2486 | static const char *aux_upvalue (StkId fi, int n, TValue **val, |
2487 | - GCObject **owner) { |
2488 | + CClosure **owner, UpVal **uv) { |
2489 | switch (ttype(fi)) { |
2490 | case LUA_TCCL: { /* C closure */ |
2491 | CClosure *f = clCvalue(fi); |
2492 | if (!(1 <= n && n <= f->nupvalues)) return NULL; |
2493 | *val = &f->upvalue[n-1]; |
2494 | - if (owner) *owner = obj2gco(f); |
2495 | + if (owner) *owner = f; |
2496 | return ""; |
2497 | } |
2498 | case LUA_TLCL: { /* Lua closure */ |
2499 | @@ -1201,9 +1181,9 @@ |
2500 | Proto *p = f->p; |
2501 | if (!(1 <= n && n <= p->sizeupvalues)) return NULL; |
2502 | *val = f->upvals[n-1]->v; |
2503 | - if (owner) *owner = obj2gco(f->upvals[n - 1]); |
2504 | + if (uv) *uv = f->upvals[n - 1]; |
2505 | name = p->upvalues[n-1].name; |
2506 | - return (name == NULL) ? "" : getstr(name); |
2507 | + return (name == NULL) ? "(*no name)" : getstr(name); |
2508 | } |
2509 | default: return NULL; /* not a closure */ |
2510 | } |
2511 | @@ -1214,7 +1194,7 @@ |
2512 | const char *name; |
2513 | TValue *val = NULL; /* to avoid warnings */ |
2514 | lua_lock(L); |
2515 | - name = aux_upvalue(index2addr(L, funcindex), n, &val, NULL); |
2516 | + name = aux_upvalue(index2addr(L, funcindex), n, &val, NULL, NULL); |
2517 | if (name) { |
2518 | setobj2s(L, L->top, val); |
2519 | api_incr_top(L); |
2520 | @@ -1227,16 +1207,18 @@ |
2521 | LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { |
2522 | const char *name; |
2523 | TValue *val = NULL; /* to avoid warnings */ |
2524 | - GCObject *owner = NULL; /* to avoid warnings */ |
2525 | + CClosure *owner = NULL; |
2526 | + UpVal *uv = NULL; |
2527 | StkId fi; |
2528 | lua_lock(L); |
2529 | fi = index2addr(L, funcindex); |
2530 | api_checknelems(L, 1); |
2531 | - name = aux_upvalue(fi, n, &val, &owner); |
2532 | + name = aux_upvalue(fi, n, &val, &owner, &uv); |
2533 | if (name) { |
2534 | L->top--; |
2535 | setobj(L, val, L->top); |
2536 | - luaC_barrier(L, owner, L->top); |
2537 | + if (owner) { luaC_barrier(L, owner, L->top); } |
2538 | + else if (uv) { luaC_upvalbarrier(L, uv); } |
2539 | } |
2540 | lua_unlock(L); |
2541 | return name; |
2542 | @@ -1246,9 +1228,9 @@ |
2543 | static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) { |
2544 | LClosure *f; |
2545 | StkId fi = index2addr(L, fidx); |
2546 | - api_check(L, ttisLclosure(fi), "Lua function expected"); |
2547 | + api_check(ttisLclosure(fi), "Lua function expected"); |
2548 | f = clLvalue(fi); |
2549 | - api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index"); |
2550 | + api_check((1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index"); |
2551 | if (pf) *pf = f; |
2552 | return &f->upvals[n - 1]; /* get its upvalue pointer */ |
2553 | } |
2554 | @@ -1262,11 +1244,11 @@ |
2555 | } |
2556 | case LUA_TCCL: { /* C closure */ |
2557 | CClosure *f = clCvalue(fi); |
2558 | - api_check(L, 1 <= n && n <= f->nupvalues, "invalid upvalue index"); |
2559 | + api_check(1 <= n && n <= f->nupvalues, "invalid upvalue index"); |
2560 | return &f->upvalue[n - 1]; |
2561 | } |
2562 | default: { |
2563 | - api_check(L, 0, "closure expected"); |
2564 | + api_check(0, "closure expected"); |
2565 | return NULL; |
2566 | } |
2567 | } |
2568 | @@ -1278,7 +1260,11 @@ |
2569 | LClosure *f1; |
2570 | UpVal **up1 = getupvalref(L, fidx1, n1, &f1); |
2571 | UpVal **up2 = getupvalref(L, fidx2, n2, NULL); |
2572 | + luaC_upvdeccount(L, *up1); |
2573 | *up1 = *up2; |
2574 | - luaC_objbarrier(L, f1, *up2); |
2575 | + (*up1)->refcount++; |
2576 | + if (upisopen(*up1)) (*up1)->u.open.touched = 1; |
2577 | + luaC_upvalbarrier(L, *up1); |
2578 | } |
2579 | |
2580 | + |
2581 | |
2582 | === modified file 'src/third_party/eris/lapi.h' |
2583 | --- src/third_party/eris/lapi.h 2014-02-22 14:47:28 +0000 |
2584 | +++ src/third_party/eris/lapi.h 2016-04-10 16:54:20 +0000 |
2585 | @@ -1,5 +1,5 @@ |
2586 | /* |
2587 | -** $Id: lapi.h,v 2.7.1.1 2013/04/12 18:48:47 roberto Exp $ |
2588 | +** $Id: lapi.h,v 2.8 2014/07/15 21:26:50 roberto Exp $ |
2589 | ** Auxiliary functions from Lua API |
2590 | ** See Copyright Notice in lua.h |
2591 | */ |
2592 | @@ -11,13 +11,13 @@ |
2593 | #include "llimits.h" |
2594 | #include "lstate.h" |
2595 | |
2596 | -#define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top, \ |
2597 | +#define api_incr_top(L) {L->top++; api_check(L->top <= L->ci->top, \ |
2598 | "stack overflow");} |
2599 | |
2600 | #define adjustresults(L,nres) \ |
2601 | { if ((nres) == LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; } |
2602 | |
2603 | -#define api_checknelems(L,n) api_check(L, (n) < (L->top - L->ci->func), \ |
2604 | +#define api_checknelems(L,n) api_check((n) < (L->top - L->ci->func), \ |
2605 | "not enough elements in the stack") |
2606 | |
2607 | |
2608 | |
2609 | === modified file 'src/third_party/eris/lauxlib.c' |
2610 | --- src/third_party/eris/lauxlib.c 2014-02-22 14:47:28 +0000 |
2611 | +++ src/third_party/eris/lauxlib.c 2016-04-10 16:54:20 +0000 |
2612 | @@ -1,9 +1,14 @@ |
2613 | /* |
2614 | -** $Id: lauxlib.c,v 1.248.1.1 2013/04/12 18:48:47 roberto Exp $ |
2615 | +** $Id: lauxlib.c,v 1.279 2014/12/14 18:32:26 roberto Exp $ |
2616 | ** Auxiliary functions for building Lua libraries |
2617 | ** See Copyright Notice in lua.h |
2618 | */ |
2619 | |
2620 | +#define lauxlib_c |
2621 | +#define LUA_LIB |
2622 | + |
2623 | +#include "lprefix.h" |
2624 | + |
2625 | |
2626 | #include <errno.h> |
2627 | #include <stdarg.h> |
2628 | @@ -16,9 +21,6 @@ |
2629 | ** Any function declared here could be written as an application function. |
2630 | */ |
2631 | |
2632 | -#define lauxlib_c |
2633 | -#define LUA_LIB |
2634 | - |
2635 | #include "lua.h" |
2636 | |
2637 | #include "lauxlib.h" |
2638 | @@ -64,11 +66,20 @@ |
2639 | } |
2640 | |
2641 | |
2642 | +/* |
2643 | +** Search for a name for a function in all loaded modules |
2644 | +** (registry._LOADED). |
2645 | +*/ |
2646 | static int pushglobalfuncname (lua_State *L, lua_Debug *ar) { |
2647 | int top = lua_gettop(L); |
2648 | lua_getinfo(L, "f", ar); /* push function */ |
2649 | - lua_pushglobaltable(L); |
2650 | + lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); |
2651 | if (findfield(L, top + 1, 2)) { |
2652 | + const char *name = lua_tostring(L, -1); |
2653 | + if (strncmp(name, "_G.", 3) == 0) { /* name start with '_G.'? */ |
2654 | + lua_pushstring(L, name + 3); /* push name without prefix */ |
2655 | + lua_remove(L, -2); /* remove original name */ |
2656 | + } |
2657 | lua_copy(L, -1, top + 1); /* move name to proper place */ |
2658 | lua_pop(L, 2); /* remove pushed values */ |
2659 | return 1; |
2660 | @@ -81,20 +92,18 @@ |
2661 | |
2662 | |
2663 | static void pushfuncname (lua_State *L, lua_Debug *ar) { |
2664 | - if (*ar->namewhat != '\0') /* is there a name? */ |
2665 | - lua_pushfstring(L, "function " LUA_QS, ar->name); |
2666 | + if (pushglobalfuncname(L, ar)) { /* try first a global name */ |
2667 | + lua_pushfstring(L, "function '%s'", lua_tostring(L, -1)); |
2668 | + lua_remove(L, -2); /* remove name */ |
2669 | + } |
2670 | + else if (*ar->namewhat != '\0') /* is there a name from code? */ |
2671 | + lua_pushfstring(L, "%s '%s'", ar->namewhat, ar->name); /* use it */ |
2672 | else if (*ar->what == 'm') /* main? */ |
2673 | lua_pushliteral(L, "main chunk"); |
2674 | - else if (*ar->what == 'C') { |
2675 | - if (pushglobalfuncname(L, ar)) { |
2676 | - lua_pushfstring(L, "function " LUA_QS, lua_tostring(L, -1)); |
2677 | - lua_remove(L, -2); /* remove name */ |
2678 | - } |
2679 | - else |
2680 | - lua_pushliteral(L, "?"); |
2681 | - } |
2682 | - else |
2683 | + else if (*ar->what != 'C') /* for Lua functions, use <file:line> */ |
2684 | lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined); |
2685 | + else /* nothing left... */ |
2686 | + lua_pushliteral(L, "?"); |
2687 | } |
2688 | |
2689 | |
2690 | @@ -150,33 +159,40 @@ |
2691 | ** ======================================================= |
2692 | */ |
2693 | |
2694 | -LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { |
2695 | +LUALIB_API int luaL_argerror (lua_State *L, int arg, const char *extramsg) { |
2696 | lua_Debug ar; |
2697 | if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ |
2698 | - return luaL_error(L, "bad argument #%d (%s)", narg, extramsg); |
2699 | + return luaL_error(L, "bad argument #%d (%s)", arg, extramsg); |
2700 | lua_getinfo(L, "n", &ar); |
2701 | if (strcmp(ar.namewhat, "method") == 0) { |
2702 | - narg--; /* do not count `self' */ |
2703 | - if (narg == 0) /* error is in the self argument itself? */ |
2704 | - return luaL_error(L, "calling " LUA_QS " on bad self (%s)", |
2705 | + arg--; /* do not count 'self' */ |
2706 | + if (arg == 0) /* error is in the self argument itself? */ |
2707 | + return luaL_error(L, "calling '%s' on bad self (%s)", |
2708 | ar.name, extramsg); |
2709 | } |
2710 | if (ar.name == NULL) |
2711 | ar.name = (pushglobalfuncname(L, &ar)) ? lua_tostring(L, -1) : "?"; |
2712 | - return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)", |
2713 | - narg, ar.name, extramsg); |
2714 | -} |
2715 | - |
2716 | - |
2717 | -static int typeerror (lua_State *L, int narg, const char *tname) { |
2718 | - const char *msg = lua_pushfstring(L, "%s expected, got %s", |
2719 | - tname, luaL_typename(L, narg)); |
2720 | - return luaL_argerror(L, narg, msg); |
2721 | -} |
2722 | - |
2723 | - |
2724 | -static void tag_error (lua_State *L, int narg, int tag) { |
2725 | - typeerror(L, narg, lua_typename(L, tag)); |
2726 | + return luaL_error(L, "bad argument #%d to '%s' (%s)", |
2727 | + arg, ar.name, extramsg); |
2728 | +} |
2729 | + |
2730 | + |
2731 | +static int typeerror (lua_State *L, int arg, const char *tname) { |
2732 | + const char *msg; |
2733 | + const char *typearg; /* name for the type of the actual argument */ |
2734 | + if (luaL_getmetafield(L, arg, "__name") == LUA_TSTRING) |
2735 | + typearg = lua_tostring(L, -1); /* use the given type name */ |
2736 | + else if (lua_type(L, arg) == LUA_TLIGHTUSERDATA) |
2737 | + typearg = "light userdata"; /* special name for messages */ |
2738 | + else |
2739 | + typearg = luaL_typename(L, arg); /* standard name */ |
2740 | + msg = lua_pushfstring(L, "%s expected, got %s", tname, typearg); |
2741 | + return luaL_argerror(L, arg, msg); |
2742 | +} |
2743 | + |
2744 | + |
2745 | +static void tag_error (lua_State *L, int arg, int tag) { |
2746 | + typeerror(L, arg, lua_typename(L, tag)); |
2747 | } |
2748 | |
2749 | |
2750 | @@ -222,7 +238,7 @@ |
2751 | } |
2752 | |
2753 | |
2754 | -#if !defined(inspectstat) /* { */ |
2755 | +#if !defined(l_inspectstat) /* { */ |
2756 | |
2757 | #if defined(LUA_USE_POSIX) |
2758 | |
2759 | @@ -231,13 +247,13 @@ |
2760 | /* |
2761 | ** use appropriate macros to interpret 'pclose' return status |
2762 | */ |
2763 | -#define inspectstat(stat,what) \ |
2764 | +#define l_inspectstat(stat,what) \ |
2765 | if (WIFEXITED(stat)) { stat = WEXITSTATUS(stat); } \ |
2766 | else if (WIFSIGNALED(stat)) { stat = WTERMSIG(stat); what = "signal"; } |
2767 | |
2768 | #else |
2769 | |
2770 | -#define inspectstat(stat,what) /* no op */ |
2771 | +#define l_inspectstat(stat,what) /* no op */ |
2772 | |
2773 | #endif |
2774 | |
2775 | @@ -249,7 +265,7 @@ |
2776 | if (stat == -1) /* error? */ |
2777 | return luaL_fileresult(L, 0, NULL); |
2778 | else { |
2779 | - inspectstat(stat, what); /* interpret result */ |
2780 | + l_inspectstat(stat, what); /* interpret result */ |
2781 | if (*what == 'e' && stat == 0) /* successful termination? */ |
2782 | lua_pushboolean(L, 1); |
2783 | else |
2784 | @@ -270,11 +286,12 @@ |
2785 | */ |
2786 | |
2787 | LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { |
2788 | - luaL_getmetatable(L, tname); /* try to get metatable */ |
2789 | - if (!lua_isnil(L, -1)) /* name already in use? */ |
2790 | + if (luaL_getmetatable(L, tname)) /* name already in use? */ |
2791 | return 0; /* leave previous value on top, but return 0 */ |
2792 | lua_pop(L, 1); |
2793 | lua_newtable(L); /* create metatable */ |
2794 | + lua_pushstring(L, tname); |
2795 | + lua_setfield(L, -2, "__name"); /* metatable.__name = tname */ |
2796 | lua_pushvalue(L, -1); |
2797 | lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */ |
2798 | return 1; |
2799 | @@ -317,16 +334,16 @@ |
2800 | ** ======================================================= |
2801 | */ |
2802 | |
2803 | -LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def, |
2804 | +LUALIB_API int luaL_checkoption (lua_State *L, int arg, const char *def, |
2805 | const char *const lst[]) { |
2806 | - const char *name = (def) ? luaL_optstring(L, narg, def) : |
2807 | - luaL_checkstring(L, narg); |
2808 | + const char *name = (def) ? luaL_optstring(L, arg, def) : |
2809 | + luaL_checkstring(L, arg); |
2810 | int i; |
2811 | for (i=0; lst[i]; i++) |
2812 | if (strcmp(lst[i], name) == 0) |
2813 | return i; |
2814 | - return luaL_argerror(L, narg, |
2815 | - lua_pushfstring(L, "invalid option " LUA_QS, name)); |
2816 | + return luaL_argerror(L, arg, |
2817 | + lua_pushfstring(L, "invalid option '%s'", name)); |
2818 | } |
2819 | |
2820 | |
2821 | @@ -342,77 +359,71 @@ |
2822 | } |
2823 | |
2824 | |
2825 | -LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) { |
2826 | - if (lua_type(L, narg) != t) |
2827 | - tag_error(L, narg, t); |
2828 | -} |
2829 | - |
2830 | - |
2831 | -LUALIB_API void luaL_checkany (lua_State *L, int narg) { |
2832 | - if (lua_type(L, narg) == LUA_TNONE) |
2833 | - luaL_argerror(L, narg, "value expected"); |
2834 | -} |
2835 | - |
2836 | - |
2837 | -LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) { |
2838 | - const char *s = lua_tolstring(L, narg, len); |
2839 | - if (!s) tag_error(L, narg, LUA_TSTRING); |
2840 | +LUALIB_API void luaL_checktype (lua_State *L, int arg, int t) { |
2841 | + if (lua_type(L, arg) != t) |
2842 | + tag_error(L, arg, t); |
2843 | +} |
2844 | + |
2845 | + |
2846 | +LUALIB_API void luaL_checkany (lua_State *L, int arg) { |
2847 | + if (lua_type(L, arg) == LUA_TNONE) |
2848 | + luaL_argerror(L, arg, "value expected"); |
2849 | +} |
2850 | + |
2851 | + |
2852 | +LUALIB_API const char *luaL_checklstring (lua_State *L, int arg, size_t *len) { |
2853 | + const char *s = lua_tolstring(L, arg, len); |
2854 | + if (!s) tag_error(L, arg, LUA_TSTRING); |
2855 | return s; |
2856 | } |
2857 | |
2858 | |
2859 | -LUALIB_API const char *luaL_optlstring (lua_State *L, int narg, |
2860 | +LUALIB_API const char *luaL_optlstring (lua_State *L, int arg, |
2861 | const char *def, size_t *len) { |
2862 | - if (lua_isnoneornil(L, narg)) { |
2863 | + if (lua_isnoneornil(L, arg)) { |
2864 | if (len) |
2865 | *len = (def ? strlen(def) : 0); |
2866 | return def; |
2867 | } |
2868 | - else return luaL_checklstring(L, narg, len); |
2869 | -} |
2870 | - |
2871 | - |
2872 | -LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) { |
2873 | - int isnum; |
2874 | - lua_Number d = lua_tonumberx(L, narg, &isnum); |
2875 | - if (!isnum) |
2876 | - tag_error(L, narg, LUA_TNUMBER); |
2877 | - return d; |
2878 | -} |
2879 | - |
2880 | - |
2881 | -LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) { |
2882 | - return luaL_opt(L, luaL_checknumber, narg, def); |
2883 | -} |
2884 | - |
2885 | - |
2886 | -LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) { |
2887 | - int isnum; |
2888 | - lua_Integer d = lua_tointegerx(L, narg, &isnum); |
2889 | - if (!isnum) |
2890 | - tag_error(L, narg, LUA_TNUMBER); |
2891 | - return d; |
2892 | -} |
2893 | - |
2894 | - |
2895 | -LUALIB_API lua_Unsigned luaL_checkunsigned (lua_State *L, int narg) { |
2896 | - int isnum; |
2897 | - lua_Unsigned d = lua_tounsignedx(L, narg, &isnum); |
2898 | - if (!isnum) |
2899 | - tag_error(L, narg, LUA_TNUMBER); |
2900 | - return d; |
2901 | -} |
2902 | - |
2903 | - |
2904 | -LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg, |
2905 | + else return luaL_checklstring(L, arg, len); |
2906 | +} |
2907 | + |
2908 | + |
2909 | +LUALIB_API lua_Number luaL_checknumber (lua_State *L, int arg) { |
2910 | + int isnum; |
2911 | + lua_Number d = lua_tonumberx(L, arg, &isnum); |
2912 | + if (!isnum) |
2913 | + tag_error(L, arg, LUA_TNUMBER); |
2914 | + return d; |
2915 | +} |
2916 | + |
2917 | + |
2918 | +LUALIB_API lua_Number luaL_optnumber (lua_State *L, int arg, lua_Number def) { |
2919 | + return luaL_opt(L, luaL_checknumber, arg, def); |
2920 | +} |
2921 | + |
2922 | + |
2923 | +static void interror (lua_State *L, int arg) { |
2924 | + if (lua_isnumber(L, arg)) |
2925 | + luaL_argerror(L, arg, "number has no integer representation"); |
2926 | + else |
2927 | + tag_error(L, arg, LUA_TNUMBER); |
2928 | +} |
2929 | + |
2930 | + |
2931 | +LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int arg) { |
2932 | + int isnum; |
2933 | + lua_Integer d = lua_tointegerx(L, arg, &isnum); |
2934 | + if (!isnum) { |
2935 | + interror(L, arg); |
2936 | + } |
2937 | + return d; |
2938 | +} |
2939 | + |
2940 | + |
2941 | +LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int arg, |
2942 | lua_Integer def) { |
2943 | - return luaL_opt(L, luaL_checkinteger, narg, def); |
2944 | -} |
2945 | - |
2946 | - |
2947 | -LUALIB_API lua_Unsigned luaL_optunsigned (lua_State *L, int narg, |
2948 | - lua_Unsigned def) { |
2949 | - return luaL_opt(L, luaL_checkunsigned, narg, def); |
2950 | + return luaL_opt(L, luaL_checkinteger, arg, def); |
2951 | } |
2952 | |
2953 | /* }====================================================== */ |
2954 | @@ -523,7 +534,7 @@ |
2955 | int ref; |
2956 | if (lua_isnil(L, -1)) { |
2957 | lua_pop(L, 1); /* remove from stack */ |
2958 | - return LUA_REFNIL; /* `nil' has a unique fixed reference */ |
2959 | + return LUA_REFNIL; /* 'nil' has a unique fixed reference */ |
2960 | } |
2961 | t = lua_absindex(L, t); |
2962 | lua_rawgeti(L, t, freelist); /* get first free element */ |
2963 | @@ -562,7 +573,7 @@ |
2964 | typedef struct LoadF { |
2965 | int n; /* number of pre-read characters */ |
2966 | FILE *f; /* file being read */ |
2967 | - char buff[LUAL_BUFFERSIZE]; /* area for reading file */ |
2968 | + char buff[BUFSIZ]; /* area for reading file */ |
2969 | } LoadF; |
2970 | |
2971 | |
2972 | @@ -655,7 +666,7 @@ |
2973 | readstatus = ferror(lf.f); |
2974 | if (filename) fclose(lf.f); /* close file (even in case of errors) */ |
2975 | if (readstatus) { |
2976 | - lua_settop(L, fnameindex); /* ignore results from `lua_load' */ |
2977 | + lua_settop(L, fnameindex); /* ignore results from 'lua_load' */ |
2978 | return errfile(L, "read", fnameindex); |
2979 | } |
2980 | lua_remove(L, fnameindex); |
2981 | @@ -698,23 +709,23 @@ |
2982 | |
2983 | LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { |
2984 | if (!lua_getmetatable(L, obj)) /* no metatable? */ |
2985 | - return 0; |
2986 | - lua_pushstring(L, event); |
2987 | - lua_rawget(L, -2); |
2988 | - if (lua_isnil(L, -1)) { |
2989 | - lua_pop(L, 2); /* remove metatable and metafield */ |
2990 | - return 0; |
2991 | - } |
2992 | + return LUA_TNIL; |
2993 | else { |
2994 | - lua_remove(L, -2); /* remove only metatable */ |
2995 | - return 1; |
2996 | + int tt; |
2997 | + lua_pushstring(L, event); |
2998 | + tt = lua_rawget(L, -2); |
2999 | + if (tt == LUA_TNIL) /* is metafield nil? */ |
3000 | + lua_pop(L, 2); /* remove metatable and metafield */ |
3001 | + else |
3002 | + lua_remove(L, -2); /* remove only metatable */ |
3003 | + return tt; /* return metafield type */ |
3004 | } |
3005 | } |
3006 | |
3007 | |
3008 | LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { |
3009 | obj = lua_absindex(L, obj); |
3010 | - if (!luaL_getmetafield(L, obj, event)) /* no metafield? */ |
3011 | + if (luaL_getmetafield(L, obj, event) == LUA_TNIL) /* no metafield? */ |
3012 | return 0; |
3013 | lua_pushvalue(L, obj); |
3014 | lua_call(L, 1, 1); |
3015 | @@ -722,13 +733,13 @@ |
3016 | } |
3017 | |
3018 | |
3019 | -LUALIB_API int luaL_len (lua_State *L, int idx) { |
3020 | - int l; |
3021 | +LUALIB_API lua_Integer luaL_len (lua_State *L, int idx) { |
3022 | + lua_Integer l; |
3023 | int isnum; |
3024 | lua_len(L, idx); |
3025 | - l = (int)lua_tointegerx(L, -1, &isnum); |
3026 | + l = lua_tointegerx(L, -1, &isnum); |
3027 | if (!isnum) |
3028 | - luaL_error(L, "object length is not a number"); |
3029 | + luaL_error(L, "object length is not an integer"); |
3030 | lua_pop(L, 1); /* remove object */ |
3031 | return l; |
3032 | } |
3033 | @@ -737,7 +748,13 @@ |
3034 | LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) { |
3035 | if (!luaL_callmeta(L, idx, "__tostring")) { /* no metafield? */ |
3036 | switch (lua_type(L, idx)) { |
3037 | - case LUA_TNUMBER: |
3038 | + case LUA_TNUMBER: { |
3039 | + if (lua_isinteger(L, idx)) |
3040 | + lua_pushfstring(L, "%I", lua_tointeger(L, idx)); |
3041 | + else |
3042 | + lua_pushfstring(L, "%f", lua_tonumber(L, idx)); |
3043 | + break; |
3044 | + } |
3045 | case LUA_TSTRING: |
3046 | lua_pushvalue(L, idx); |
3047 | break; |
3048 | @@ -772,8 +789,7 @@ |
3049 | e = strchr(fname, '.'); |
3050 | if (e == NULL) e = fname + strlen(fname); |
3051 | lua_pushlstring(L, fname, e - fname); |
3052 | - lua_rawget(L, -2); |
3053 | - if (lua_isnil(L, -1)) { /* no such field? */ |
3054 | + if (lua_rawget(L, -2) == LUA_TNIL) { /* no such field? */ |
3055 | lua_pop(L, 1); /* remove this nil */ |
3056 | lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */ |
3057 | lua_pushlstring(L, fname, e - fname); |
3058 | @@ -810,13 +826,12 @@ |
3059 | LUALIB_API void luaL_pushmodule (lua_State *L, const char *modname, |
3060 | int sizehint) { |
3061 | luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1); /* get _LOADED table */ |
3062 | - lua_getfield(L, -1, modname); /* get _LOADED[modname] */ |
3063 | - if (!lua_istable(L, -1)) { /* not found? */ |
3064 | + if (lua_getfield(L, -1, modname) != LUA_TTABLE) { /* no _LOADED[modname]? */ |
3065 | lua_pop(L, 1); /* remove previous result */ |
3066 | /* try global variable (and create one if it does not exist) */ |
3067 | lua_pushglobaltable(L); |
3068 | if (luaL_findtable(L, 0, modname, sizehint) != NULL) |
3069 | - luaL_error(L, "name conflict for module " LUA_QS, modname); |
3070 | + luaL_error(L, "name conflict for module '%s'", modname); |
3071 | lua_pushvalue(L, -1); |
3072 | lua_setfield(L, -3, modname); /* _LOADED[modname] = new table */ |
3073 | } |
3074 | @@ -846,7 +861,6 @@ |
3075 | ** Returns with only the table at the stack. |
3076 | */ |
3077 | LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { |
3078 | - luaL_checkversion(L); |
3079 | luaL_checkstack(L, nup, "too many upvalues"); |
3080 | for (; l->name != NULL; l++) { /* fill the table with given functions */ |
3081 | int i; |
3082 | @@ -864,8 +878,8 @@ |
3083 | ** into the stack |
3084 | */ |
3085 | LUALIB_API int luaL_getsubtable (lua_State *L, int idx, const char *fname) { |
3086 | - lua_getfield(L, idx, fname); |
3087 | - if (lua_istable(L, -1)) return 1; /* table already there */ |
3088 | + if (lua_getfield(L, idx, fname) == LUA_TTABLE) |
3089 | + return 1; /* table already there */ |
3090 | else { |
3091 | lua_pop(L, 1); /* remove previous result */ |
3092 | idx = lua_absindex(L, idx); |
3093 | @@ -878,22 +892,26 @@ |
3094 | |
3095 | |
3096 | /* |
3097 | -** stripped-down 'require'. Calls 'openf' to open a module, |
3098 | -** registers the result in 'package.loaded' table and, if 'glb' |
3099 | -** is true, also registers the result in the global table. |
3100 | +** Stripped-down 'require': After checking "loaded" table, calls 'openf' |
3101 | +** to open a module, registers the result in 'package.loaded' table and, |
3102 | +** if 'glb' is true, also registers the result in the global table. |
3103 | ** Leaves resulting module on the top. |
3104 | */ |
3105 | LUALIB_API void luaL_requiref (lua_State *L, const char *modname, |
3106 | lua_CFunction openf, int glb) { |
3107 | - lua_pushcfunction(L, openf); |
3108 | - lua_pushstring(L, modname); /* argument to open function */ |
3109 | - lua_call(L, 1, 1); /* open module */ |
3110 | luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED"); |
3111 | - lua_pushvalue(L, -2); /* make copy of module (call result) */ |
3112 | - lua_setfield(L, -2, modname); /* _LOADED[modname] = module */ |
3113 | - lua_pop(L, 1); /* remove _LOADED table */ |
3114 | + lua_getfield(L, -1, modname); /* _LOADED[modname] */ |
3115 | + if (!lua_toboolean(L, -1)) { /* package not already loaded? */ |
3116 | + lua_pop(L, 1); /* remove field */ |
3117 | + lua_pushcfunction(L, openf); |
3118 | + lua_pushstring(L, modname); /* argument to open function */ |
3119 | + lua_call(L, 1, 1); /* call 'openf' to open module */ |
3120 | + lua_pushvalue(L, -1); /* make copy of module (call result) */ |
3121 | + lua_setfield(L, -3, modname); /* _LOADED[modname] = module */ |
3122 | + } |
3123 | + lua_remove(L, -2); /* remove _LOADED table */ |
3124 | if (glb) { |
3125 | - lua_pushvalue(L, -1); /* copy of 'mod' */ |
3126 | + lua_pushvalue(L, -1); /* copy of module */ |
3127 | lua_setglobal(L, modname); /* _G[modname] = module */ |
3128 | } |
3129 | } |
3130 | @@ -908,7 +926,7 @@ |
3131 | while ((wild = strstr(s, p)) != NULL) { |
3132 | luaL_addlstring(&b, s, wild - s); /* push prefix */ |
3133 | luaL_addstring(&b, r); /* push replacement in place of pattern */ |
3134 | - s = wild + l; /* continue after `p' */ |
3135 | + s = wild + l; /* continue after 'p' */ |
3136 | } |
3137 | luaL_addstring(&b, s); /* push last suffix */ |
3138 | luaL_pushresult(&b); |
3139 | @@ -928,8 +946,8 @@ |
3140 | |
3141 | |
3142 | static int panic (lua_State *L) { |
3143 | - luai_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n", |
3144 | - lua_tostring(L, -1)); |
3145 | + lua_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n", |
3146 | + lua_tostring(L, -1)); |
3147 | return 0; /* return to Lua to abort */ |
3148 | } |
3149 | |
3150 | @@ -941,19 +959,14 @@ |
3151 | } |
3152 | |
3153 | |
3154 | -LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver) { |
3155 | +LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver, size_t sz) { |
3156 | const lua_Number *v = lua_version(L); |
3157 | + if (sz != LUAL_NUMSIZES) /* check numeric types */ |
3158 | + luaL_error(L, "core and library have incompatible numeric types"); |
3159 | if (v != lua_version(NULL)) |
3160 | luaL_error(L, "multiple Lua VMs detected"); |
3161 | else if (*v != ver) |
3162 | luaL_error(L, "version mismatch: app. needs %f, Lua core provides %f", |
3163 | ver, *v); |
3164 | - /* check conversions number -> integer types */ |
3165 | - lua_pushnumber(L, -(lua_Number)0x1234); |
3166 | - if (lua_tointeger(L, -1) != -0x1234 || |
3167 | - lua_tounsigned(L, -1) != (lua_Unsigned)-0x1234) |
3168 | - luaL_error(L, "bad conversion number->int;" |
3169 | - " must recompile Lua with proper settings"); |
3170 | - lua_pop(L, 1); |
3171 | } |
3172 | |
3173 | |
3174 | === modified file 'src/third_party/eris/lauxlib.h' |
3175 | --- src/third_party/eris/lauxlib.h 2014-02-22 14:47:28 +0000 |
3176 | +++ src/third_party/eris/lauxlib.h 2016-04-10 16:54:20 +0000 |
3177 | @@ -1,5 +1,5 @@ |
3178 | /* |
3179 | -** $Id: lauxlib.h,v 1.120.1.1 2013/04/12 18:48:47 roberto Exp $ |
3180 | +** $Id: lauxlib.h,v 1.128 2014/10/29 16:11:17 roberto Exp $ |
3181 | ** Auxiliary functions for building Lua libraries |
3182 | ** See Copyright Notice in lua.h |
3183 | */ |
3184 | @@ -16,7 +16,7 @@ |
3185 | |
3186 | |
3187 | |
3188 | -/* extra error code for `luaL_load' */ |
3189 | +/* extra error code for 'luaL_load' */ |
3190 | #define LUA_ERRFILE (LUA_ERRERR+1) |
3191 | |
3192 | |
3193 | @@ -26,30 +26,30 @@ |
3194 | } luaL_Reg; |
3195 | |
3196 | |
3197 | -LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver); |
3198 | -#define luaL_checkversion(L) luaL_checkversion_(L, LUA_VERSION_NUM) |
3199 | +#define LUAL_NUMSIZES (sizeof(lua_Integer)*16 + sizeof(lua_Number)) |
3200 | + |
3201 | +LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver, size_t sz); |
3202 | +#define luaL_checkversion(L) \ |
3203 | + luaL_checkversion_(L, LUA_VERSION_NUM, LUAL_NUMSIZES) |
3204 | |
3205 | LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); |
3206 | LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); |
3207 | LUALIB_API const char *(luaL_tolstring) (lua_State *L, int idx, size_t *len); |
3208 | -LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg); |
3209 | -LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg, |
3210 | +LUALIB_API int (luaL_argerror) (lua_State *L, int arg, const char *extramsg); |
3211 | +LUALIB_API const char *(luaL_checklstring) (lua_State *L, int arg, |
3212 | size_t *l); |
3213 | -LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg, |
3214 | +LUALIB_API const char *(luaL_optlstring) (lua_State *L, int arg, |
3215 | const char *def, size_t *l); |
3216 | -LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg); |
3217 | -LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def); |
3218 | +LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int arg); |
3219 | +LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int arg, lua_Number def); |
3220 | |
3221 | -LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg); |
3222 | -LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg, |
3223 | +LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int arg); |
3224 | +LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int arg, |
3225 | lua_Integer def); |
3226 | -LUALIB_API lua_Unsigned (luaL_checkunsigned) (lua_State *L, int numArg); |
3227 | -LUALIB_API lua_Unsigned (luaL_optunsigned) (lua_State *L, int numArg, |
3228 | - lua_Unsigned def); |
3229 | |
3230 | LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); |
3231 | -LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t); |
3232 | -LUALIB_API void (luaL_checkany) (lua_State *L, int narg); |
3233 | +LUALIB_API void (luaL_checktype) (lua_State *L, int arg, int t); |
3234 | +LUALIB_API void (luaL_checkany) (lua_State *L, int arg); |
3235 | |
3236 | LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); |
3237 | LUALIB_API void (luaL_setmetatable) (lua_State *L, const char *tname); |
3238 | @@ -59,7 +59,7 @@ |
3239 | LUALIB_API void (luaL_where) (lua_State *L, int lvl); |
3240 | LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); |
3241 | |
3242 | -LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def, |
3243 | +LUALIB_API int (luaL_checkoption) (lua_State *L, int arg, const char *def, |
3244 | const char *const lst[]); |
3245 | |
3246 | LUALIB_API int (luaL_fileresult) (lua_State *L, int stat, const char *fname); |
3247 | @@ -83,7 +83,7 @@ |
3248 | |
3249 | LUALIB_API lua_State *(luaL_newstate) (void); |
3250 | |
3251 | -LUALIB_API int (luaL_len) (lua_State *L, int idx); |
3252 | +LUALIB_API lua_Integer (luaL_len) (lua_State *L, int idx); |
3253 | |
3254 | LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, |
3255 | const char *r); |
3256 | @@ -108,16 +108,13 @@ |
3257 | #define luaL_newlibtable(L,l) \ |
3258 | lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1) |
3259 | |
3260 | -#define luaL_newlib(L,l) (luaL_newlibtable(L,l), luaL_setfuncs(L,l,0)) |
3261 | +#define luaL_newlib(L,l) \ |
3262 | + (luaL_checkversion(L), luaL_newlibtable(L,l), luaL_setfuncs(L,l,0)) |
3263 | |
3264 | -#define luaL_argcheck(L, cond,numarg,extramsg) \ |
3265 | - ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) |
3266 | +#define luaL_argcheck(L, cond,arg,extramsg) \ |
3267 | + ((void)((cond) || luaL_argerror(L, (arg), (extramsg)))) |
3268 | #define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) |
3269 | #define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) |
3270 | -#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) |
3271 | -#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) |
3272 | -#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) |
3273 | -#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) |
3274 | |
3275 | #define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) |
3276 | |
3277 | @@ -207,6 +204,53 @@ |
3278 | #endif |
3279 | |
3280 | |
3281 | +/* |
3282 | +** {================================================================== |
3283 | +** "Abstraction Layer" for basic report of messages and errors |
3284 | +** =================================================================== |
3285 | +*/ |
3286 | + |
3287 | +/* print a string */ |
3288 | +#if !defined(lua_writestring) |
3289 | +#define lua_writestring(s,l) fwrite((s), sizeof(char), (l), stdout) |
3290 | +#endif |
3291 | + |
3292 | +/* print a newline and flush the output */ |
3293 | +#if !defined(lua_writeline) |
3294 | +#define lua_writeline() (lua_writestring("\n", 1), fflush(stdout)) |
3295 | +#endif |
3296 | + |
3297 | +/* print an error message */ |
3298 | +#if !defined(lua_writestringerror) |
3299 | +#define lua_writestringerror(s,p) \ |
3300 | + (fprintf(stderr, (s), (p)), fflush(stderr)) |
3301 | +#endif |
3302 | + |
3303 | +/* }================================================================== */ |
3304 | + |
3305 | + |
3306 | +/* |
3307 | +** {============================================================ |
3308 | +** Compatibility with deprecated conversions |
3309 | +** ============================================================= |
3310 | +*/ |
3311 | +#if defined(LUA_COMPAT_APIINTCASTS) |
3312 | + |
3313 | +#define luaL_checkunsigned(L,a) ((lua_Unsigned)luaL_checkinteger(L,a)) |
3314 | +#define luaL_optunsigned(L,a,d) \ |
3315 | + ((lua_Unsigned)luaL_optinteger(L,a,(lua_Integer)(d))) |
3316 | + |
3317 | +#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) |
3318 | +#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) |
3319 | + |
3320 | +#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) |
3321 | +#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) |
3322 | + |
3323 | +#endif |
3324 | +/* }============================================================ */ |
3325 | + |
3326 | + |
3327 | + |
3328 | #endif |
3329 | |
3330 | |
3331 | |
3332 | === modified file 'src/third_party/eris/lbaselib.c' |
3333 | --- src/third_party/eris/lbaselib.c 2014-02-22 14:47:28 +0000 |
3334 | +++ src/third_party/eris/lbaselib.c 2016-04-10 16:54:20 +0000 |
3335 | @@ -1,9 +1,13 @@ |
3336 | /* |
3337 | -** $Id: lbaselib.c,v 1.276.1.1 2013/04/12 18:48:47 roberto Exp $ |
3338 | +** $Id: lbaselib.c,v 1.309 2014/12/10 12:26:42 roberto Exp $ |
3339 | ** Basic library |
3340 | ** See Copyright Notice in lua.h |
3341 | */ |
3342 | |
3343 | +#define lbaselib_c |
3344 | +#define LUA_LIB |
3345 | + |
3346 | +#include "lprefix.h" |
3347 | |
3348 | |
3349 | #include <ctype.h> |
3350 | @@ -11,9 +15,6 @@ |
3351 | #include <stdlib.h> |
3352 | #include <string.h> |
3353 | |
3354 | -#define lbaselib_c |
3355 | -#define LUA_LIB |
3356 | - |
3357 | #include "lua.h" |
3358 | |
3359 | #include "lauxlib.h" |
3360 | @@ -32,62 +33,74 @@ |
3361 | lua_call(L, 1, 1); |
3362 | s = lua_tolstring(L, -1, &l); /* get result */ |
3363 | if (s == NULL) |
3364 | - return luaL_error(L, |
3365 | - LUA_QL("tostring") " must return a string to " LUA_QL("print")); |
3366 | - if (i>1) luai_writestring("\t", 1); |
3367 | - luai_writestring(s, l); |
3368 | + return luaL_error(L, "'tostring' must return a string to 'print'"); |
3369 | + if (i>1) lua_writestring("\t", 1); |
3370 | + lua_writestring(s, l); |
3371 | lua_pop(L, 1); /* pop result */ |
3372 | } |
3373 | - luai_writeline(); |
3374 | + lua_writeline(); |
3375 | return 0; |
3376 | } |
3377 | |
3378 | |
3379 | #define SPACECHARS " \f\n\r\t\v" |
3380 | |
3381 | +static const char *b_str2int (const char *s, int base, lua_Integer *pn) { |
3382 | + lua_Unsigned n = 0; |
3383 | + int neg = 0; |
3384 | + s += strspn(s, SPACECHARS); /* skip initial spaces */ |
3385 | + if (*s == '-') { s++; neg = 1; } /* handle signal */ |
3386 | + else if (*s == '+') s++; |
3387 | + if (!isalnum((unsigned char)*s)) /* no digit? */ |
3388 | + return NULL; |
3389 | + do { |
3390 | + int digit = (isdigit((unsigned char)*s)) ? *s - '0' |
3391 | + : toupper((unsigned char)*s) - 'A' + 10; |
3392 | + if (digit >= base) return NULL; /* invalid numeral */ |
3393 | + n = n * base + digit; |
3394 | + s++; |
3395 | + } while (isalnum((unsigned char)*s)); |
3396 | + s += strspn(s, SPACECHARS); /* skip trailing spaces */ |
3397 | + *pn = (lua_Integer)((neg) ? (0u - n) : n); |
3398 | + return s; |
3399 | +} |
3400 | + |
3401 | + |
3402 | static int luaB_tonumber (lua_State *L) { |
3403 | - if (lua_isnoneornil(L, 2)) { /* standard conversion */ |
3404 | - int isnum; |
3405 | - lua_Number n = lua_tonumberx(L, 1, &isnum); |
3406 | - if (isnum) { |
3407 | - lua_pushnumber(L, n); |
3408 | - return 1; |
3409 | - } /* else not a number; must be something */ |
3410 | + if (lua_isnoneornil(L, 2)) { /* standard conversion? */ |
3411 | luaL_checkany(L, 1); |
3412 | + if (lua_type(L, 1) == LUA_TNUMBER) { /* already a number? */ |
3413 | + lua_settop(L, 1); /* yes; return it */ |
3414 | + return 1; |
3415 | + } |
3416 | + else { |
3417 | + size_t l; |
3418 | + const char *s = lua_tolstring(L, 1, &l); |
3419 | + if (s != NULL && lua_stringtonumber(L, s) == l + 1) |
3420 | + return 1; /* successful conversion to number */ |
3421 | + /* else not a number */ |
3422 | + } |
3423 | } |
3424 | else { |
3425 | size_t l; |
3426 | - const char *s = luaL_checklstring(L, 1, &l); |
3427 | - const char *e = s + l; /* end point for 's' */ |
3428 | - int base = luaL_checkint(L, 2); |
3429 | - int neg = 0; |
3430 | + const char *s; |
3431 | + lua_Integer n = 0; /* to avoid warnings */ |
3432 | + lua_Integer base = luaL_checkinteger(L, 2); |
3433 | + luaL_checktype(L, 1, LUA_TSTRING); /* before 'luaL_checklstring'! */ |
3434 | + s = luaL_checklstring(L, 1, &l); |
3435 | luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); |
3436 | - s += strspn(s, SPACECHARS); /* skip initial spaces */ |
3437 | - if (*s == '-') { s++; neg = 1; } /* handle signal */ |
3438 | - else if (*s == '+') s++; |
3439 | - if (isalnum((unsigned char)*s)) { |
3440 | - lua_Number n = 0; |
3441 | - do { |
3442 | - int digit = (isdigit((unsigned char)*s)) ? *s - '0' |
3443 | - : toupper((unsigned char)*s) - 'A' + 10; |
3444 | - if (digit >= base) break; /* invalid numeral; force a fail */ |
3445 | - n = n * (lua_Number)base + (lua_Number)digit; |
3446 | - s++; |
3447 | - } while (isalnum((unsigned char)*s)); |
3448 | - s += strspn(s, SPACECHARS); /* skip trailing spaces */ |
3449 | - if (s == e) { /* no invalid trailing characters? */ |
3450 | - lua_pushnumber(L, (neg) ? -n : n); |
3451 | - return 1; |
3452 | - } /* else not a number */ |
3453 | + if (b_str2int(s, (int)base, &n) == s + l) { |
3454 | + lua_pushinteger(L, n); |
3455 | + return 1; |
3456 | } /* else not a number */ |
3457 | - } |
3458 | + } /* else not a number */ |
3459 | lua_pushnil(L); /* not a number */ |
3460 | return 1; |
3461 | } |
3462 | |
3463 | |
3464 | static int luaB_error (lua_State *L) { |
3465 | - int level = luaL_optint(L, 2, 1); |
3466 | + int level = (int)luaL_optinteger(L, 2, 1); |
3467 | lua_settop(L, 1); |
3468 | if (lua_isstring(L, 1) && level > 0) { /* add extra information? */ |
3469 | luaL_where(L, level); |
3470 | @@ -114,7 +127,7 @@ |
3471 | luaL_checktype(L, 1, LUA_TTABLE); |
3472 | luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, |
3473 | "nil or table expected"); |
3474 | - if (luaL_getmetafield(L, 1, "__metatable")) |
3475 | + if (luaL_getmetafield(L, 1, "__metatable") != LUA_TNIL) |
3476 | return luaL_error(L, "cannot change a protected metatable"); |
3477 | lua_settop(L, 2); |
3478 | lua_setmetatable(L, 1); |
3479 | @@ -160,19 +173,18 @@ |
3480 | static int luaB_collectgarbage (lua_State *L) { |
3481 | static const char *const opts[] = {"stop", "restart", "collect", |
3482 | "count", "step", "setpause", "setstepmul", |
3483 | - "setmajorinc", "isrunning", "generational", "incremental", NULL}; |
3484 | + "isrunning", NULL}; |
3485 | static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, |
3486 | LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, |
3487 | - LUA_GCSETMAJORINC, LUA_GCISRUNNING, LUA_GCGEN, LUA_GCINC}; |
3488 | + LUA_GCISRUNNING}; |
3489 | int o = optsnum[luaL_checkoption(L, 1, "collect", opts)]; |
3490 | - int ex = luaL_optint(L, 2, 0); |
3491 | + int ex = (int)luaL_optinteger(L, 2, 0); |
3492 | int res = lua_gc(L, o, ex); |
3493 | switch (o) { |
3494 | case LUA_GCCOUNT: { |
3495 | int b = lua_gc(L, LUA_GCCOUNTB, 0); |
3496 | - lua_pushnumber(L, res + ((lua_Number)b/1024)); |
3497 | - lua_pushinteger(L, b); |
3498 | - return 2; |
3499 | + lua_pushnumber(L, (lua_Number)res + ((lua_Number)b/1024)); |
3500 | + return 1; |
3501 | } |
3502 | case LUA_GCSTEP: case LUA_GCISRUNNING: { |
3503 | lua_pushboolean(L, res); |
3504 | @@ -186,16 +198,19 @@ |
3505 | } |
3506 | |
3507 | |
3508 | +/* |
3509 | +** This function has all type names as upvalues, to maximize performance. |
3510 | +*/ |
3511 | static int luaB_type (lua_State *L) { |
3512 | luaL_checkany(L, 1); |
3513 | - lua_pushstring(L, luaL_typename(L, 1)); |
3514 | + lua_pushvalue(L, lua_upvalueindex(lua_type(L, 1) + 1)); |
3515 | return 1; |
3516 | } |
3517 | |
3518 | |
3519 | static int pairsmeta (lua_State *L, const char *method, int iszero, |
3520 | lua_CFunction iter) { |
3521 | - if (!luaL_getmetafield(L, 1, method)) { /* no metamethod? */ |
3522 | + if (luaL_getmetafield(L, 1, method) == LUA_TNIL) { /* no metamethod? */ |
3523 | luaL_checktype(L, 1, LUA_TTABLE); /* argument must be a table */ |
3524 | lua_pushcfunction(L, iter); /* will return generator, */ |
3525 | lua_pushvalue(L, 1); /* state, */ |
3526 | @@ -227,18 +242,44 @@ |
3527 | } |
3528 | |
3529 | |
3530 | +/* |
3531 | +** Traversal function for 'ipairs' for raw tables |
3532 | +*/ |
3533 | +static int ipairsaux_raw (lua_State *L) { |
3534 | + lua_Integer i = luaL_checkinteger(L, 2) + 1; |
3535 | + luaL_checktype(L, 1, LUA_TTABLE); |
3536 | + lua_pushinteger(L, i); |
3537 | + return (lua_rawgeti(L, 1, i) == LUA_TNIL) ? 1 : 2; |
3538 | +} |
3539 | + |
3540 | + |
3541 | +/* |
3542 | +** Traversal function for 'ipairs' for tables with metamethods |
3543 | +*/ |
3544 | static int ipairsaux (lua_State *L) { |
3545 | - int i = luaL_checkint(L, 2); |
3546 | - luaL_checktype(L, 1, LUA_TTABLE); |
3547 | - i++; /* next value */ |
3548 | + lua_Integer i = luaL_checkinteger(L, 2) + 1; |
3549 | lua_pushinteger(L, i); |
3550 | - lua_rawgeti(L, 1, i); |
3551 | - return (lua_isnil(L, -1)) ? 1 : 2; |
3552 | + return (lua_geti(L, 1, i) == LUA_TNIL) ? 1 : 2; |
3553 | } |
3554 | |
3555 | |
3556 | +/* |
3557 | +** This function will use either 'ipairsaux' or 'ipairsaux_raw' to |
3558 | +** traverse a table, depending on whether the table has metamethods |
3559 | +** that can affect the traversal. |
3560 | +*/ |
3561 | static int luaB_ipairs (lua_State *L) { |
3562 | - return pairsmeta(L, "__ipairs", 1, ipairsaux); |
3563 | + lua_CFunction iter = (luaL_getmetafield(L, 1, "__index") != LUA_TNIL) |
3564 | + ? ipairsaux : ipairsaux_raw; |
3565 | +#if defined(LUA_COMPAT_IPAIRS) |
3566 | + return pairsmeta(L, "__ipairs", 1, iter); |
3567 | +#else |
3568 | + luaL_checkany(L, 1); |
3569 | + lua_pushcfunction(L, iter); /* iteration function */ |
3570 | + lua_pushvalue(L, 1); /* state */ |
3571 | + lua_pushinteger(L, 0); /* initial value */ |
3572 | + return 3; |
3573 | +#endif |
3574 | } |
3575 | |
3576 | |
3577 | @@ -284,7 +325,7 @@ |
3578 | |
3579 | |
3580 | /* |
3581 | -** Reader for generic `load' function: `lua_load' uses the |
3582 | +** Reader for generic 'load' function: 'lua_load' uses the |
3583 | ** stack for internal stuff, so the reader cannot change the |
3584 | ** stack top. Instead, it keeps its resulting string in a |
3585 | ** reserved slot inside the stack. |
3586 | @@ -328,7 +369,8 @@ |
3587 | /* }====================================================== */ |
3588 | |
3589 | |
3590 | -static int dofilecont (lua_State *L) { |
3591 | +static int dofilecont (lua_State *L, int d1, lua_KContext d2) { |
3592 | + (void)d1; (void)d2; /* only to match 'lua_Kfunction' prototype */ |
3593 | return lua_gettop(L) - 1; |
3594 | } |
3595 | |
3596 | @@ -339,14 +381,20 @@ |
3597 | if (luaL_loadfile(L, fname) != LUA_OK) |
3598 | return lua_error(L); |
3599 | lua_callk(L, 0, LUA_MULTRET, 0, dofilecont); |
3600 | - return dofilecont(L); |
3601 | + return dofilecont(L, 0, 0); |
3602 | } |
3603 | |
3604 | |
3605 | static int luaB_assert (lua_State *L) { |
3606 | - if (!lua_toboolean(L, 1)) |
3607 | - return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!")); |
3608 | - return lua_gettop(L); |
3609 | + if (lua_toboolean(L, 1)) /* condition is true? */ |
3610 | + return lua_gettop(L); /* return all arguments */ |
3611 | + else { /* error */ |
3612 | + luaL_checkany(L, 1); /* there must be a condition */ |
3613 | + lua_remove(L, 1); /* remove it */ |
3614 | + lua_pushliteral(L, "assertion failed!"); /* default message */ |
3615 | + lua_settop(L, 1); /* leave only message (default if no other one) */ |
3616 | + return luaB_error(L); /* call 'error' */ |
3617 | + } |
3618 | } |
3619 | |
3620 | |
3621 | @@ -357,53 +405,57 @@ |
3622 | return 1; |
3623 | } |
3624 | else { |
3625 | - int i = luaL_checkint(L, 1); |
3626 | + lua_Integer i = luaL_checkinteger(L, 1); |
3627 | if (i < 0) i = n + i; |
3628 | else if (i > n) i = n; |
3629 | luaL_argcheck(L, 1 <= i, 1, "index out of range"); |
3630 | - return n - i; |
3631 | + return n - (int)i; |
3632 | } |
3633 | } |
3634 | |
3635 | |
3636 | -static int finishpcall (lua_State *L, int status) { |
3637 | - if (!lua_checkstack(L, 1)) { /* no space for extra boolean? */ |
3638 | - lua_settop(L, 0); /* create space for return values */ |
3639 | - lua_pushboolean(L, 0); |
3640 | - lua_pushstring(L, "stack overflow"); |
3641 | +/* |
3642 | +** Continuation function for 'pcall' and 'xpcall'. Both functions |
3643 | +** already pushed a 'true' before doing the call, so in case of success |
3644 | +** 'finishpcall' only has to return everything in the stack minus |
3645 | +** 'extra' values (where 'extra' is exactly the number of items to be |
3646 | +** ignored). |
3647 | +*/ |
3648 | +static int finishpcall (lua_State *L, int status, lua_KContext extra) { |
3649 | + if (status != LUA_OK && status != LUA_YIELD) { /* error? */ |
3650 | + lua_pushboolean(L, 0); /* first result (false) */ |
3651 | + lua_pushvalue(L, -2); /* error message */ |
3652 | return 2; /* return false, msg */ |
3653 | } |
3654 | - lua_pushboolean(L, status); /* first result (status) */ |
3655 | - lua_replace(L, 1); /* put first result in first slot */ |
3656 | - return lua_gettop(L); |
3657 | -} |
3658 | - |
3659 | - |
3660 | -static int pcallcont (lua_State *L) { |
3661 | - int status = lua_getctx(L, NULL); |
3662 | - return finishpcall(L, (status == LUA_YIELD)); |
3663 | + else |
3664 | + return lua_gettop(L) - (int)extra; /* return all results */ |
3665 | } |
3666 | |
3667 | |
3668 | static int luaB_pcall (lua_State *L) { |
3669 | int status; |
3670 | luaL_checkany(L, 1); |
3671 | - lua_pushnil(L); |
3672 | - lua_insert(L, 1); /* create space for status result */ |
3673 | - status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, pcallcont); |
3674 | - return finishpcall(L, (status == LUA_OK)); |
3675 | + lua_pushboolean(L, 1); /* first result if no errors */ |
3676 | + lua_insert(L, 1); /* put it in place */ |
3677 | + status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, finishpcall); |
3678 | + return finishpcall(L, status, 0); |
3679 | } |
3680 | |
3681 | |
3682 | +/* |
3683 | +** Do a protected call with error handling. After 'lua_rotate', the |
3684 | +** stack will have <f, err, true, f, [args...]>; so, the function passes |
3685 | +** 2 to 'finishpcall' to skip the 2 first values when returning results. |
3686 | +*/ |
3687 | static int luaB_xpcall (lua_State *L) { |
3688 | int status; |
3689 | int n = lua_gettop(L); |
3690 | - luaL_argcheck(L, n >= 2, 2, "value expected"); |
3691 | - lua_pushvalue(L, 1); /* exchange function... */ |
3692 | - lua_copy(L, 2, 1); /* ...and error handler */ |
3693 | - lua_replace(L, 2); |
3694 | - status = lua_pcallk(L, n - 2, LUA_MULTRET, 1, 0, pcallcont); |
3695 | - return finishpcall(L, (status == LUA_OK)); |
3696 | + luaL_checktype(L, 2, LUA_TFUNCTION); /* check error function */ |
3697 | + lua_pushboolean(L, 1); /* first result */ |
3698 | + lua_pushvalue(L, 1); /* function */ |
3699 | + lua_rotate(L, 3, 2); /* move them below function's arguments */ |
3700 | + status = lua_pcallk(L, n - 2, LUA_MULTRET, 2, 2, finishpcall); |
3701 | + return finishpcall(L, status, 2); |
3702 | } |
3703 | |
3704 | |
3705 | @@ -438,21 +490,31 @@ |
3706 | {"setmetatable", luaB_setmetatable}, |
3707 | {"tonumber", luaB_tonumber}, |
3708 | {"tostring", luaB_tostring}, |
3709 | - {"type", luaB_type}, |
3710 | {"xpcall", luaB_xpcall}, |
3711 | + /* placeholders */ |
3712 | + {"type", NULL}, |
3713 | + {"_G", NULL}, |
3714 | + {"_VERSION", NULL}, |
3715 | {NULL, NULL} |
3716 | }; |
3717 | |
3718 | |
3719 | LUAMOD_API int luaopen_base (lua_State *L) { |
3720 | + int i; |
3721 | + /* open lib into global table */ |
3722 | + lua_pushglobaltable(L); |
3723 | + luaL_setfuncs(L, base_funcs, 0); |
3724 | /* set global _G */ |
3725 | - lua_pushglobaltable(L); |
3726 | - lua_pushglobaltable(L); |
3727 | + lua_pushvalue(L, -1); |
3728 | lua_setfield(L, -2, "_G"); |
3729 | - /* open lib into global table */ |
3730 | - luaL_setfuncs(L, base_funcs, 0); |
3731 | + /* set global _VERSION */ |
3732 | lua_pushliteral(L, LUA_VERSION); |
3733 | - lua_setfield(L, -2, "_VERSION"); /* set global _VERSION */ |
3734 | + lua_setfield(L, -2, "_VERSION"); |
3735 | + /* set function 'type' with proper upvalues */ |
3736 | + for (i = 0; i < LUA_NUMTAGS; i++) /* push all type names as upvalues */ |
3737 | + lua_pushstring(L, lua_typename(L, i)); |
3738 | + lua_pushcclosure(L, luaB_type, LUA_NUMTAGS); |
3739 | + lua_setfield(L, -2, "type"); |
3740 | return 1; |
3741 | } |
3742 | |
3743 | @@ -461,33 +523,46 @@ |
3744 | luaL_checktype(L, -1, LUA_TTABLE); |
3745 | luaL_checkstack(L, 2, NULL); |
3746 | |
3747 | - if (forUnpersist) { |
3748 | - lua_pushstring(L, "__eris.baselib_pcallcont"); |
3749 | - lua_pushcfunction(L, pcallcont); |
3750 | - } |
3751 | - else { |
3752 | - lua_pushcfunction(L, pcallcont); |
3753 | - lua_pushstring(L, "__eris.baselib_pcallcont"); |
3754 | - } |
3755 | - lua_rawset(L, -3); |
3756 | - |
3757 | - if (forUnpersist) { |
3758 | - lua_pushstring(L, "__eris.baselib_luaB_next"); |
3759 | - lua_pushcfunction(L, luaB_next); |
3760 | - } |
3761 | - else { |
3762 | - lua_pushcfunction(L, luaB_next); |
3763 | - lua_pushstring(L, "__eris.baselib_luaB_next"); |
3764 | - } |
3765 | - lua_rawset(L, -3); |
3766 | - |
3767 | - if (forUnpersist) { |
3768 | - lua_pushstring(L, "__eris.baselib_ipairsaux"); |
3769 | - lua_pushcfunction(L, ipairsaux); |
3770 | - } |
3771 | - else { |
3772 | - lua_pushcfunction(L, ipairsaux); |
3773 | - lua_pushstring(L, "__eris.baselib_ipairsaux"); |
3774 | + /* NOTE: This is a terrible, terrible hack. We push a continuation function |
3775 | + * as a normal C function. We kinda have to, though, to allow proper lookup |
3776 | + * in the ref table, and it is never ever called, so we get away with it. */ |
3777 | + if (forUnpersist) { |
3778 | + lua_pushstring(L, "__eris.baselib_finishpcall"); |
3779 | + lua_pushcfunction(L, (lua_CFunction)finishpcall); |
3780 | + } |
3781 | + else { |
3782 | + lua_pushcfunction(L, (lua_CFunction)finishpcall); |
3783 | + lua_pushstring(L, "__eris.baselib_finishpcall"); |
3784 | + } |
3785 | + lua_rawset(L, -3); |
3786 | + |
3787 | + if (forUnpersist) { |
3788 | + lua_pushstring(L, "__eris.baselib_luaB_next"); |
3789 | + lua_pushcfunction(L, luaB_next); |
3790 | + } |
3791 | + else { |
3792 | + lua_pushcfunction(L, luaB_next); |
3793 | + lua_pushstring(L, "__eris.baselib_luaB_next"); |
3794 | + } |
3795 | + lua_rawset(L, -3); |
3796 | + |
3797 | + if (forUnpersist) { |
3798 | + lua_pushstring(L, "__eris.baselib_ipairsaux"); |
3799 | + lua_pushcfunction(L, ipairsaux); |
3800 | + } |
3801 | + else { |
3802 | + lua_pushcfunction(L, ipairsaux); |
3803 | + lua_pushstring(L, "__eris.baselib_ipairsaux"); |
3804 | + } |
3805 | + lua_rawset(L, -3); |
3806 | + |
3807 | + if (forUnpersist) { |
3808 | + lua_pushstring(L, "__eris.baselib_ipairsaux_raw"); |
3809 | + lua_pushcfunction(L, ipairsaux_raw); |
3810 | + } |
3811 | + else { |
3812 | + lua_pushcfunction(L, ipairsaux_raw); |
3813 | + lua_pushstring(L, "__eris.baselib_ipairsaux_raw"); |
3814 | } |
3815 | lua_rawset(L, -3); |
3816 | } |
3817 | |
3818 | === modified file 'src/third_party/eris/lbitlib.c' |
3819 | --- src/third_party/eris/lbitlib.c 2014-02-22 14:47:28 +0000 |
3820 | +++ src/third_party/eris/lbitlib.c 2016-04-10 16:54:20 +0000 |
3821 | @@ -1,5 +1,5 @@ |
3822 | /* |
3823 | -** $Id: lbitlib.c,v 1.18.1.2 2013/07/09 18:01:41 roberto Exp $ |
3824 | +** $Id: lbitlib.c,v 1.28 2014/11/02 19:19:04 roberto Exp $ |
3825 | ** Standard library for bitwise operations |
3826 | ** See Copyright Notice in lua.h |
3827 | */ |
3828 | @@ -7,20 +7,32 @@ |
3829 | #define lbitlib_c |
3830 | #define LUA_LIB |
3831 | |
3832 | +#include "lprefix.h" |
3833 | + |
3834 | + |
3835 | #include "lua.h" |
3836 | |
3837 | #include "lauxlib.h" |
3838 | #include "lualib.h" |
3839 | |
3840 | |
3841 | +#if defined(LUA_COMPAT_BITLIB) /* { */ |
3842 | + |
3843 | + |
3844 | /* number of bits to consider in a number */ |
3845 | #if !defined(LUA_NBITS) |
3846 | #define LUA_NBITS 32 |
3847 | #endif |
3848 | |
3849 | |
3850 | +/* |
3851 | +** a lua_Unsigned with its first LUA_NBITS bits equal to 1. (Shift must |
3852 | +** be made in two parts to avoid problems when LUA_NBITS is equal to the |
3853 | +** number of bits in a lua_Unsigned.) |
3854 | +*/ |
3855 | #define ALLONES (~(((~(lua_Unsigned)0) << (LUA_NBITS - 1)) << 1)) |
3856 | |
3857 | + |
3858 | /* macro to trim extra bits */ |
3859 | #define trim(x) ((x) & ALLONES) |
3860 | |
3861 | @@ -29,13 +41,10 @@ |
3862 | #define mask(n) (~((ALLONES << 1) << ((n) - 1))) |
3863 | |
3864 | |
3865 | -typedef lua_Unsigned b_uint; |
3866 | - |
3867 | - |
3868 | - |
3869 | -static b_uint andaux (lua_State *L) { |
3870 | + |
3871 | +static lua_Unsigned andaux (lua_State *L) { |
3872 | int i, n = lua_gettop(L); |
3873 | - b_uint r = ~(b_uint)0; |
3874 | + lua_Unsigned r = ~(lua_Unsigned)0; |
3875 | for (i = 1; i <= n; i++) |
3876 | r &= luaL_checkunsigned(L, i); |
3877 | return trim(r); |
3878 | @@ -43,14 +52,14 @@ |
3879 | |
3880 | |
3881 | static int b_and (lua_State *L) { |
3882 | - b_uint r = andaux(L); |
3883 | + lua_Unsigned r = andaux(L); |
3884 | lua_pushunsigned(L, r); |
3885 | return 1; |
3886 | } |
3887 | |
3888 | |
3889 | static int b_test (lua_State *L) { |
3890 | - b_uint r = andaux(L); |
3891 | + lua_Unsigned r = andaux(L); |
3892 | lua_pushboolean(L, r != 0); |
3893 | return 1; |
3894 | } |
3895 | @@ -58,7 +67,7 @@ |
3896 | |
3897 | static int b_or (lua_State *L) { |
3898 | int i, n = lua_gettop(L); |
3899 | - b_uint r = 0; |
3900 | + lua_Unsigned r = 0; |
3901 | for (i = 1; i <= n; i++) |
3902 | r |= luaL_checkunsigned(L, i); |
3903 | lua_pushunsigned(L, trim(r)); |
3904 | @@ -68,7 +77,7 @@ |
3905 | |
3906 | static int b_xor (lua_State *L) { |
3907 | int i, n = lua_gettop(L); |
3908 | - b_uint r = 0; |
3909 | + lua_Unsigned r = 0; |
3910 | for (i = 1; i <= n; i++) |
3911 | r ^= luaL_checkunsigned(L, i); |
3912 | lua_pushunsigned(L, trim(r)); |
3913 | @@ -77,13 +86,13 @@ |
3914 | |
3915 | |
3916 | static int b_not (lua_State *L) { |
3917 | - b_uint r = ~luaL_checkunsigned(L, 1); |
3918 | + lua_Unsigned r = ~luaL_checkunsigned(L, 1); |
3919 | lua_pushunsigned(L, trim(r)); |
3920 | return 1; |
3921 | } |
3922 | |
3923 | |
3924 | -static int b_shift (lua_State *L, b_uint r, int i) { |
3925 | +static int b_shift (lua_State *L, lua_Unsigned r, lua_Integer i) { |
3926 | if (i < 0) { /* shift right? */ |
3927 | i = -i; |
3928 | r = trim(r); |
3929 | @@ -101,33 +110,33 @@ |
3930 | |
3931 | |
3932 | static int b_lshift (lua_State *L) { |
3933 | - return b_shift(L, luaL_checkunsigned(L, 1), luaL_checkint(L, 2)); |
3934 | + return b_shift(L, luaL_checkunsigned(L, 1), luaL_checkinteger(L, 2)); |
3935 | } |
3936 | |
3937 | |
3938 | static int b_rshift (lua_State *L) { |
3939 | - return b_shift(L, luaL_checkunsigned(L, 1), -luaL_checkint(L, 2)); |
3940 | + return b_shift(L, luaL_checkunsigned(L, 1), -luaL_checkinteger(L, 2)); |
3941 | } |
3942 | |
3943 | |
3944 | static int b_arshift (lua_State *L) { |
3945 | - b_uint r = luaL_checkunsigned(L, 1); |
3946 | - int i = luaL_checkint(L, 2); |
3947 | - if (i < 0 || !(r & ((b_uint)1 << (LUA_NBITS - 1)))) |
3948 | + lua_Unsigned r = luaL_checkunsigned(L, 1); |
3949 | + lua_Integer i = luaL_checkinteger(L, 2); |
3950 | + if (i < 0 || !(r & ((lua_Unsigned)1 << (LUA_NBITS - 1)))) |
3951 | return b_shift(L, r, -i); |
3952 | else { /* arithmetic shift for 'negative' number */ |
3953 | if (i >= LUA_NBITS) r = ALLONES; |
3954 | else |
3955 | - r = trim((r >> i) | ~(~(b_uint)0 >> i)); /* add signal bit */ |
3956 | + r = trim((r >> i) | ~(trim(~(lua_Unsigned)0) >> i)); /* add signal bit */ |
3957 | lua_pushunsigned(L, r); |
3958 | return 1; |
3959 | } |
3960 | } |
3961 | |
3962 | |
3963 | -static int b_rot (lua_State *L, int i) { |
3964 | - b_uint r = luaL_checkunsigned(L, 1); |
3965 | - i &= (LUA_NBITS - 1); /* i = i % NBITS */ |
3966 | +static int b_rot (lua_State *L, lua_Integer d) { |
3967 | + lua_Unsigned r = luaL_checkunsigned(L, 1); |
3968 | + int i = d & (LUA_NBITS - 1); /* i = d % NBITS */ |
3969 | r = trim(r); |
3970 | if (i != 0) /* avoid undefined shift of LUA_NBITS when i == 0 */ |
3971 | r = (r << i) | (r >> (LUA_NBITS - i)); |
3972 | @@ -137,12 +146,12 @@ |
3973 | |
3974 | |
3975 | static int b_lrot (lua_State *L) { |
3976 | - return b_rot(L, luaL_checkint(L, 2)); |
3977 | + return b_rot(L, luaL_checkinteger(L, 2)); |
3978 | } |
3979 | |
3980 | |
3981 | static int b_rrot (lua_State *L) { |
3982 | - return b_rot(L, -luaL_checkint(L, 2)); |
3983 | + return b_rot(L, -luaL_checkinteger(L, 2)); |
3984 | } |
3985 | |
3986 | |
3987 | @@ -153,20 +162,20 @@ |
3988 | ** 'width' being used uninitialized.) |
3989 | */ |
3990 | static int fieldargs (lua_State *L, int farg, int *width) { |
3991 | - int f = luaL_checkint(L, farg); |
3992 | - int w = luaL_optint(L, farg + 1, 1); |
3993 | + lua_Integer f = luaL_checkinteger(L, farg); |
3994 | + lua_Integer w = luaL_optinteger(L, farg + 1, 1); |
3995 | luaL_argcheck(L, 0 <= f, farg, "field cannot be negative"); |
3996 | luaL_argcheck(L, 0 < w, farg + 1, "width must be positive"); |
3997 | if (f + w > LUA_NBITS) |
3998 | luaL_error(L, "trying to access non-existent bits"); |
3999 | - *width = w; |
4000 | - return f; |
4001 | + *width = (int)w; |
4002 | + return (int)f; |
4003 | } |
4004 | |
4005 | |
4006 | static int b_extract (lua_State *L) { |
4007 | int w; |
4008 | - b_uint r = luaL_checkunsigned(L, 1); |
4009 | + lua_Unsigned r = trim(luaL_checkunsigned(L, 1)); |
4010 | int f = fieldargs(L, 2, &w); |
4011 | r = (r >> f) & mask(w); |
4012 | lua_pushunsigned(L, r); |
4013 | @@ -176,8 +185,8 @@ |
4014 | |
4015 | static int b_replace (lua_State *L) { |
4016 | int w; |
4017 | - b_uint r = luaL_checkunsigned(L, 1); |
4018 | - b_uint v = luaL_checkunsigned(L, 2); |
4019 | + lua_Unsigned r = trim(luaL_checkunsigned(L, 1)); |
4020 | + lua_Unsigned v = luaL_checkunsigned(L, 2); |
4021 | int f = fieldargs(L, 3, &w); |
4022 | int m = mask(w); |
4023 | v &= m; /* erase bits outside given width */ |
4024 | @@ -210,3 +219,12 @@ |
4025 | return 1; |
4026 | } |
4027 | |
4028 | + |
4029 | +#else /* }{ */ |
4030 | + |
4031 | + |
4032 | +LUAMOD_API int luaopen_bit32 (lua_State *L) { |
4033 | + return luaL_error(L, "library 'bit32' has been deprecated"); |
4034 | +} |
4035 | + |
4036 | +#endif /* } */ |
4037 | |
4038 | === modified file 'src/third_party/eris/lcode.c' |
4039 | --- src/third_party/eris/lcode.c 2014-02-22 14:47:28 +0000 |
4040 | +++ src/third_party/eris/lcode.c 2016-04-10 16:54:20 +0000 |
4041 | @@ -1,15 +1,18 @@ |
4042 | /* |
4043 | -** $Id: lcode.c,v 2.62.1.1 2013/04/12 18:48:47 roberto Exp $ |
4044 | +** $Id: lcode.c,v 2.99 2014/12/29 16:49:25 roberto Exp $ |
4045 | ** Code generator for Lua |
4046 | ** See Copyright Notice in lua.h |
4047 | */ |
4048 | |
4049 | - |
4050 | -#include <stdlib.h> |
4051 | - |
4052 | #define lcode_c |
4053 | #define LUA_CORE |
4054 | |
4055 | +#include "lprefix.h" |
4056 | + |
4057 | + |
4058 | +#include <math.h> |
4059 | +#include <stdlib.h> |
4060 | + |
4061 | #include "lua.h" |
4062 | |
4063 | #include "lcode.h" |
4064 | @@ -26,11 +29,25 @@ |
4065 | #include "lvm.h" |
4066 | |
4067 | |
4068 | +/* Maximum number of registers in a Lua function */ |
4069 | +#define MAXREGS 250 |
4070 | + |
4071 | + |
4072 | #define hasjumps(e) ((e)->t != (e)->f) |
4073 | |
4074 | |
4075 | -static int isnumeral(expdesc *e) { |
4076 | - return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP); |
4077 | +static int tonumeral(expdesc *e, TValue *v) { |
4078 | + if (e->t != NO_JUMP || e->f != NO_JUMP) |
4079 | + return 0; /* not a numeral */ |
4080 | + switch (e->k) { |
4081 | + case VKINT: |
4082 | + if (v) setivalue(v, e->u.ival); |
4083 | + return 1; |
4084 | + case VKFLT: |
4085 | + if (v) setfltvalue(v, e->u.nval); |
4086 | + return 1; |
4087 | + default: return 0; |
4088 | + } |
4089 | } |
4090 | |
4091 | |
4092 | @@ -88,7 +105,7 @@ |
4093 | |
4094 | |
4095 | /* |
4096 | -** returns current `pc' and marks it as a jump target (to avoid wrong |
4097 | +** returns current 'pc' and marks it as a jump target (to avoid wrong |
4098 | ** optimizations with consecutive instructions not in the same basic block). |
4099 | */ |
4100 | int luaK_getlabel (FuncState *fs) { |
4101 | @@ -176,7 +193,7 @@ |
4102 | } |
4103 | |
4104 | |
4105 | -LUAI_FUNC void luaK_patchclose (FuncState *fs, int list, int level) { |
4106 | +void luaK_patchclose (FuncState *fs, int list, int level) { |
4107 | level++; /* argument is +1 to reserve 0 as non-op */ |
4108 | while (list != NO_JUMP) { |
4109 | int next = getjump(fs, list); |
4110 | @@ -211,7 +228,7 @@ |
4111 | |
4112 | static int luaK_code (FuncState *fs, Instruction i) { |
4113 | Proto *f = fs->f; |
4114 | - dischargejpc(fs); /* `pc' will change */ |
4115 | + dischargejpc(fs); /* 'pc' will change */ |
4116 | /* put new instruction in code array */ |
4117 | luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction, |
4118 | MAX_INT, "opcodes"); |
4119 | @@ -261,7 +278,7 @@ |
4120 | void luaK_checkstack (FuncState *fs, int n) { |
4121 | int newstack = fs->freereg + n; |
4122 | if (newstack > fs->f->maxstacksize) { |
4123 | - if (newstack >= MAXSTACK) |
4124 | + if (newstack >= MAXREGS) |
4125 | luaX_syntaxerror(fs->ls, "function or expression too complex"); |
4126 | fs->f->maxstacksize = cast_byte(newstack); |
4127 | } |
4128 | @@ -288,25 +305,28 @@ |
4129 | } |
4130 | |
4131 | |
4132 | +/* |
4133 | +** Use scanner's table to cache position of constants in constant list |
4134 | +** and try to reuse constants |
4135 | +*/ |
4136 | static int addk (FuncState *fs, TValue *key, TValue *v) { |
4137 | lua_State *L = fs->ls->L; |
4138 | - TValue *idx = luaH_set(L, fs->h, key); |
4139 | Proto *f = fs->f; |
4140 | + TValue *idx = luaH_set(L, fs->ls->h, key); /* index scanner table */ |
4141 | int k, oldsize; |
4142 | - if (ttisnumber(idx)) { |
4143 | - lua_Number n = nvalue(idx); |
4144 | - lua_number2int(k, n); |
4145 | - if (luaV_rawequalobj(&f->k[k], v)) |
4146 | - return k; |
4147 | - /* else may be a collision (e.g., between 0.0 and "\0\0\0\0\0\0\0\0"); |
4148 | - go through and create a new entry for this value */ |
4149 | + if (ttisinteger(idx)) { /* is there an index there? */ |
4150 | + k = cast_int(ivalue(idx)); |
4151 | + /* correct value? (warning: must distinguish floats from integers!) */ |
4152 | + if (k < fs->nk && ttype(&f->k[k]) == ttype(v) && |
4153 | + luaV_rawequalobj(&f->k[k], v)) |
4154 | + return k; /* reuse index */ |
4155 | } |
4156 | /* constant not found; create a new entry */ |
4157 | oldsize = f->sizek; |
4158 | k = fs->nk; |
4159 | /* numerical value does not need GC barrier; |
4160 | table has no metatable, so it does not need to invalidate cache */ |
4161 | - setnvalue(idx, cast_num(k)); |
4162 | + setivalue(idx, k); |
4163 | luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants"); |
4164 | while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); |
4165 | setobj(L, &f->k[k], v); |
4166 | @@ -323,20 +343,23 @@ |
4167 | } |
4168 | |
4169 | |
4170 | -int luaK_numberK (FuncState *fs, lua_Number r) { |
4171 | - int n; |
4172 | - lua_State *L = fs->ls->L; |
4173 | +/* |
4174 | +** Integers use userdata as keys to avoid collision with floats with same |
4175 | +** value; conversion to 'void*' used only for hashing, no "precision" |
4176 | +** problems |
4177 | +*/ |
4178 | +int luaK_intK (FuncState *fs, lua_Integer n) { |
4179 | + TValue k, o; |
4180 | + setpvalue(&k, cast(void*, cast(size_t, n))); |
4181 | + setivalue(&o, n); |
4182 | + return addk(fs, &k, &o); |
4183 | +} |
4184 | + |
4185 | + |
4186 | +static int luaK_numberK (FuncState *fs, lua_Number r) { |
4187 | TValue o; |
4188 | - setnvalue(&o, r); |
4189 | - if (r == 0 || luai_numisnan(NULL, r)) { /* handle -0 and NaN */ |
4190 | - /* use raw representation as key to avoid numeric problems */ |
4191 | - setsvalue(L, L->top++, luaS_newlstr(L, (char *)&r, sizeof(r))); |
4192 | - n = addk(fs, L->top - 1, &o); |
4193 | - L->top--; |
4194 | - } |
4195 | - else |
4196 | - n = addk(fs, &o, &o); /* regular case */ |
4197 | - return n; |
4198 | + setfltvalue(&o, r); |
4199 | + return addk(fs, &o, &o); |
4200 | } |
4201 | |
4202 | |
4203 | @@ -351,7 +374,7 @@ |
4204 | TValue k, v; |
4205 | setnilvalue(&v); |
4206 | /* cannot use nil as key; instead use table itself to represent nil */ |
4207 | - sethvalue(fs->ls->L, &k, fs->h); |
4208 | + sethvalue(fs->ls->L, &k, fs->ls->h); |
4209 | return addk(fs, &k, &v); |
4210 | } |
4211 | |
4212 | @@ -433,10 +456,14 @@ |
4213 | luaK_codek(fs, reg, e->u.info); |
4214 | break; |
4215 | } |
4216 | - case VKNUM: { |
4217 | + case VKFLT: { |
4218 | luaK_codek(fs, reg, luaK_numberK(fs, e->u.nval)); |
4219 | break; |
4220 | } |
4221 | + case VKINT: { |
4222 | + luaK_codek(fs, reg, luaK_intK(fs, e->u.ival)); |
4223 | + break; |
4224 | + } |
4225 | case VRELOCABLE: { |
4226 | Instruction *pc = &getcode(fs, e); |
4227 | SETARG_A(*pc, reg); |
4228 | @@ -468,7 +495,7 @@ |
4229 | static void exp2reg (FuncState *fs, expdesc *e, int reg) { |
4230 | discharge2reg(fs, e, reg); |
4231 | if (e->k == VJMP) |
4232 | - luaK_concat(fs, &e->t, e->u.info); /* put this jump in `t' list */ |
4233 | + luaK_concat(fs, &e->t, e->u.info); /* put this jump in 't' list */ |
4234 | if (hasjumps(e)) { |
4235 | int final; /* position after whole expression */ |
4236 | int p_f = NO_JUMP; /* position of an eventual LOAD false */ |
4237 | @@ -538,13 +565,19 @@ |
4238 | } |
4239 | else break; |
4240 | } |
4241 | - case VKNUM: { |
4242 | + case VKINT: { |
4243 | + e->u.info = luaK_intK(fs, e->u.ival); |
4244 | + e->k = VK; |
4245 | + goto vk; |
4246 | + } |
4247 | + case VKFLT: { |
4248 | e->u.info = luaK_numberK(fs, e->u.nval); |
4249 | e->k = VK; |
4250 | /* go through */ |
4251 | } |
4252 | case VK: { |
4253 | - if (e->u.info <= MAXINDEXRK) /* constant fits in argC? */ |
4254 | + vk: |
4255 | + if (e->u.info <= MAXINDEXRK) /* constant fits in 'argC'? */ |
4256 | return RKASK(e->u.info); |
4257 | else break; |
4258 | } |
4259 | @@ -627,7 +660,7 @@ |
4260 | pc = e->u.info; |
4261 | break; |
4262 | } |
4263 | - case VK: case VKNUM: case VTRUE: { |
4264 | + case VK: case VKFLT: case VKINT: case VTRUE: { |
4265 | pc = NO_JUMP; /* always true; do nothing */ |
4266 | break; |
4267 | } |
4268 | @@ -636,7 +669,7 @@ |
4269 | break; |
4270 | } |
4271 | } |
4272 | - luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */ |
4273 | + luaK_concat(fs, &e->f, pc); /* insert last jump in 'f' list */ |
4274 | luaK_patchtohere(fs, e->t); |
4275 | e->t = NO_JUMP; |
4276 | } |
4277 | @@ -659,7 +692,7 @@ |
4278 | break; |
4279 | } |
4280 | } |
4281 | - luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */ |
4282 | + luaK_concat(fs, &e->t, pc); /* insert last jump in 't' list */ |
4283 | luaK_patchtohere(fs, e->f); |
4284 | e->f = NO_JUMP; |
4285 | } |
4286 | @@ -672,7 +705,7 @@ |
4287 | e->k = VTRUE; |
4288 | break; |
4289 | } |
4290 | - case VK: case VKNUM: case VTRUE: { |
4291 | + case VK: case VKFLT: case VKINT: case VTRUE: { |
4292 | e->k = VFALSE; |
4293 | break; |
4294 | } |
4295 | @@ -710,25 +743,70 @@ |
4296 | } |
4297 | |
4298 | |
4299 | -static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { |
4300 | - lua_Number r; |
4301 | - if (!isnumeral(e1) || !isnumeral(e2)) return 0; |
4302 | - if ((op == OP_DIV || op == OP_MOD) && e2->u.nval == 0) |
4303 | - return 0; /* do not attempt to divide by 0 */ |
4304 | - r = luaO_arith(op - OP_ADD + LUA_OPADD, e1->u.nval, e2->u.nval); |
4305 | - e1->u.nval = r; |
4306 | +/* |
4307 | +** return false if folding can raise an error |
4308 | +*/ |
4309 | +static int validop (int op, TValue *v1, TValue *v2) { |
4310 | + switch (op) { |
4311 | + case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR: |
4312 | + case LUA_OPSHL: case LUA_OPSHR: case LUA_OPBNOT: { /* conversion errors */ |
4313 | + lua_Integer i; |
4314 | + return (tointeger(v1, &i) && tointeger(v2, &i)); |
4315 | + } |
4316 | + case LUA_OPDIV: case LUA_OPIDIV: case LUA_OPMOD: /* division by 0 */ |
4317 | + return (nvalue(v2) != 0); |
4318 | + default: return 1; /* everything else is valid */ |
4319 | + } |
4320 | +} |
4321 | + |
4322 | + |
4323 | +/* |
4324 | +** Try to "constant-fold" an operation; return 1 iff successful |
4325 | +*/ |
4326 | +static int constfolding (FuncState *fs, int op, expdesc *e1, expdesc *e2) { |
4327 | + TValue v1, v2, res; |
4328 | + if (!tonumeral(e1, &v1) || !tonumeral(e2, &v2) || !validop(op, &v1, &v2)) |
4329 | + return 0; /* non-numeric operands or not safe to fold */ |
4330 | + luaO_arith(fs->ls->L, op, &v1, &v2, &res); /* does operation */ |
4331 | + if (ttisinteger(&res)) { |
4332 | + e1->k = VKINT; |
4333 | + e1->u.ival = ivalue(&res); |
4334 | + } |
4335 | + else { /* folds neither NaN nor 0.0 (to avoid collapsing with -0.0) */ |
4336 | + lua_Number n = fltvalue(&res); |
4337 | + if (luai_numisnan(n) || n == 0) |
4338 | + return 0; |
4339 | + e1->k = VKFLT; |
4340 | + e1->u.nval = n; |
4341 | + } |
4342 | return 1; |
4343 | } |
4344 | |
4345 | |
4346 | -static void codearith (FuncState *fs, OpCode op, |
4347 | - expdesc *e1, expdesc *e2, int line) { |
4348 | - if (constfolding(op, e1, e2)) |
4349 | - return; |
4350 | +/* |
4351 | +** Code for binary and unary expressions that "produce values" |
4352 | +** (arithmetic operations, bitwise operations, concat, length). First |
4353 | +** try to do constant folding (only for numeric [arithmetic and |
4354 | +** bitwise] operations, which is what 'lua_arith' accepts). |
4355 | +** Expression to produce final result will be encoded in 'e1'. |
4356 | +*/ |
4357 | +static void codeexpval (FuncState *fs, OpCode op, |
4358 | + expdesc *e1, expdesc *e2, int line) { |
4359 | + lua_assert(op >= OP_ADD); |
4360 | + if (op <= OP_BNOT && constfolding(fs, op - OP_ADD + LUA_OPADD, e1, e2)) |
4361 | + return; /* result has been folded */ |
4362 | else { |
4363 | - int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0; |
4364 | - int o1 = luaK_exp2RK(fs, e1); |
4365 | - if (o1 > o2) { |
4366 | + int o1, o2; |
4367 | + /* move operands to registers (if needed) */ |
4368 | + if (op == OP_UNM || op == OP_BNOT || op == OP_LEN) { /* unary op? */ |
4369 | + o2 = 0; /* no second expression */ |
4370 | + o1 = luaK_exp2anyreg(fs, e1); /* cannot operate on constants */ |
4371 | + } |
4372 | + else { /* regular case (binary operators) */ |
4373 | + o2 = luaK_exp2RK(fs, e2); /* both operands are "RK" */ |
4374 | + o1 = luaK_exp2RK(fs, e1); |
4375 | + } |
4376 | + if (o1 > o2) { /* free registers in proper order */ |
4377 | freeexp(fs, e1); |
4378 | freeexp(fs, e2); |
4379 | } |
4380 | @@ -736,8 +814,8 @@ |
4381 | freeexp(fs, e2); |
4382 | freeexp(fs, e1); |
4383 | } |
4384 | - e1->u.info = luaK_codeABC(fs, op, 0, o1, o2); |
4385 | - e1->k = VRELOCABLE; |
4386 | + e1->u.info = luaK_codeABC(fs, op, 0, o1, o2); /* generate opcode */ |
4387 | + e1->k = VRELOCABLE; /* all those operations are relocable */ |
4388 | luaK_fixline(fs, line); |
4389 | } |
4390 | } |
4391 | @@ -750,7 +828,7 @@ |
4392 | freeexp(fs, e2); |
4393 | freeexp(fs, e1); |
4394 | if (cond == 0 && op != OP_EQ) { |
4395 | - int temp; /* exchange args to replace by `<' or `<=' */ |
4396 | + int temp; /* exchange args to replace by '<' or '<=' */ |
4397 | temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ |
4398 | cond = 1; |
4399 | } |
4400 | @@ -761,23 +839,13 @@ |
4401 | |
4402 | void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) { |
4403 | expdesc e2; |
4404 | - e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; |
4405 | + e2.t = e2.f = NO_JUMP; e2.k = VKINT; e2.u.ival = 0; |
4406 | switch (op) { |
4407 | - case OPR_MINUS: { |
4408 | - if (isnumeral(e)) /* minus constant? */ |
4409 | - e->u.nval = luai_numunm(NULL, e->u.nval); /* fold it */ |
4410 | - else { |
4411 | - luaK_exp2anyreg(fs, e); |
4412 | - codearith(fs, OP_UNM, e, &e2, line); |
4413 | - } |
4414 | + case OPR_MINUS: case OPR_BNOT: case OPR_LEN: { |
4415 | + codeexpval(fs, cast(OpCode, (op - OPR_MINUS) + OP_UNM), e, &e2, line); |
4416 | break; |
4417 | } |
4418 | case OPR_NOT: codenot(fs, e); break; |
4419 | - case OPR_LEN: { |
4420 | - luaK_exp2anyreg(fs, e); /* cannot operate on constants */ |
4421 | - codearith(fs, OP_LEN, e, &e2, line); |
4422 | - break; |
4423 | - } |
4424 | default: lua_assert(0); |
4425 | } |
4426 | } |
4427 | @@ -794,12 +862,15 @@ |
4428 | break; |
4429 | } |
4430 | case OPR_CONCAT: { |
4431 | - luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */ |
4432 | + luaK_exp2nextreg(fs, v); /* operand must be on the 'stack' */ |
4433 | break; |
4434 | } |
4435 | - case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: |
4436 | - case OPR_MOD: case OPR_POW: { |
4437 | - if (!isnumeral(v)) luaK_exp2RK(fs, v); |
4438 | + case OPR_ADD: case OPR_SUB: |
4439 | + case OPR_MUL: case OPR_DIV: case OPR_IDIV: |
4440 | + case OPR_MOD: case OPR_POW: |
4441 | + case OPR_BAND: case OPR_BOR: case OPR_BXOR: |
4442 | + case OPR_SHL: case OPR_SHR: { |
4443 | + if (!tonumeral(v, NULL)) luaK_exp2RK(fs, v); |
4444 | break; |
4445 | } |
4446 | default: { |
4447 | @@ -837,13 +908,15 @@ |
4448 | } |
4449 | else { |
4450 | luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ |
4451 | - codearith(fs, OP_CONCAT, e1, e2, line); |
4452 | + codeexpval(fs, OP_CONCAT, e1, e2, line); |
4453 | } |
4454 | break; |
4455 | } |
4456 | case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: |
4457 | - case OPR_MOD: case OPR_POW: { |
4458 | - codearith(fs, cast(OpCode, op - OPR_ADD + OP_ADD), e1, e2, line); |
4459 | + case OPR_IDIV: case OPR_MOD: case OPR_POW: |
4460 | + case OPR_BAND: case OPR_BOR: case OPR_BXOR: |
4461 | + case OPR_SHL: case OPR_SHR: { |
4462 | + codeexpval(fs, cast(OpCode, (op - OPR_ADD) + OP_ADD), e1, e2, line); |
4463 | break; |
4464 | } |
4465 | case OPR_EQ: case OPR_LT: case OPR_LE: { |
4466 | |
4467 | === modified file 'src/third_party/eris/lcode.h' |
4468 | --- src/third_party/eris/lcode.h 2014-02-22 14:47:28 +0000 |
4469 | +++ src/third_party/eris/lcode.h 2016-04-10 16:54:20 +0000 |
4470 | @@ -1,5 +1,5 @@ |
4471 | /* |
4472 | -** $Id: lcode.h,v 1.58.1.1 2013/04/12 18:48:47 roberto Exp $ |
4473 | +** $Id: lcode.h,v 1.63 2013/12/30 20:47:58 roberto Exp $ |
4474 | ** Code generator for Lua |
4475 | ** See Copyright Notice in lua.h |
4476 | */ |
4477 | @@ -24,7 +24,11 @@ |
4478 | ** grep "ORDER OPR" if you change these enums (ORDER OP) |
4479 | */ |
4480 | typedef enum BinOpr { |
4481 | - OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW, |
4482 | + OPR_ADD, OPR_SUB, OPR_MUL, OPR_MOD, OPR_POW, |
4483 | + OPR_DIV, |
4484 | + OPR_IDIV, |
4485 | + OPR_BAND, OPR_BOR, OPR_BXOR, |
4486 | + OPR_SHL, OPR_SHR, |
4487 | OPR_CONCAT, |
4488 | OPR_EQ, OPR_LT, OPR_LE, |
4489 | OPR_NE, OPR_GT, OPR_GE, |
4490 | @@ -33,7 +37,7 @@ |
4491 | } BinOpr; |
4492 | |
4493 | |
4494 | -typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; |
4495 | +typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; |
4496 | |
4497 | |
4498 | #define getcode(fs,e) ((fs)->f->code[(e)->u.info]) |
4499 | @@ -52,7 +56,7 @@ |
4500 | LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n); |
4501 | LUAI_FUNC void luaK_checkstack (FuncState *fs, int n); |
4502 | LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s); |
4503 | -LUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r); |
4504 | +LUAI_FUNC int luaK_intK (FuncState *fs, lua_Integer n); |
4505 | LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); |
4506 | LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e); |
4507 | LUAI_FUNC void luaK_exp2anyregup (FuncState *fs, expdesc *e); |
4508 | |
4509 | === modified file 'src/third_party/eris/lcorolib.c' |
4510 | --- src/third_party/eris/lcorolib.c 2014-02-22 14:47:28 +0000 |
4511 | +++ src/third_party/eris/lcorolib.c 2016-04-10 16:54:20 +0000 |
4512 | @@ -1,22 +1,30 @@ |
4513 | /* |
4514 | -** $Id: lcorolib.c,v 1.5.1.1 2013/04/12 18:48:47 roberto Exp $ |
4515 | +** $Id: lcorolib.c,v 1.9 2014/11/02 19:19:04 roberto Exp $ |
4516 | ** Coroutine Library |
4517 | ** See Copyright Notice in lua.h |
4518 | */ |
4519 | |
4520 | - |
4521 | -#include <stdlib.h> |
4522 | - |
4523 | - |
4524 | #define lcorolib_c |
4525 | #define LUA_LIB |
4526 | |
4527 | +#include "lprefix.h" |
4528 | + |
4529 | + |
4530 | +#include <stdlib.h> |
4531 | + |
4532 | #include "lua.h" |
4533 | |
4534 | #include "lauxlib.h" |
4535 | #include "lualib.h" |
4536 | |
4537 | |
4538 | +static lua_State *getco (lua_State *L) { |
4539 | + lua_State *co = lua_tothread(L, 1); |
4540 | + luaL_argcheck(L, co, 1, "thread expected"); |
4541 | + return co; |
4542 | +} |
4543 | + |
4544 | + |
4545 | static int auxresume (lua_State *L, lua_State *co, int narg) { |
4546 | int status; |
4547 | if (!lua_checkstack(co, narg)) { |
4548 | @@ -47,9 +55,8 @@ |
4549 | |
4550 | |
4551 | static int luaB_coresume (lua_State *L) { |
4552 | - lua_State *co = lua_tothread(L, 1); |
4553 | + lua_State *co = getco(L); |
4554 | int r; |
4555 | - luaL_argcheck(L, co, 1, "coroutine expected"); |
4556 | r = auxresume(L, co, lua_gettop(L) - 1); |
4557 | if (r < 0) { |
4558 | lua_pushboolean(L, 0); |
4559 | @@ -59,7 +66,7 @@ |
4560 | else { |
4561 | lua_pushboolean(L, 1); |
4562 | lua_insert(L, -(r + 1)); |
4563 | - return r + 1; /* return true + `resume' returns */ |
4564 | + return r + 1; /* return true + 'resume' returns */ |
4565 | } |
4566 | } |
4567 | |
4568 | @@ -102,8 +109,7 @@ |
4569 | |
4570 | |
4571 | static int luaB_costatus (lua_State *L) { |
4572 | - lua_State *co = lua_tothread(L, 1); |
4573 | - luaL_argcheck(L, co, 1, "coroutine expected"); |
4574 | + lua_State *co = getco(L); |
4575 | if (L == co) lua_pushliteral(L, "running"); |
4576 | else { |
4577 | switch (lua_status(co)) { |
4578 | @@ -129,6 +135,12 @@ |
4579 | } |
4580 | |
4581 | |
4582 | +static int luaB_yieldable (lua_State *L) { |
4583 | + lua_pushboolean(L, lua_isyieldable(L)); |
4584 | + return 1; |
4585 | +} |
4586 | + |
4587 | + |
4588 | static int luaB_corunning (lua_State *L) { |
4589 | int ismain = lua_pushthread(L); |
4590 | lua_pushboolean(L, ismain); |
4591 | @@ -143,6 +155,7 @@ |
4592 | {"status", luaB_costatus}, |
4593 | {"wrap", luaB_cowrap}, |
4594 | {"yield", luaB_yield}, |
4595 | + {"isyieldable", luaB_yieldable}, |
4596 | {NULL, NULL} |
4597 | }; |
4598 | |
4599 | |
4600 | === modified file 'src/third_party/eris/lctype.c' |
4601 | --- src/third_party/eris/lctype.c 2014-02-22 14:47:28 +0000 |
4602 | +++ src/third_party/eris/lctype.c 2016-04-10 16:54:20 +0000 |
4603 | @@ -1,5 +1,5 @@ |
4604 | /* |
4605 | -** $Id: lctype.c,v 1.11.1.1 2013/04/12 18:48:47 roberto Exp $ |
4606 | +** $Id: lctype.c,v 1.12 2014/11/02 19:19:04 roberto Exp $ |
4607 | ** 'ctype' functions for Lua |
4608 | ** See Copyright Notice in lua.h |
4609 | */ |
4610 | @@ -7,6 +7,9 @@ |
4611 | #define lctype_c |
4612 | #define LUA_CORE |
4613 | |
4614 | +#include "lprefix.h" |
4615 | + |
4616 | + |
4617 | #include "lctype.h" |
4618 | |
4619 | #if !LUA_USE_CTYPE /* { */ |
4620 | |
4621 | === modified file 'src/third_party/eris/lctype.h' |
4622 | --- src/third_party/eris/lctype.h 2014-02-22 14:47:28 +0000 |
4623 | +++ src/third_party/eris/lctype.h 2016-04-10 16:54:20 +0000 |
4624 | @@ -1,5 +1,5 @@ |
4625 | /* |
4626 | -** $Id: lctype.h,v 1.12.1.1 2013/04/12 18:48:47 roberto Exp $ |
4627 | +** $Id: lctype.h,v 1.12 2011/07/15 12:50:29 roberto Exp $ |
4628 | ** 'ctype' functions for Lua |
4629 | ** See Copyright Notice in lua.h |
4630 | */ |
4631 | |
4632 | === modified file 'src/third_party/eris/ldblib.c' |
4633 | --- src/third_party/eris/ldblib.c 2014-02-22 14:47:28 +0000 |
4634 | +++ src/third_party/eris/ldblib.c 2016-04-10 16:54:20 +0000 |
4635 | @@ -1,25 +1,30 @@ |
4636 | /* |
4637 | -** $Id: ldblib.c,v 1.132.1.1 2013/04/12 18:48:47 roberto Exp $ |
4638 | +** $Id: ldblib.c,v 1.148 2015/01/02 12:52:22 roberto Exp $ |
4639 | ** Interface from Lua to its debug API |
4640 | ** See Copyright Notice in lua.h |
4641 | */ |
4642 | |
4643 | +#define ldblib_c |
4644 | +#define LUA_LIB |
4645 | + |
4646 | +#include "lprefix.h" |
4647 | + |
4648 | |
4649 | #include <stdio.h> |
4650 | #include <stdlib.h> |
4651 | #include <string.h> |
4652 | |
4653 | -#define ldblib_c |
4654 | -#define LUA_LIB |
4655 | - |
4656 | #include "lua.h" |
4657 | |
4658 | #include "lauxlib.h" |
4659 | #include "lualib.h" |
4660 | |
4661 | |
4662 | -#define HOOKKEY "_HKEY" |
4663 | - |
4664 | +/* |
4665 | +** The hook table at registry[&HOOKKEY] maps threads to their current |
4666 | +** hook function. (We only need the unique address of 'HOOKKEY'.) |
4667 | +*/ |
4668 | +static const int HOOKKEY = 0; |
4669 | |
4670 | |
4671 | static int db_getregistry (lua_State *L) { |
4672 | @@ -57,35 +62,20 @@ |
4673 | |
4674 | |
4675 | static int db_setuservalue (lua_State *L) { |
4676 | - if (lua_type(L, 1) == LUA_TLIGHTUSERDATA) |
4677 | - luaL_argerror(L, 1, "full userdata expected, got light userdata"); |
4678 | luaL_checktype(L, 1, LUA_TUSERDATA); |
4679 | - if (!lua_isnoneornil(L, 2)) |
4680 | - luaL_checktype(L, 2, LUA_TTABLE); |
4681 | + luaL_checkany(L, 2); |
4682 | lua_settop(L, 2); |
4683 | lua_setuservalue(L, 1); |
4684 | return 1; |
4685 | } |
4686 | |
4687 | |
4688 | -static void settabss (lua_State *L, const char *i, const char *v) { |
4689 | - lua_pushstring(L, v); |
4690 | - lua_setfield(L, -2, i); |
4691 | -} |
4692 | - |
4693 | - |
4694 | -static void settabsi (lua_State *L, const char *i, int v) { |
4695 | - lua_pushinteger(L, v); |
4696 | - lua_setfield(L, -2, i); |
4697 | -} |
4698 | - |
4699 | - |
4700 | -static void settabsb (lua_State *L, const char *i, int v) { |
4701 | - lua_pushboolean(L, v); |
4702 | - lua_setfield(L, -2, i); |
4703 | -} |
4704 | - |
4705 | - |
4706 | +/* |
4707 | +** Auxiliary function used by several library functions: check for |
4708 | +** an optional thread as function's first argument and set 'arg' with |
4709 | +** 1 if this argument is present (so that functions can skip it to |
4710 | +** access their other arguments) |
4711 | +*/ |
4712 | static lua_State *getthread (lua_State *L, int *arg) { |
4713 | if (lua_isthread(L, 1)) { |
4714 | *arg = 1; |
4715 | @@ -93,44 +83,70 @@ |
4716 | } |
4717 | else { |
4718 | *arg = 0; |
4719 | - return L; |
4720 | + return L; /* function will operate over current thread */ |
4721 | } |
4722 | } |
4723 | |
4724 | |
4725 | +/* |
4726 | +** Variations of 'lua_settable', used by 'db_getinfo' to put results |
4727 | +** from 'lua_getinfo' into result table. Key is always a string; |
4728 | +** value can be a string, an int, or a boolean. |
4729 | +*/ |
4730 | +static void settabss (lua_State *L, const char *k, const char *v) { |
4731 | + lua_pushstring(L, v); |
4732 | + lua_setfield(L, -2, k); |
4733 | +} |
4734 | + |
4735 | +static void settabsi (lua_State *L, const char *k, int v) { |
4736 | + lua_pushinteger(L, v); |
4737 | + lua_setfield(L, -2, k); |
4738 | +} |
4739 | + |
4740 | +static void settabsb (lua_State *L, const char *k, int v) { |
4741 | + lua_pushboolean(L, v); |
4742 | + lua_setfield(L, -2, k); |
4743 | +} |
4744 | + |
4745 | + |
4746 | +/* |
4747 | +** In function 'db_getinfo', the call to 'lua_getinfo' may push |
4748 | +** results on the stack; later it creates the result table to put |
4749 | +** these objects. Function 'treatstackoption' puts the result from |
4750 | +** 'lua_getinfo' on top of the result table so that it can call |
4751 | +** 'lua_setfield'. |
4752 | +*/ |
4753 | static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) { |
4754 | - if (L == L1) { |
4755 | - lua_pushvalue(L, -2); |
4756 | - lua_remove(L, -3); |
4757 | - } |
4758 | + if (L == L1) |
4759 | + lua_rotate(L, -2, 1); /* exchange object and table */ |
4760 | else |
4761 | - lua_xmove(L1, L, 1); |
4762 | - lua_setfield(L, -2, fname); |
4763 | + lua_xmove(L1, L, 1); /* move object to the "main" stack */ |
4764 | + lua_setfield(L, -2, fname); /* put object into table */ |
4765 | } |
4766 | |
4767 | |
4768 | +/* |
4769 | +** Calls 'lua_getinfo' and collects all results in a new table. |
4770 | +*/ |
4771 | static int db_getinfo (lua_State *L) { |
4772 | lua_Debug ar; |
4773 | int arg; |
4774 | lua_State *L1 = getthread(L, &arg); |
4775 | const char *options = luaL_optstring(L, arg+2, "flnStu"); |
4776 | - if (lua_isnumber(L, arg+1)) { |
4777 | - if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) { |
4778 | + if (lua_isfunction(L, arg + 1)) { /* info about a function? */ |
4779 | + options = lua_pushfstring(L, ">%s", options); /* add '>' to 'options' */ |
4780 | + lua_pushvalue(L, arg + 1); /* move function to 'L1' stack */ |
4781 | + lua_xmove(L, L1, 1); |
4782 | + } |
4783 | + else { /* stack level */ |
4784 | + if (!lua_getstack(L1, (int)luaL_checkinteger(L, arg + 1), &ar)) { |
4785 | lua_pushnil(L); /* level out of range */ |
4786 | return 1; |
4787 | } |
4788 | } |
4789 | - else if (lua_isfunction(L, arg+1)) { |
4790 | - lua_pushfstring(L, ">%s", options); |
4791 | - options = lua_tostring(L, -1); |
4792 | - lua_pushvalue(L, arg+1); |
4793 | - lua_xmove(L, L1, 1); |
4794 | - } |
4795 | - else |
4796 | - return luaL_argerror(L, arg+1, "function or level expected"); |
4797 | if (!lua_getinfo(L1, options, &ar)) |
4798 | return luaL_argerror(L, arg+2, "invalid option"); |
4799 | - lua_createtable(L, 0, 2); |
4800 | + lua_newtable(L); /* table to collect results */ |
4801 | if (strchr(options, 'S')) { |
4802 | settabss(L, "source", ar.source); |
4803 | settabss(L, "short_src", ar.short_src); |
4804 | @@ -164,20 +180,21 @@ |
4805 | lua_State *L1 = getthread(L, &arg); |
4806 | lua_Debug ar; |
4807 | const char *name; |
4808 | - int nvar = luaL_checkint(L, arg+2); /* local-variable index */ |
4809 | + int nvar = (int)luaL_checkinteger(L, arg + 2); /* local-variable index */ |
4810 | if (lua_isfunction(L, arg + 1)) { /* function argument? */ |
4811 | lua_pushvalue(L, arg + 1); /* push function */ |
4812 | lua_pushstring(L, lua_getlocal(L, NULL, nvar)); /* push local name */ |
4813 | - return 1; |
4814 | + return 1; /* return only name (there is no value) */ |
4815 | } |
4816 | else { /* stack-level argument */ |
4817 | - if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */ |
4818 | + int level = (int)luaL_checkinteger(L, arg + 1); |
4819 | + if (!lua_getstack(L1, level, &ar)) /* out of range? */ |
4820 | return luaL_argerror(L, arg+1, "level out of range"); |
4821 | name = lua_getlocal(L1, &ar, nvar); |
4822 | if (name) { |
4823 | - lua_xmove(L1, L, 1); /* push local value */ |
4824 | + lua_xmove(L1, L, 1); /* move local value */ |
4825 | lua_pushstring(L, name); /* push name */ |
4826 | - lua_pushvalue(L, -2); /* re-order */ |
4827 | + lua_rotate(L, -2, 1); /* re-order */ |
4828 | return 2; |
4829 | } |
4830 | else { |
4831 | @@ -190,26 +207,35 @@ |
4832 | |
4833 | static int db_setlocal (lua_State *L) { |
4834 | int arg; |
4835 | + const char *name; |
4836 | lua_State *L1 = getthread(L, &arg); |
4837 | lua_Debug ar; |
4838 | - if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */ |
4839 | + int level = (int)luaL_checkinteger(L, arg + 1); |
4840 | + int nvar = (int)luaL_checkinteger(L, arg + 2); |
4841 | + if (!lua_getstack(L1, level, &ar)) /* out of range? */ |
4842 | return luaL_argerror(L, arg+1, "level out of range"); |
4843 | luaL_checkany(L, arg+3); |
4844 | lua_settop(L, arg+3); |
4845 | lua_xmove(L, L1, 1); |
4846 | - lua_pushstring(L, lua_setlocal(L1, &ar, luaL_checkint(L, arg+2))); |
4847 | + name = lua_setlocal(L1, &ar, nvar); |
4848 | + if (name == NULL) |
4849 | + lua_pop(L1, 1); /* pop value (if not popped by 'lua_setlocal') */ |
4850 | + lua_pushstring(L, name); |
4851 | return 1; |
4852 | } |
4853 | |
4854 | |
4855 | +/* |
4856 | +** get (if 'get' is true) or set an upvalue from a closure |
4857 | +*/ |
4858 | static int auxupvalue (lua_State *L, int get) { |
4859 | const char *name; |
4860 | - int n = luaL_checkint(L, 2); |
4861 | - luaL_checktype(L, 1, LUA_TFUNCTION); |
4862 | + int n = (int)luaL_checkinteger(L, 2); /* upvalue index */ |
4863 | + luaL_checktype(L, 1, LUA_TFUNCTION); /* closure */ |
4864 | name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n); |
4865 | if (name == NULL) return 0; |
4866 | lua_pushstring(L, name); |
4867 | - lua_insert(L, -(get+1)); |
4868 | + lua_insert(L, -(get+1)); /* no-op if get is false */ |
4869 | return get + 1; |
4870 | } |
4871 | |
4872 | @@ -225,13 +251,15 @@ |
4873 | } |
4874 | |
4875 | |
4876 | +/* |
4877 | +** Check whether a given upvalue from a given closure exists and |
4878 | +** returns its index |
4879 | +*/ |
4880 | static int checkupval (lua_State *L, int argf, int argnup) { |
4881 | - lua_Debug ar; |
4882 | - int nup = luaL_checkint(L, argnup); |
4883 | - luaL_checktype(L, argf, LUA_TFUNCTION); |
4884 | - lua_pushvalue(L, argf); |
4885 | - lua_getinfo(L, ">u", &ar); |
4886 | - luaL_argcheck(L, 1 <= nup && nup <= ar.nups, argnup, "invalid upvalue index"); |
4887 | + int nup = (int)luaL_checkinteger(L, argnup); /* upvalue index */ |
4888 | + luaL_checktype(L, argf, LUA_TFUNCTION); /* closure */ |
4889 | + luaL_argcheck(L, (lua_getupvalue(L, argf, nup) != NULL), argnup, |
4890 | + "invalid upvalue index"); |
4891 | return nup; |
4892 | } |
4893 | |
4894 | @@ -253,26 +281,29 @@ |
4895 | } |
4896 | |
4897 | |
4898 | -#define gethooktable(L) luaL_getsubtable(L, LUA_REGISTRYINDEX, HOOKKEY) |
4899 | - |
4900 | - |
4901 | +/* |
4902 | +** Call hook function registered at hook table for the current |
4903 | +** thread (if there is one) |
4904 | +*/ |
4905 | static void hookf (lua_State *L, lua_Debug *ar) { |
4906 | static const char *const hooknames[] = |
4907 | {"call", "return", "line", "count", "tail call"}; |
4908 | - gethooktable(L); |
4909 | + lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY); |
4910 | lua_pushthread(L); |
4911 | - lua_rawget(L, -2); |
4912 | - if (lua_isfunction(L, -1)) { |
4913 | - lua_pushstring(L, hooknames[(int)ar->event]); |
4914 | + if (lua_rawget(L, -2) == LUA_TFUNCTION) { /* is there a hook function? */ |
4915 | + lua_pushstring(L, hooknames[(int)ar->event]); /* push event name */ |
4916 | if (ar->currentline >= 0) |
4917 | - lua_pushinteger(L, ar->currentline); |
4918 | + lua_pushinteger(L, ar->currentline); /* push current line */ |
4919 | else lua_pushnil(L); |
4920 | lua_assert(lua_getinfo(L, "lS", ar)); |
4921 | - lua_call(L, 2, 0); |
4922 | + lua_call(L, 2, 0); /* call hook function */ |
4923 | } |
4924 | } |
4925 | |
4926 | |
4927 | +/* |
4928 | +** Convert a string mask (for 'sethook') into a bit mask |
4929 | +*/ |
4930 | static int makemask (const char *smask, int count) { |
4931 | int mask = 0; |
4932 | if (strchr(smask, 'c')) mask |= LUA_MASKCALL; |
4933 | @@ -283,6 +314,9 @@ |
4934 | } |
4935 | |
4936 | |
4937 | +/* |
4938 | +** Convert a bit mask (for 'gethook') into a string mask |
4939 | +*/ |
4940 | static char *unmakemask (int mask, char *smask) { |
4941 | int i = 0; |
4942 | if (mask & LUA_MASKCALL) smask[i++] = 'c'; |
4943 | @@ -297,26 +331,29 @@ |
4944 | int arg, mask, count; |
4945 | lua_Hook func; |
4946 | lua_State *L1 = getthread(L, &arg); |
4947 | - if (lua_isnoneornil(L, arg+1)) { |
4948 | + if (lua_isnoneornil(L, arg+1)) { /* no hook? */ |
4949 | lua_settop(L, arg+1); |
4950 | func = NULL; mask = 0; count = 0; /* turn off hooks */ |
4951 | } |
4952 | else { |
4953 | const char *smask = luaL_checkstring(L, arg+2); |
4954 | luaL_checktype(L, arg+1, LUA_TFUNCTION); |
4955 | - count = luaL_optint(L, arg+3, 0); |
4956 | + count = (int)luaL_optinteger(L, arg + 3, 0); |
4957 | func = hookf; mask = makemask(smask, count); |
4958 | } |
4959 | - if (gethooktable(L) == 0) { /* creating hook table? */ |
4960 | + if (lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY) == LUA_TNIL) { |
4961 | + lua_createtable(L, 0, 2); /* create a hook table */ |
4962 | + lua_pushvalue(L, -1); |
4963 | + lua_rawsetp(L, LUA_REGISTRYINDEX, &HOOKKEY); /* set it in position */ |
4964 | lua_pushstring(L, "k"); |
4965 | lua_setfield(L, -2, "__mode"); /** hooktable.__mode = "k" */ |
4966 | lua_pushvalue(L, -1); |
4967 | lua_setmetatable(L, -2); /* setmetatable(hooktable) = hooktable */ |
4968 | } |
4969 | - lua_pushthread(L1); lua_xmove(L1, L, 1); |
4970 | - lua_pushvalue(L, arg+1); |
4971 | - lua_rawset(L, -3); /* set new hook */ |
4972 | - lua_sethook(L1, func, mask, count); /* set hooks */ |
4973 | + lua_pushthread(L1); lua_xmove(L1, L, 1); /* key (thread) */ |
4974 | + lua_pushvalue(L, arg + 1); /* value (hook function) */ |
4975 | + lua_rawset(L, -3); /* hooktable[L1] = new Lua hook */ |
4976 | + lua_sethook(L1, func, mask, count); |
4977 | return 0; |
4978 | } |
4979 | |
4980 | @@ -327,16 +364,18 @@ |
4981 | char buff[5]; |
4982 | int mask = lua_gethookmask(L1); |
4983 | lua_Hook hook = lua_gethook(L1); |
4984 | - if (hook != NULL && hook != hookf) /* external hook? */ |
4985 | + if (hook == NULL) /* no hook? */ |
4986 | + lua_pushnil(L); |
4987 | + else if (hook != hookf) /* external hook? */ |
4988 | lua_pushliteral(L, "external hook"); |
4989 | - else { |
4990 | - gethooktable(L); |
4991 | + else { /* hook table must exist */ |
4992 | + lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY); |
4993 | lua_pushthread(L1); lua_xmove(L1, L, 1); |
4994 | - lua_rawget(L, -2); /* get hook */ |
4995 | + lua_rawget(L, -2); /* 1st result = hooktable[L1] */ |
4996 | lua_remove(L, -2); /* remove hook table */ |
4997 | } |
4998 | - lua_pushstring(L, unmakemask(mask, buff)); |
4999 | - lua_pushinteger(L, lua_gethookcount(L1)); |
5000 | + lua_pushstring(L, unmakemask(mask, buff)); /* 2nd result = mask */ |
We're going to break savegame compatibility for this release anyway. What's holding us from updating to Lua 5.3 eris?