Lua diffu-lua-5.4.0-work2-alpha-rc1


Makefile

@@ -36,7 +36,7 @@
 # == END OF USER SETTINGS -- NO NEED TO CHANGE ANYTHING BELOW THIS LINE =======
 
 # Convenience platforms targets.
-PLATS= aix bsd c89 freebsd generic linux linux-readline macosx mingw posix solaris
+PLATS= aix bsd c89 freebsd generic guess linux linux-readline macosx mingw posix solaris
 
 # What to install.
 TO_BIN= lua luac

@@ -109,6 +109,6 @@
 	@echo "includedir=$(INSTALL_INC)"
 
 # list targets that do not create files (but not all makes understand .PHONY)
-.PHONY: all $(PLATS) clean test install local none dummy echo pecho lecho
+.PHONY: all $(PLATS) clean test install uninstall local none dummy echo pc
 
 # (end of Makefile)

README

@@ -1,5 +1,5 @@
 
-This is Lua 5.4.0 (work2), released on 18 Jun 2018.
+This is Lua 5.4.0 (alpha), released on 29 May 2019.
 
 For installation instructions, license details, and
 further information about Lua, see doc/readme.html.

doc/contents.html

@@ -32,7 +32,7 @@
 
 <P>
 <SMALL>
-Copyright &copy; 2018 Lua.org, PUC-Rio.
+Copyright &copy; 2019 Lua.org, PUC-Rio.
 Freely available under the terms of the
 <A HREF="http://www.lua.org/license.html">Lua license</A>.
 </SMALL>

@@ -70,6 +70,7 @@
 <LI><A HREF="manual.html#3.3.5">3.3.5 &ndash; For Statement</A>
 <LI><A HREF="manual.html#3.3.6">3.3.6 &ndash; Function Calls as Statements</A>
 <LI><A HREF="manual.html#3.3.7">3.3.7 &ndash; Local Declarations</A>
+<LI><A HREF="manual.html#3.3.8">3.3.8 &ndash; To-be-closed Variables</A>
 </UL>
 <LI><A HREF="manual.html#3.4">3.4 &ndash; Expressions</A>
 <UL>

@@ -106,7 +107,7 @@
 <LI><A HREF="manual.html#5.1">5.1 &ndash; Functions and Types</A>
 </UL>
 <P>
-<LI><A HREF="manual.html#6">6 &ndash; Standard Libraries</A>
+<LI><A HREF="manual.html#6">6 &ndash; The Standard Libraries</A>
 <UL>
 <LI><A HREF="manual.html#6.1">6.1 &ndash; Basic Functions</A>
 <LI><A HREF="manual.html#6.2">6.2 &ndash; Coroutine Manipulation</A>

@@ -128,9 +129,9 @@
 <P>
 <LI><A HREF="manual.html#8">8 &ndash; Incompatibilities with the Previous Version</A>
 <UL>
-<LI><A HREF="manual.html#8.1">8.1 &ndash; Changes in the Language</A>
-<LI><A HREF="manual.html#8.2">8.2 &ndash; Changes in the Libraries</A>
-<LI><A HREF="manual.html#8.3">8.3 &ndash; Changes in the API</A>
+<LI><A HREF="manual.html#8.1">8.1 &ndash; Incompatibilities in the Language</A>
+<LI><A HREF="manual.html#8.2">8.2 &ndash; Incompatibilities in the Libraries</A>
+<LI><A HREF="manual.html#8.3">8.3 &ndash; Incompatibilities in the API</A>
 </UL>
 <P>
 <LI><A HREF="manual.html#9">9 &ndash; The Complete Syntax of Lua</A>

@@ -167,12 +168,14 @@
 <A HREF="manual.html#pdf-tonumber">tonumber</A><BR>
 <A HREF="manual.html#pdf-tostring">tostring</A><BR>
 <A HREF="manual.html#pdf-type">type</A><BR>
+<A HREF="manual.html#pdf-warn">warn</A><BR>
 <A HREF="manual.html#pdf-xpcall">xpcall</A><BR>
 
 <P>
 <A HREF="manual.html#6.2">coroutine</A><BR>
 <A HREF="manual.html#pdf-coroutine.create">coroutine.create</A><BR>
 <A HREF="manual.html#pdf-coroutine.isyieldable">coroutine.isyieldable</A><BR>
+<A HREF="manual.html#pdf-coroutine.kill">coroutine.kill</A><BR>
 <A HREF="manual.html#pdf-coroutine.resume">coroutine.resume</A><BR>
 <A HREF="manual.html#pdf-coroutine.running">coroutine.running</A><BR>
 <A HREF="manual.html#pdf-coroutine.status">coroutine.status</A><BR>

@@ -344,6 +347,7 @@
 <A HREF="manual.html#lua_Reader">lua_Reader</A><BR>
 <A HREF="manual.html#lua_State">lua_State</A><BR>
 <A HREF="manual.html#lua_Unsigned">lua_Unsigned</A><BR>
+<A HREF="manual.html#lua_WarnFunction">lua_WarnFunction</A><BR>
 <A HREF="manual.html#lua_Writer">lua_Writer</A><BR>
 
 <P>

@@ -429,6 +433,7 @@
 <A HREF="manual.html#lua_register">lua_register</A><BR>
 <A HREF="manual.html#lua_remove">lua_remove</A><BR>
 <A HREF="manual.html#lua_replace">lua_replace</A><BR>
+<A HREF="manual.html#lua_resetthread">lua_resetthread</A><BR>
 <A HREF="manual.html#lua_resume">lua_resume</A><BR>
 <A HREF="manual.html#lua_rotate">lua_rotate</A><BR>
 <A HREF="manual.html#lua_setallocf">lua_setallocf</A><BR>

@@ -442,10 +447,12 @@
 <A HREF="manual.html#lua_settable">lua_settable</A><BR>
 <A HREF="manual.html#lua_settop">lua_settop</A><BR>
 <A HREF="manual.html#lua_setupvalue">lua_setupvalue</A><BR>
+<A HREF="manual.html#lua_setwarnf">lua_setwarnf</A><BR>
 <A HREF="manual.html#lua_status">lua_status</A><BR>
 <A HREF="manual.html#lua_stringtonumber">lua_stringtonumber</A><BR>
 <A HREF="manual.html#lua_toboolean">lua_toboolean</A><BR>
 <A HREF="manual.html#lua_tocfunction">lua_tocfunction</A><BR>
+<A HREF="manual.html#lua_toclose">lua_toclose</A><BR>
 <A HREF="manual.html#lua_tointeger">lua_tointeger</A><BR>
 <A HREF="manual.html#lua_tointegerx">lua_tointegerx</A><BR>
 <A HREF="manual.html#lua_tolstring">lua_tolstring</A><BR>

@@ -461,6 +468,7 @@
 <A HREF="manual.html#lua_upvalueindex">lua_upvalueindex</A><BR>
 <A HREF="manual.html#lua_upvaluejoin">lua_upvaluejoin</A><BR>
 <A HREF="manual.html#lua_version">lua_version</A><BR>
+<A HREF="manual.html#lua_warning">lua_warning</A><BR>
 <A HREF="manual.html#lua_xmove">lua_xmove</A><BR>
 <A HREF="manual.html#lua_yield">lua_yield</A><BR>
 <A HREF="manual.html#lua_yieldk">lua_yieldk</A><BR>

@@ -475,14 +483,18 @@
 
 <P>
 <A HREF="manual.html#luaL_addchar">luaL_addchar</A><BR>
+<A HREF="manual.html#luaL_addgsub">luaL_addgsub</A><BR>
 <A HREF="manual.html#luaL_addlstring">luaL_addlstring</A><BR>
 <A HREF="manual.html#luaL_addsize">luaL_addsize</A><BR>
 <A HREF="manual.html#luaL_addstring">luaL_addstring</A><BR>
 <A HREF="manual.html#luaL_addvalue">luaL_addvalue</A><BR>
 <A HREF="manual.html#luaL_argcheck">luaL_argcheck</A><BR>
 <A HREF="manual.html#luaL_argerror">luaL_argerror</A><BR>
+<A HREF="manual.html#luaL_argexpected">luaL_argexpected</A><BR>
+<A HREF="manual.html#luaL_buffaddr">luaL_buffaddr</A><BR>
 <A HREF="manual.html#luaL_buffinit">luaL_buffinit</A><BR>
 <A HREF="manual.html#luaL_buffinitsize">luaL_buffinitsize</A><BR>
+<A HREF="manual.html#luaL_bufflen">luaL_bufflen</A><BR>
 <A HREF="manual.html#luaL_callmeta">luaL_callmeta</A><BR>
 <A HREF="manual.html#luaL_checkany">luaL_checkany</A><BR>
 <A HREF="manual.html#luaL_checkinteger">luaL_checkinteger</A><BR>

@@ -530,6 +542,7 @@
 <A HREF="manual.html#luaL_testudata">luaL_testudata</A><BR>
 <A HREF="manual.html#luaL_tolstring">luaL_tolstring</A><BR>
 <A HREF="manual.html#luaL_traceback">luaL_traceback</A><BR>
+<A HREF="manual.html#luaL_typeerror">luaL_typeerror</A><BR>
 <A HREF="manual.html#luaL_typename">luaL_typename</A><BR>
 <A HREF="manual.html#luaL_unref">luaL_unref</A><BR>
 <A HREF="manual.html#luaL_where">luaL_where</A><BR>

@@ -551,7 +564,6 @@
 <P>
 <A HREF="manual.html#pdf-LUA_ERRERR">LUA_ERRERR</A><BR>
 <A HREF="manual.html#pdf-LUA_ERRFILE">LUA_ERRFILE</A><BR>
-<A HREF="manual.html#pdf-LUA_ERRGCMM">LUA_ERRGCMM</A><BR>
 <A HREF="manual.html#pdf-LUA_ERRMEM">LUA_ERRMEM</A><BR>
 <A HREF="manual.html#pdf-LUA_ERRRUN">LUA_ERRRUN</A><BR>
 <A HREF="manual.html#pdf-LUA_ERRSYNTAX">LUA_ERRSYNTAX</A><BR>

@@ -560,6 +572,7 @@
 <A HREF="manual.html#pdf-LUA_HOOKLINE">LUA_HOOKLINE</A><BR>
 <A HREF="manual.html#pdf-LUA_HOOKRET">LUA_HOOKRET</A><BR>
 <A HREF="manual.html#pdf-LUA_HOOKTAILCALL">LUA_HOOKTAILCALL</A><BR>
+<A HREF="manual.html#pdf-LUAL_BUFFERSIZE">LUAL_BUFFERSIZE</A><BR>
 <A HREF="manual.html#pdf-LUA_MASKCALL">LUA_MASKCALL</A><BR>
 <A HREF="manual.html#pdf-LUA_MASKCOUNT">LUA_MASKCOUNT</A><BR>
 <A HREF="manual.html#pdf-LUA_MASKLINE">LUA_MASKLINE</A><BR>

@@ -603,7 +616,6 @@
 <A HREF="manual.html#pdf-LUA_TUSERDATA">LUA_TUSERDATA</A><BR>
 <A HREF="manual.html#pdf-LUA_USE_APICHECK">LUA_USE_APICHECK</A><BR>
 <A HREF="manual.html#pdf-LUA_YIELD">LUA_YIELD</A><BR>
-<A HREF="manual.html#pdf-LUAL_BUFFERSIZE">LUAL_BUFFERSIZE</A><BR>
 
 </TD>
 </TR>

@@ -611,10 +623,10 @@
 
 <P CLASS="footer">
 Last update:
-Mon Jun 18 17:11:17 -03 2018
+Wed May 29 08:06:44 -03 2019
 </P>
 <!--
-Last change: revised for Lua 5.4.0 (work2)
+Last change: revised for Lua 5.4.0 (alpha)
 -->
 
 </BODY>

doc/manual.html

@@ -19,7 +19,7 @@
 
 <P>
 <SMALL>
-Copyright &copy; 2018 Lua.org, PUC-Rio.
+Copyright &copy; 2019 Lua.org, PUC-Rio.
 Freely available under the terms of the
 <a href="http://www.lua.org/license.html">Lua license</a>.
 </SMALL>

@@ -35,7 +35,7 @@
 <!-- ====================================================================== -->
 <p>
 
-<!-- $Id: manual.of,v 1.175 2018/06/18 19:17:35 roberto Exp $ -->
+<!-- $Id: manual.of $ -->
 
 
 

@@ -56,7 +56,7 @@
 runs by interpreting bytecode with a register-based
 virtual machine,
 and has automatic memory management with
-incremental garbage collection,
+a generational garbage collection,
 making it ideal for configuration, scripting,
 and rapid prototyping.
 

@@ -134,31 +134,16 @@
 <em>thread</em>, and <em>table</em>.
 The type <em>nil</em> has one single value, <b>nil</b>,
 whose main property is to be different from any other value;
-it usually represents the absence of a useful value.
+it often represents the absence of a useful value.
 The type <em>boolean</em> has two values, <b>false</b> and <b>true</b>.
 Both <b>nil</b> and <b>false</b> make a condition false;
 any other value makes it true.
-The type <em>number</em> represents both
-integer numbers and real (floating-point) numbers.
-The type <em>string</em> represents immutable sequences of bytes.
-
-Lua is 8-bit clean:
-strings can contain any 8-bit value,
-including embedded zeros ('<code>\0</code>').
-Lua is also encoding-agnostic;
-it makes no assumptions about the contents of a string.
 
 
 <p>
-The type <em>number</em> uses two internal representations,
-or two subtypes,
-one called <em>integer</em> and the other called <em>float</em>.
-Lua has explicit rules about when each representation is used,
-but it also converts between them automatically as needed (see <a href="#3.4.3">&sect;3.4.3</a>).
-Therefore,
-the programmer may choose to mostly ignore the difference
-between integers and floats
-or to assume complete control over the representation of each number.
+The type <em>number</em> represents both
+integer numbers and real (floating-point) numbers,
+using two subtypes: <em>integer</em> and <em>float</em>.
 Standard Lua uses 64-bit integers and double-precision (64-bit) floats,
 but you can also compile Lua so that it
 uses 32-bit integers and/or single-precision (32-bit) floats.

@@ -169,6 +154,26 @@
 
 
 <p>
+Lua has explicit rules about when each subtype is used,
+but it also converts between them automatically as needed (see <a href="#3.4.3">&sect;3.4.3</a>).
+Therefore,
+the programmer may choose to mostly ignore the difference
+between integers and floats
+or to assume complete control over the representation of each number.
+
+
+<p>
+The type <em>string</em> represents immutable sequences of bytes.
+
+Lua is 8-bit clean:
+strings can contain any 8-bit value,
+including embedded zeros ('<code>\0</code>').
+Lua is also encoding-agnostic;
+it makes no assumptions about the contents of a string.
+The length of any string in Lua must fit in a Lua integer.
+
+
+<p>
 Lua can call (and manipulate) functions written in Lua and
 functions written in C (see <a href="#3.4.10">&sect;3.4.10</a>).
 Both are represented by the type <em>function</em>.

@@ -190,7 +195,8 @@
 (see <a href="#2.4">&sect;2.4</a>).
 Userdata values cannot be created or modified in Lua,
 only through the C&nbsp;API.
-This guarantees the integrity of data owned by the host program.
+This guarantees the integrity of data owned by
+the host program and C&nbsp;libraries.
 
 
 <p>

@@ -207,10 +213,10 @@
 but any Lua value except <b>nil</b> and NaN.
 (<em>Not a Number</em> is a special floating-point value
 used by the IEEE 754 standard to represent
-undefined or unrepresentable numerical results, such as <code>0/0</code>.)
+undefined numerical results, such as <code>0/0</code>.)
 Tables can be <em>heterogeneous</em>;
 that is, they can contain values of all types (except <b>nil</b>).
-Any key with value <b>nil</b> is not considered part of the table.
+Any key associated to the value <b>nil</b> is not considered part of the table.
 Conversely, any key that is not part of a table has
 an associated value <b>nil</b>.
 

@@ -246,14 +252,10 @@
 are equal to their respective integers
 (e.g., <code>1.0 == 1</code>).
 To avoid ambiguities,
-any float with integral value used as a key
-is converted to its respective integer.
+any float used as a key that is equal to an integer
+is converted to that integer.
 For instance, if you write <code>a[2.0] = true</code>,
-the actual key inserted into the table will be the
-integer <code>2</code>.
-(On the other hand,
-2 and "<code>2</code>" are different Lua values and therefore
-denote different table entries.)
+the actual key inserted into the table will be the integer <code>2</code>.
 
 
 <p>

@@ -267,7 +269,7 @@
 
 <p>
 The library function <a href="#pdf-type"><code>type</code></a> returns a string describing the type
-of a given value (see <a href="#6.1">&sect;6.1</a>).
+of a given value (see <a href="#pdf-type"><code>type</code></a>).
 
 
 

@@ -276,7 +278,7 @@
 <h2>2.2 &ndash; <a name="2.2">Environments and the Global Environment</a></h2>
 
 <p>
-As will be discussed in <a href="#3.2">&sect;3.2</a> and <a href="#3.3.3">&sect;3.3.3</a>,
+As we will discuss further in <a href="#3.2">&sect;3.2</a> and <a href="#3.3.3">&sect;3.3.3</a>,
 any reference to a free name
 (that is, a name not bound to any declaration) <code>var</code>
 is syntactically translated to <code>_ENV.var</code>.

@@ -304,7 +306,8 @@
 Lua keeps a distinguished environment called the <em>global environment</em>.
 This value is kept at a special index in the C registry (see <a href="#4.5">&sect;4.5</a>).
 In Lua, the global variable <a href="#pdf-_G"><code>_G</code></a> is initialized with this same value.
-(<a href="#pdf-_G"><code>_G</code></a> is never used internally.)
+(<a href="#pdf-_G"><code>_G</code></a> is never used internally,
+so changing its value will affect only your own code.)
 
 
 <p>

@@ -313,7 +316,7 @@
 is the global environment (see <a href="#pdf-load"><code>load</code></a>).
 Therefore, by default,
 free names in Lua code refer to entries in the global environment
-(and, therefore, they are also called <em>global variables</em>).
+and, therefore, they are also called <em>global variables</em>.
 Moreover, all standard libraries are loaded in the global environment
 and some functions there operate on that environment.
 You can use <a href="#pdf-load"><code>load</code></a> (or <a href="#pdf-loadfile"><code>loadfile</code></a>)

@@ -377,6 +380,14 @@
 nor for errors while running finalizers.)
 
 
+<p>
+Lua also offers a system of <em>warnings</em> (see <a href="#pdf-warn"><code>warn</code></a>).
+Unlike errors, warnings do not interfere
+in any way with program execution.
+They typically only generate a message to the user,
+although this behavior can be adapted from C (see <a href="#lua_setwarnf"><code>lua_setwarnf</code></a>).
+
+
 
 
 

@@ -409,24 +420,18 @@
 You can query the metatable of any value
 using the <a href="#pdf-getmetatable"><code>getmetatable</code></a> function.
 Lua queries metamethods in metatables using a raw access (see <a href="#pdf-rawget"><code>rawget</code></a>).
-So, to retrieve the metamethod for event <code>ev</code> in object <code>o</code>,
-Lua does the equivalent to the following code:
 
-<pre>
-     rawget(getmetatable(<em>o</em>) or {}, "__<em>ev</em>")
-</pre>
 
 <p>
 You can replace the metatable of tables
 using the <a href="#pdf-setmetatable"><code>setmetatable</code></a> function.
-You cannot change the metatable of other types from Lua code
-(except by using the debug library (<a href="#6.10">&sect;6.10</a>));
-you should use the C&nbsp;API for that.
+You cannot change the metatable of other types from Lua code,
+except by using the debug library (<a href="#6.10">&sect;6.10</a>).
 
 
 <p>
-Tables and full userdata have individual metatables
-(although multiple tables and userdata can share their metatables).
+Tables and full userdata have individual metatables,
+although multiple tables and userdata can share their metatables.
 Values of all other types share one single metatable per type;
 that is, there is one single metatable for all numbers,
 one for all strings, etc.

@@ -462,8 +467,7 @@
 
 <li><b><code>__add</code>: </b>
 the addition (<code>+</code>) operation.
-If any operand for an addition is not a number
-(nor a string coercible to a number),
+If any operand for an addition is not a number,
 Lua will try to call a metamethod.
 First, Lua will check the first operand (even if it is valid).
 If that operand does not define a metamethod for <code>__add</code>,

@@ -517,7 +521,7 @@
 Behavior similar to the addition operation,
 except that Lua will try a metamethod
 if any operand is neither an integer
-nor a value coercible to an integer (see <a href="#3.4.3">&sect;3.4.3</a>).
+nor a float coercible to an integer (see <a href="#3.4.3">&sect;3.4.3</a>).
 </li>
 
 <li><b><code>__bor</code>: </b>

@@ -586,17 +590,7 @@
 
 <li><b><code>__le</code>: </b>
 the less equal (<code>&lt;=</code>) operation.
-Unlike other operations,
-the less-equal operation can use two different events.
-First, Lua looks for the <code>__le</code> metamethod in both operands,
-like in the less than operation.
-If it cannot find such a metamethod,
-then it will try the <code>__lt</code> metamethod,
-assuming that <code>a &lt;= b</code> is equivalent to <code>not (b &lt; a)</code>.
-As with the other comparison operators,
-the result is always a boolean.
-(This use of the <code>__lt</code> event can be removed in future versions;
-it is also slower than a real <code>__le</code> metamethod.)
+Behavior similar to the less than operation.
 </li>
 
 <li><b><code>__index</code>: </b>

@@ -616,8 +610,8 @@
 is the result of the operation.
 If it is a table,
 the final result is the result of indexing this table with <code>key</code>.
-(This indexing is regular, not raw,
-and therefore can trigger another metamethod.)
+This indexing is regular, not raw,
+and therefore can trigger another metamethod.
 </li>
 
 <li><b><code>__newindex</code>: </b>

@@ -635,8 +629,8 @@
 it is called with <code>table</code>, <code>key</code>, and <code>value</code> as arguments.
 If it is a table,
 Lua does an indexing assignment to this table with the same key and value.
-(This assignment is regular, not raw,
-and therefore can trigger another metamethod.)
+This assignment is regular, not raw,
+and therefore can trigger another metamethod.
 
 
 <p>

@@ -657,7 +651,7 @@
 followed by the arguments of the original call (<code>args</code>).
 All results of the call
 are the result of the operation.
-(This is the only metamethod that allows multiple results.)
+This is the only metamethod that allows multiple results.
 </li>
 
 </ul>

@@ -703,7 +697,7 @@
 <p>
 The default GC mode with the default parameters
 are adequate for most uses.
-Programs that waste a large proportion of its time
+However, programs that waste a large proportion of their time
 allocating and freeing memory can benefit from other settings.
 Keep in mind that the GC behavior is non-portable
 both across platforms and across different Lua releases;

@@ -712,10 +706,10 @@
 
 <p>
 You can change the GC mode and parameters by calling
-<a href="#lua_gc"><code>lua_gc</code></a> in C
+<a href="#lua_gc"><code>lua_gc</code></a> in&nbsp;C
 or <a href="#pdf-collectgarbage"><code>collectgarbage</code></a> in Lua.
 You can also use these functions to control
-the collector directly (e.g., stop and restart it).
+the collector directly (e.g., to stop and restart it).
 
 
 

@@ -738,7 +732,7 @@
 The collector starts a new cycle when the use of memory
 hits <em>n%</em> of the use after the previous collection.
 Larger values make the collector less aggressive.
-Values smaller than 100 mean the collector will not wait to
+Values equal to or less than 100 mean the collector will not wait to
 start a new cycle.
 A value of 200 means that the collector waits for the total memory in use
 to double before starting a new cycle.

@@ -747,14 +741,14 @@
 
 <p>
 The garbage-collector step multiplier
-controls the relative speed of the collector relative to
+controls the speed of the collector relative to
 memory allocation,
 that is,
 how many elements it marks or sweeps for each
 kilobyte of memory allocated.
 Larger values make the collector more aggressive but also increase
 the size of each incremental step.
-You should not use values smaller than 100,
+You should not use values less than 100,
 because they make the collector too slow and
 can result in the collector never finishing a cycle.
 The default value is 100;  the maximum value is 1000.

@@ -771,7 +765,7 @@
 A large value (e.g., 60) makes the collector a stop-the-world
 (non-incremental) collector.
 The default value is 13,
-which makes for steps of approximately 8&nbsp;Kbytes.
+which means steps of approximately 8&nbsp;Kbytes.
 
 
 

@@ -823,11 +817,13 @@
 You can set garbage-collector metamethods for tables
 and, using the C&nbsp;API,
 for full userdata (see <a href="#2.4">&sect;2.4</a>).
-These metamethods are also called <em>finalizers</em>.
+These metamethods, called <em>finalizers</em>,
+are called when the garbage collector detects that the
+corresponding table or userdata is unreachable.
 Finalizers allow you to coordinate Lua's garbage collection
-with external resource management
-(such as closing files, network or database connections,
-or freeing your own memory).
+with external resource management such as closing files,
+network or database connections,
+or freeing your own memory.
 
 
 <p>

@@ -842,22 +838,20 @@
 
 
 <p>
-When a marked object becomes garbage,
+When a marked object becomes unreachable,
 it is not collected immediately by the garbage collector.
 Instead, Lua puts it in a list.
 After the collection,
 Lua goes through that list.
 For each object in the list,
 it checks the object's <code>__gc</code> metamethod:
-If it is a function,
-Lua calls it with the object as its single argument;
-if the metamethod is not a function,
-Lua simply ignores it.
+If it is present,
+Lua calls it with the object as its single argument.
 
 
 <p>
 At the end of each garbage-collection cycle,
-the finalizers for objects are called in
+the finalizers are called in
 the reverse order that the objects were marked for finalization,
 among those collected in that cycle;
 that is, the first finalizer to be called is the one associated

@@ -891,6 +885,22 @@
 these marks have no effect.
 
 
+<p>
+Finalizers cannot yield.
+Except for that, they can do anything,
+such as raise errors, create new objects,
+or even run the garbage collector.
+However, because they can run in unpredictable times,
+it is good practice to restrict each finalizer
+to the minimum necessary to properly release
+its associated resource.
+
+
+<p>
+Any error while running a finalizer generates a warning;
+the error is not propagated.
+
+
 
 
 

@@ -947,8 +957,10 @@
 and therefore are not removed from weak tables
 (unless their associated values are collected).
 Although strings are subject to garbage collection,
-they do not have an explicit construction,
-and therefore are not removed from weak tables.
+they do not have an explicit construction and
+their equality is by value;
+they behave more like values than like objects.
+Therefore, they are not removed from weak tables.
 
 
 <p>

@@ -1015,7 +1027,10 @@
 <a href="#pdf-coroutine.resume"><code>coroutine.resume</code></a> returns <b>true</b>,
 plus any values returned by the coroutine main function.
 In case of errors, <a href="#pdf-coroutine.resume"><code>coroutine.resume</code></a> returns <b>false</b>
-plus an error object.
+plus the error object.
+In this case, the coroutine does not unwind its stack,
+so that it is possible to inspect it after the error
+with the debug API.
 
 
 <p>

@@ -1043,8 +1058,10 @@
 <a href="#pdf-coroutine.wrap"><code>coroutine.wrap</code></a> returns all the values returned by <a href="#pdf-coroutine.resume"><code>coroutine.resume</code></a>,
 except the first one (the boolean error code).
 Unlike <a href="#pdf-coroutine.resume"><code>coroutine.resume</code></a>,
-<a href="#pdf-coroutine.wrap"><code>coroutine.wrap</code></a> does not catch errors;
-any error is propagated to the caller.
+the function created by <a href="#pdf-coroutine.wrap"><code>coroutine.wrap</code></a>
+propagates any error to the caller.
+In this case,
+the function also kills the coroutine (see <a href="#pdf-coroutine.kill"><code>coroutine.kill</code></a>).
 
 
 <p>

@@ -1121,16 +1138,19 @@
 
 <p>
 Lua is a free-form language.
-It ignores spaces (including new lines) and comments
-between lexical elements (tokens),
-except as delimiters between names and keywords.
+It ignores spaces and comments between lexical elements (tokens),
+except as delimiters between two tokens.
+In source code,
+Lua recognizes as spaces the standard ASCII white-space
+characters space, form feed, newline,
+carriage return, horizontal tab, and vertical tab.
 
 
 <p>
 <em>Names</em>
 (also called <em>identifiers</em>)
-in Lua can be any string of letters,
-digits, and underscores,
+in Lua can be any string of Latin letters,
+Arabic-Indic digits, and underscores,
 not beginning with a digit and
 not being a reserved word.
 Identifiers are used to name variables, table fields, and labels.

@@ -1212,9 +1232,12 @@
 The UTF-8 encoding of a Unicode character
 can be inserted in a literal string with
 the escape sequence <code>\u{<em>XXX</em>}</code>
-(note the mandatory enclosing brackets),
+(with mandatory enclosing brackets),
 where <em>XXX</em> is a sequence of one or more hexadecimal digits
 representing the character code point.
+This code point can be any value less than <em>2<sup>31</sup></em>.
+(Lua uses the original UTF-8 specification here,
+which is not restricted to valid Unicode code points.)
 
 
 <p>

@@ -1239,12 +1262,11 @@
 (carriage return, newline, carriage return followed by newline,
 or newline followed by carriage return)
 is converted to a simple newline.
+When the opening long bracket is immediately followed by a newline,
+the newline is not included in the string.
 
 
 <p>
-For convenience,
-when the opening long bracket is immediately followed by a newline,
-the newline is not included in the string.
 As an example, in a system using ASCII
 (in which '<code>a</code>' is coded as&nbsp;97,
 newline is coded as&nbsp;10, and '<code>1</code>' is coded as&nbsp;49),

@@ -1265,10 +1287,10 @@
 Any byte in a literal string not
 explicitly affected by the previous rules represents itself.
 However, Lua opens files for parsing in text mode,
-and the system file functions may have problems with
+and the system's file functions may have problems with
 some control characters.
 So, it is safer to represent
-non-text data as a quoted literal with
+binary data as a quoted literal with
 explicit escape sequences for the non-text characters.
 
 

@@ -1282,11 +1304,18 @@
 Hexadecimal constants also accept an optional fractional part
 plus an optional binary exponent,
 marked by a letter '<code>p</code>' or '<code>P</code>'.
+
+
+<p>
 A numeric constant with a radix point or an exponent
 denotes a float;
 otherwise,
-if its value fits in an integer,
-it denotes an integer.
+if its value fits in an integer or it is a hexadecimal constant,
+it denotes an integer;
+otherwise (that is, a decimal integer numeral that overflows),
+it denotes a float.
+(Hexadecimal integer numerals that overflow <em>wrap around</em>;
+they always denote an integer value.)
 Examples of valid integer constants are
 
 <pre>

@@ -1328,7 +1357,7 @@
 <pre>
 	var ::= Name
 </pre><p>
-Name denotes identifiers, as defined in <a href="#3.1">&sect;3.1</a>.
+Name denotes identifiers (see <a href="#3.1">&sect;3.1</a>).
 
 
 <p>

@@ -1375,9 +1404,9 @@
 
 <p>
 Lua supports an almost conventional set of statements,
-similar to those in Pascal or C.
+similar to those in other conventional languages.
 This set includes
-assignments, control structures, function calls,
+blocks, assignments, control structures, function calls,
 and variable declarations.
 
 

@@ -1401,7 +1430,7 @@
 </pre>
 
 <p>
-Function calls and assignments
+Both function calls and assignments
 can start with an open parenthesis.
 This possibility leads to an ambiguity in Lua's grammar.
 Consider the following fragment:

@@ -1410,7 +1439,7 @@
      a = b + c
      (print or io.write)('done')
 </pre><p>
-The grammar could see it in two ways:
+The grammar could see this fragment in two ways:
 
 <pre>
      a = b + c(print or io.write)('done')

@@ -1479,7 +1508,7 @@
 
 <p>
 Chunks can also be precompiled into binary form;
-see program <code>luac</code> and function <a href="#pdf-string.dump"><code>string.dump</code></a> for details.
+see the program <code>luac</code> and the function <a href="#pdf-string.dump"><code>string.dump</code></a> for details.
 Programs in source and compiled forms are interchangeable;
 Lua automatically detects the file type and acts accordingly (see <a href="#pdf-load"><code>load</code></a>).
 

@@ -1511,7 +1540,7 @@
 If there are more values than needed,
 the excess values are thrown away.
 If there are fewer values than needed,
-the list is extended with as many  <b>nil</b>'s as needed.
+the list is extended with <b>nil</b>'s.
 If the list of expressions ends with a function call,
 then all values returned by that call enter the list of values,
 before the adjustment

@@ -1580,7 +1609,7 @@
 control structure can return any value.
 Both <b>false</b> and <b>nil</b> test false.
 All values different from <b>nil</b> and <b>false</b> test true.
-(In particular, the number 0 and the empty string also test true).
+In particular, the number 0 and the empty string also test true.
 
 
 <p>

@@ -1606,11 +1635,12 @@
 
 <p>
 A label is visible in the entire block where it is defined,
-except
-inside nested blocks where a label with the same name is defined and
-inside nested functions.
+except inside nested functions.
 A goto may jump to any visible label as long as it does not
 enter into the scope of a local variable.
+A label should not be declared
+where a label with the same name is visible,
+even if this other label has been declared in an enclosing block.
 
 
 <p>

@@ -1633,7 +1663,7 @@
 <p>
 The <b>return</b> statement is used to return values
 from a function or a chunk
-(which is an anonymous function).
+(which is handled as an anonymous function).
 
 Functions can return more than one value,
 so the syntax for the <b>return</b> statement is

@@ -1645,7 +1675,7 @@
 <p>
 The <b>return</b> statement can only be written
 as the last statement of a block.
-If it is really necessary to <b>return</b> in the middle of a block,
+If it is necessary to <b>return</b> in the middle of a block,
 then an explicit inner block can be used,
 as in the idiom <code>do return end</code>,
 because now <b>return</b> is the last statement in its (inner) block.

@@ -1662,78 +1692,59 @@
 one numerical and one generic.
 
 
+
+<h4>The numerical <b>for</b> loop</h4>
+
 <p>
 The numerical <b>for</b> loop repeats a block of code while a
-control variable runs through an arithmetic progression.
+control variable goes through an arithmetic progression.
 It has the following syntax:
 
 <pre>
 	stat ::= <b>for</b> Name &lsquo;<b>=</b>&rsquo; exp &lsquo;<b>,</b>&rsquo; exp [&lsquo;<b>,</b>&rsquo; exp] <b>do</b> block <b>end</b>
 </pre><p>
-The <em>block</em> is repeated for <em>name</em> starting at the value of
-the first <em>exp</em>, until it passes the second <em>exp</em> by steps of the
-third <em>exp</em>.
-More precisely, a <b>for</b> statement like
+The given identifier (Name) defines the control variable,
+which is local to the loop body (<em>block</em>).
 
-<pre>
-     for v = <em>e1</em>, <em>e2</em>, <em>e3</em> do <em>block</em> end
-</pre><p>
-is equivalent to the code:
-
-<pre>
-     do
-       local <em>var</em>, <em>limit</em>, <em>step</em> = tonumber(<em>e1</em>), tonumber(<em>e2</em>), tonumber(<em>e3</em>)
-       if not (<em>var</em> and <em>limit</em> and <em>step</em>) then error() end
-       <em>var</em> = <em>var</em> - <em>step</em>
-       while true do
-         <em>var</em> = <em>var</em> + <em>step</em>
-         if (<em>step</em> &gt;= 0 and <em>var</em> &gt; <em>limit</em>) or (<em>step</em> &lt; 0 and <em>var</em> &lt; <em>limit</em>) then
-           break
-         end
-         local v = <em>var</em>
-         <em>block</em>
-       end
-     end
-</pre>
 
 <p>
-Note the following:
+The loop starts by evaluating once the three control expressions;
+they must all result in numbers.
+Their values are called respectively
+the <em>initial value</em>, the <em>limit</em>, and the <em>step</em>.
+If the step is absent, it defaults to&nbsp;1.
+Then the loop body is repeated with the value of the control variable
+going through an arithmetic progression,
+starting at the initial value,
+with a common difference given by the step,
+until that value passes the limit.
+A negative step makes a decreasing sequence;
+a step equal to zero raises an error.
+If the initial value is already greater than the limit
+(or less than, if the step is negative),
+the body is not executed.
 
-<ul>
 
-<li>
-All three control expressions are evaluated only once,
-before the loop starts.
-They must all result in numbers.
-</li>
-
-<li>
-<code><em>var</em></code>, <code><em>limit</em></code>, and <code><em>step</em></code> are invisible variables.
-The names shown here are for explanatory purposes only.
-</li>
-
-<li>
-If the third expression (the step) is absent,
-then a step of&nbsp;1 is used.
-</li>
+<p>
+If both the initial value and the step are integers,
+the loop is done with integers;
+in this case, the range of the control variable is clipped
+by the range of integers.
+Otherwise, the loop is done with floats.
+(Beware of floating-point accuracy in this case.)
 
-<li>
-You can use <b>break</b> and <b>goto</b> to exit a <b>for</b> loop.
-</li>
 
-<li>
-The loop variable <code>v</code> is local to the loop body.
+<p>
+You should not change the value of the control variable
+during the loop.
 If you need its value after the loop,
 assign it to another variable before exiting the loop.
-</li>
 
-<li>
-The values in <em>var</em>, <em>limit</em>, and <em>step</em>
-can be integers or floats.
-All operations on them respect the usual rules in Lua.
-</li>
 
-</ul>
+
+
+
+<h4>The generic <b>for</b> loop</h4>
 
 <p>
 The generic <b>for</b> statement works over functions,

@@ -1749,49 +1760,50 @@
 A <b>for</b> statement like
 
 <pre>
-     for <em>var_1</em>, &middot;&middot;&middot;, <em>var_n</em> in <em>explist</em> do <em>block</em> end
+     for <em>var_1</em>, &middot;&middot;&middot;, <em>var_n</em> in <em>explist</em> do <em>body</em> end
 </pre><p>
-is equivalent to the code:
+works as follows.
 
-<pre>
-     do
-       local <em>f</em>, <em>s</em>, <em>var</em> = <em>explist</em>
-       while true do
-         local <em>var_1</em>, &middot;&middot;&middot;, <em>var_n</em> = <em>f</em>(<em>s</em>, <em>var</em>)
-         if <em>var_1</em> == nil then break end
-         <em>var</em> = <em>var_1</em>
-         <em>block</em>
-       end
-     end
-</pre><p>
-Note the following:
 
-<ul>
+<p>
+The names <em>var_i</em> declare loop variables local to the loop body.
+The first of these variables is the <em>control variable</em>.
 
-<li>
-<code><em>explist</em></code> is evaluated only once.
-Its results are an <em>iterator</em> function,
+
+<p>
+The loop starts by evaluating <em>explist</em>
+to produce four values:
+an <em>iterator function</em>,
 a <em>state</em>,
-and an initial value for the first <em>iterator variable</em>.
-</li>
+an initial value for the control variable,
+and a <em>closing value</em>.
 
-<li>
-<code><em>f</em></code>, <code><em>s</em></code>, and <code><em>var</em></code> are invisible variables.
-The names are here for explanatory purposes only.
-</li>
 
-<li>
-You can use <b>break</b> to exit a <b>for</b> loop.
-</li>
+<p>
+Then, at each iteration,
+Lua calls the iterator function with two arguments:
+the state and the control variable.
+The results from this call are then assigned to the loop variables,
+following the rules of multiple assignments (see <a href="#3.3.3">&sect;3.3.3</a>).
+If the control variable becomes <b>nil</b>,
+the loop terminates.
+Otherwise, the body is executed and the loop goes
+to the next iteration.
+
+
+<p>
+The closing value behaves like a
+to-be-closed variable (see <a href="#3.3.8">&sect;3.3.8</a>),
+which can be used to release resources when the loop ends.
+Otherwise, it does not interfere with the loop.
+
+
+<p>
+You should not change the value of the control variable
+during the loop.
+
 
-<li>
-The loop variables <code><em>var_i</em></code> are local to the loop;
-you cannot use their values after the <b>for</b> ends.
-If you need these values,
-then assign them to other variables before breaking or exiting the loop.
-</li>
 
-</ul>
 
 
 

@@ -1812,14 +1824,22 @@
 
 <h3>3.3.7 &ndash; <a name="3.3.7">Local Declarations</a></h3><p>
 Local variables can be declared anywhere inside a block.
-The declaration can include an initial assignment:
+The declaration can include an initialization:
 
 <pre>
 	stat ::= <b>local</b> namelist [&lsquo;<b>=</b>&rsquo; explist]
-</pre><p>
+	stat ::=  <b>local</b> &lsquo;<b>&lt;</b>&rsquo; Name &lsquo;<b>&gt;</b>&rsquo; Name &lsquo;<b>=</b>&rsquo; exp </pre><p>
 If present, an initial assignment has the same semantics
 of a multiple assignment (see <a href="#3.3.3">&sect;3.3.3</a>).
 Otherwise, all variables are initialized with <b>nil</b>.
+The second syntax declares a local with a given attribute,
+which is the name between the angle brackets.
+In this case, there must be an initialization.
+There are two possible attributes:
+<code>const</code>, which declares a constant variable,
+that is, a variable that cannot be assigned to
+after its initialization;
+and <code>toclose</code>, wich declares a to-be-closed variable (see <a href="#3.3.8">&sect;3.3.8</a>).
 
 
 <p>

@@ -1834,6 +1854,62 @@
 
 
 
+<h3>3.3.8 &ndash; <a name="3.3.8">To-be-closed Variables</a></h3>
+
+<p>
+A local variable can be declared as a <em>to-be-closed</em> variable,
+using the identifier <code>toclose</code> as its attribute:
+
+<pre>
+	stat ::=  <b>local</b> &lsquo;<b>&lt;</b>&rsquo; <code>toclose</code> &lsquo;<b>&gt;</b>&rsquo; Name &lsquo;<b>=</b>&rsquo; exp </pre><p>
+A to-be-closed variable behaves like a constant local variable,
+except that its value is <em>closed</em> whenever the variable
+goes out of scope, including normal block termination,
+exiting its block by <b>break</b>/<b>goto</b>/<b>return</b>,
+or exiting by an error.
+
+
+<p>
+Here, to <em>close</em> a value means
+to call its <code>__close</code> metamethod.
+If the value is <b>nil</b>, it is ignored;
+otherwise,
+if it does not have a <code>__close</code> metamethod,
+an error is raised.
+When calling the metamethod,
+the value itself is passed as the first argument
+and the error object (if any) is passed as a second argument;
+if there was no error, the second argument is <b>nil</b>.
+
+
+<p>
+If several to-be-closed variables go out of scope at the same event,
+they are closed in the reverse order that they were declared.
+If there is any error while running a closing method,
+that error is handled like an error in the regular code
+where the variable was defined;
+in particular,
+the other pending closing methods will still be called.
+
+
+<p>
+If a coroutine yields inside a block and is never resumed again,
+the variables visible at that block will never go out of scope,
+and therefore they will not be closed.
+Similarly, if a coroutine ends with an error,
+it does not unwind its stack,
+so it does not close any variable.
+You should either use finalizers
+or call <a href="#pdf-coroutine.kill"><code>coroutine.kill</code></a> to close the variables in these cases.
+However, note that if the coroutine was created
+through <a href="#pdf-coroutine.wrap"><code>coroutine.wrap</code></a>,
+then its corresponding function will close all variables
+in case of errors.
+
+
+
+
+
 
 
 <h2>3.4 &ndash; <a name="3.4">Expressions</a></h2>

@@ -1945,7 +2021,7 @@
 the operation is performed over integers and the result is an integer.
 Otherwise, if both operands are numbers,
 then they are converted to floats,
-the operation is performed following the usual rules
+the operation is performed following the machine's rules
 for floating-point arithmetic
 (usually the IEEE 754 standard),
 and the result is a float.

@@ -1964,7 +2040,7 @@
 <p>
 Floor division (<code>//</code>) is a division
 that rounds the quotient towards minus infinity,
-that is, the floor of the division of its operands.
+resulting in the floor of the division of its operands.
 
 
 <p>

@@ -1978,7 +2054,8 @@
 according to the usual rules of two-complement arithmetic.
 (In other words,
 they return the unique representable integer
-that is equal modulo <em>2<sup>64</sup></em> to the mathematical result.)
+that is equal modulo <em>2<sup>n</sup></em> to the mathematical result,
+where <em>n</em> is the number of bits of the integer type.)
 
 
 

@@ -2046,23 +2123,34 @@
 
 
 <p>
-The string library uses metamethods that try to coerce
-strings to numbers in all arithmetic operations.
-Any string operator is converted to an integer or a float,
+Several places in Lua coerce strings to numbers when necessary.
+A string is converted to an integer or a float
 following its syntax and the rules of the Lua lexer.
 (The string may have also leading and trailing spaces and a sign.)
 All conversions from strings to numbers
 accept both a dot and the current locale mark
 as the radix character.
 (The Lua lexer, however, accepts only a dot.)
+If the string is not a valid numeral,
+the conversion fails.
+If necessary, the result of this first step is then converted
+to the required number subtype following the previous rules
+for conversions between floats and integers.
+
+
+<p>
+The string library uses metamethods that try to coerce
+strings to numbers in all arithmetic operations.
+If the conversion fails,
+the library calls the metamethod of the other operand
+(if present) or it raises an error.
 
 
 <p>
 The conversion from numbers to strings uses a
 non-specified human-readable format.
-For complete control over how numbers are converted to strings,
-use the <code>format</code> function from the string library
-(see <a href="#pdf-string.format"><code>string.format</code></a>).
+To convert numbers to strings in any specific way,
+use the function <a href="#pdf-string.format"><code>string.format</code></a>.
 
 
 

@@ -2086,7 +2174,7 @@
 Equality (<code>==</code>) first compares the type of its operands.
 If the types are different, then the result is <b>false</b>.
 Otherwise, the values of the operands are compared.
-Strings are compared in the obvious way.
+Strings are equal if they have the same byte content.
 Numbers are equal if they denote the same mathematical value.
 
 

@@ -2095,14 +2183,14 @@
 are compared by reference:
 two objects are considered equal only if they are the same object.
 Every time you create a new object
-(a table, userdata, or thread),
+(a table, a userdata, or a thread),
 this new object is different from any previously existing object.
-A closure is always equal to itself.
-Closures with any detectable difference
+A function is always equal to itself.
+Functions with any detectable difference
 (different behavior, different definition) are always different.
-Closures created at different times but with no detectable differences
+Functions created at different times but with no detectable differences
 may be classified as equal or not
-(depending on internal cashing details).
+(depending on internal caching details).
 
 
 <p>

@@ -2125,8 +2213,8 @@
 <p>
 The order operators work as follows.
 If both arguments are numbers,
-then they are compared according to their mathematical values
-(regardless of their subtypes).
+then they are compared according to their mathematical values,
+regardless of their subtypes.
 Otherwise, if both arguments are strings,
 then their values are compared according to the current locale.
 Otherwise, Lua tries to call the <code>__lt</code> or the <code>__le</code>

@@ -2137,8 +2225,8 @@
 
 <p>
 Following the IEEE 754 standard,
-NaN is considered neither smaller than,
-nor equal to, nor greater than any value (including itself).
+the special value NaN is considered neither less than,
+nor equal to, nor greater than any value, including itself.
 
 
 

@@ -2182,8 +2270,9 @@
 <h3>3.4.6 &ndash; <a name="3.4.6">Concatenation</a></h3><p>
 The string concatenation operator in Lua is
 denoted by two dots ('<code>..</code>').
-If both operands are strings or numbers, then they are converted to
-strings according to the rules described in <a href="#3.4.3">&sect;3.4.3</a>.
+If both operands are strings or numbers,
+then the numbers are converted to strings
+in a non-specified format (see <a href="#3.4.3">&sect;3.4.3</a>).
 Otherwise, the <code>__concat</code> metamethod is called (see <a href="#2.4">&sect;2.4</a>).
 
 

@@ -2197,9 +2286,9 @@
 
 
 <p>
-The length of a string is its number of bytes
-(that is, the usual meaning of string length when each
-character is one byte).
+The length of a string is its number of bytes.
+(That is the usual meaning of string length when each
+character is one byte.)
 
 
 <p>

@@ -2223,8 +2312,10 @@
 as it has only one border (5).
 The table <code>{10, 20, 30, nil, 50}</code> has two borders (3 and 5),
 and therefore it is not a sequence.
+(The <b>nil</b> at index 4 is called a <em>hole</em>.)
 The table <code>{nil, 20, 30, nil, nil, 60, nil}</code>
-has three borders (0, 3, and 6),
+has three borders (0, 3, and 6) and three holes
+(at indices 1, 4, and 5),
 so it is not a sequence, too.
 The table <code>{}</code> is a sequence with border 0.
 Note that non-natural keys do not interfere

@@ -2304,10 +2395,10 @@
 with key <code>exp1</code> and value <code>exp2</code>.
 A field of the form <code>name = exp</code> is equivalent to
 <code>["name"] = exp</code>.
-Finally, fields of the form <code>exp</code> are equivalent to
+Fields of the form <code>exp</code> are equivalent to
 <code>[i] = exp</code>, where <code>i</code> are consecutive integers
-starting with 1.
-Fields in the other formats do not affect this counting.
+starting with 1;
+fields in the other formats do not affect this counting.
 For example,
 
 <pre>

@@ -2360,8 +2451,9 @@
 If the value of prefixexp has type <em>function</em>,
 then this function is called
 with the given arguments.
-Otherwise, the prefixexp <code>__call</code> metamethod is called,
-having as first argument the value of prefixexp,
+Otherwise, if present,
+the prefixexp <code>__call</code> metamethod is called:
+its first argument is the value of prefixexp,
 followed by the original call arguments
 (see <a href="#2.4">&sect;2.4</a>).
 

@@ -2372,7 +2464,7 @@
 <pre>
 	functioncall ::= prefixexp &lsquo;<b>:</b>&rsquo; Name args
 </pre><p>
-can be used to call "methods".
+can be used to emulate methods.
 A call <code>v:name(<em>args</em>)</code>
 is syntactic sugar for <code>v.name(v,<em>args</em>)</code>,
 except that <code>v</code> is evaluated only once.

@@ -2397,8 +2489,8 @@
 
 
 <p>
-A call of the form <code>return <em>functioncall</em></code> is called
-a <em>tail call</em>.
+A call of the form <code>return <em>functioncall</em></code> not in the
+scope of a to-be-closed variable is called a <em>tail call</em>.
 Lua implements <em>proper tail calls</em>
 (or <em>proper tail recursion</em>):
 in a tail call,

@@ -2408,14 +2500,16 @@
 However, a tail call erases any debug information about the
 calling function.
 Note that a tail call only happens with a particular syntax,
-where the <b>return</b> has one single function call as argument;
-this syntax makes the calling function return exactly
-the returns of the called function.
+where the <b>return</b> has one single function call as argument,
+and it is outside the scope of any to-be-closed variable.
+This syntax makes the calling function return exactly
+the returns of the called function,
+without any intervening action.
 So, none of the following examples are tail calls:
 
 <pre>
      return (f(x))        -- results adjusted to 1
-     return 2 * f(x)
+     return 2 * f(x)      -- result multiplied by 2
      return x, f(x)       -- additional results
      f(x); return         -- results discarded
      return x or f(x)     -- results adjusted to 1

@@ -2485,10 +2579,11 @@
 A function definition is an executable expression,
 whose value has type <em>function</em>.
 When Lua precompiles a chunk,
-all its function bodies are precompiled too.
+all its function bodies are precompiled too,
+but they are not created yet.
 Then, whenever Lua executes the function definition,
 the function is <em>instantiated</em> (or <em>closed</em>).
-This function instance (or <em>closure</em>)
+This function instance, or <em>closure</em>,
 is the final value of the expression.
 
 

@@ -2556,13 +2651,13 @@
 
 There is a system-dependent limit on the number of values
 that a function may return.
-This limit is guaranteed to be larger than 1000.
+This limit is guaranteed to be greater than 1000.
 
 
 <p>
 The <em>colon</em> syntax
-is used for defining <em>methods</em>,
-that is, functions that have an implicit extra parameter <code>self</code>.
+is used to emulate <em>methods</em>,
+adding an implicit extra parameter <code>self</code> to the function.
 Thus, the statement
 
 <pre>

@@ -2717,8 +2812,8 @@
 most query operations in the API do not follow a strict stack discipline.
 Instead, they can refer to any element in the stack
 by using an <em>index</em>:
-A positive index represents an absolute stack position
-(starting at&nbsp;1);
+A positive index represents an absolute stack position,
+starting at&nbsp;1 as the bottom of the stack;
 a negative index represents an offset relative to the top of the stack.
 More specifically, if the stack has <em>n</em> elements,
 then index&nbsp;1 represents the first element

@@ -2794,7 +2889,7 @@
 within the space allocated for the stack,
 that is, indices up to the stack size.
 (Note that 0 is never an acceptable index.)
-Indices to upvalues (see <a href="#4.4">&sect;4.4</a>) larger than the real number
+Indices to upvalues (see <a href="#4.4">&sect;4.4</a>) greater than the real number
 of upvalues in the current C&nbsp;function are also acceptable (but invalid).
 Except when noted otherwise,
 functions in the API work with acceptable indices.

@@ -2804,7 +2899,7 @@
 Acceptable indices serve to avoid extra tests
 against the stack top when querying the stack.
 For instance, a C&nbsp;function can query its third argument
-without the need to first check whether there is a third argument,
+without the need to check whether there is a third argument,
 that is, without the need to check whether 3 is a valid index.
 
 

@@ -2845,7 +2940,8 @@
 
 
 <p>
-A C&nbsp;closure can also change the values of its corresponding upvalues.
+A C&nbsp;closure can also change the values
+of its corresponding upvalues.
 
 
 

@@ -2857,7 +2953,7 @@
 Lua provides a <em>registry</em>,
 a predefined table that can be used by any C&nbsp;code to
 store whatever Lua values it needs to store.
-The registry table is always located at pseudo-index
+The registry table is always accessible at pseudo-index
 <a name="pdf-LUA_REGISTRYINDEX"><code>LUA_REGISTRYINDEX</code></a>.
 Any C&nbsp;library can store data into this table,
 but it must take care to choose keys

@@ -2875,7 +2971,8 @@
 The integer keys in the registry are used
 by the reference mechanism (see <a href="#luaL_ref"><code>luaL_ref</code></a>)
 and by some predefined values.
-Therefore, integer keys must not be used for other purposes.
+Therefore, integer keys in the registry
+must not be used for other purposes.
 
 
 <p>

@@ -2905,8 +3002,8 @@
 Internally, Lua uses the C <code>longjmp</code> facility to handle errors.
 (Lua will use exceptions if you compile it as C++;
 search for <code>LUAI_THROW</code> in the source code for details.)
-When Lua faces any error
-(such as a memory allocation error or a type error)
+When Lua faces any error,
+such as a memory allocation error or a type error,
 it <em>raises</em> an error;
 that is, it does a long jump.
 A <em>protected environment</em> uses <code>setjmp</code>

@@ -2915,7 +3012,8 @@
 
 
 <p>
-Inside a C&nbsp;function you can raise an error by calling <a href="#lua_error"><code>lua_error</code></a>.
+Inside a C&nbsp;function you can raise an error explicitly
+by calling <a href="#lua_error"><code>lua_error</code></a>.
 
 
 <p>

@@ -2946,7 +3044,7 @@
 as it should be already protected.
 However,
 when C code operates on other Lua states
-(e.g., a Lua parameter to the function,
+(e.g., a Lua-state argument to the function,
 a Lua state stored in the registry, or
 the result of <a href="#lua_newthread"><code>lua_newthread</code></a>),
 it should use them only in API calls that cannot raise errors.

@@ -2954,7 +3052,7 @@
 
 <p>
 The panic function runs as if it were a message handler (see <a href="#2.3">&sect;2.3</a>);
-in particular, the error object is at the top of the stack.
+in particular, the error object is on the top of the stack.
 However, there is no guarantee about stack space.
 To push anything on the stack,
 the panic function must first check the available space (see <a href="#4.2">&sect;4.2</a>).

@@ -2990,9 +3088,9 @@
 This original function then calls one of those three functions in the C API,
 which we will call the <em>callee function</em>,
 that then yields the current thread.
-(This can happen when the callee function is <a href="#lua_yieldk"><code>lua_yieldk</code></a>,
+This can happen when the callee function is <a href="#lua_yieldk"><code>lua_yieldk</code></a>,
 or when the callee function is either <a href="#lua_callk"><code>lua_callk</code></a> or <a href="#lua_pcallk"><code>lua_pcallk</code></a>
-and the function called by them yields.)
+and the function called by them yields.
 
 
 <p>

@@ -3062,11 +3160,11 @@
 <p>
 Besides the Lua state,
 the continuation function has two other parameters:
-the final status of the call plus the context value (<code>ctx</code>) that
+the final status of the call and the context value (<code>ctx</code>) that
 was passed originally to <a href="#lua_pcallk"><code>lua_pcallk</code></a>.
-(Lua does not use this context value;
+Lua does not use this context value;
 it only passes this value from the original function to the
-continuation function.)
+continuation function.
 For <a href="#lua_pcallk"><code>lua_pcallk</code></a>,
 the status is the same value that would be returned by <a href="#lua_pcallk"><code>lua_pcallk</code></a>,
 except that it is <a href="#pdf-LUA_YIELD"><code>LUA_YIELD</code></a> when being executed after a yield

@@ -3120,17 +3218,16 @@
 depending on the situation;
 an interrogation mark '<code>?</code>' means that
 we cannot know how many elements the function pops/pushes
-by looking only at its arguments
-(e.g., they may depend on what is on the stack).
+by looking only at its arguments.
+(For instance, they may depend on what is on the stack.)
 The third field, <code>x</code>,
 tells whether the function may raise errors:
 '<code>-</code>' means the function never raises any error;
-'<code>m</code>' means the function may raise out-of-memory errors
-and errors running a finalizer;
+'<code>m</code>' means the function may raise only out-of-memory errors;
 '<code>v</code>' means the function may raise the errors explained in the text;
-'<code>e</code>' means the function may raise any errors
-(because it can run arbitrary Lua code,
-either directly or through metamethods).
+'<code>e</code>' means the function can run arbitrary Lua code,
+either directly or through metamethods,
+and therefore may raise any errors.
 
 
 

@@ -3190,13 +3287,13 @@
 <p>
 When <code>nsize</code> is zero,
 the allocator must behave like <code>free</code>
-and return <code>NULL</code>.
+and then return <code>NULL</code>.
 
 
 <p>
 When <code>nsize</code> is not zero,
 the allocator must behave like <code>realloc</code>.
-The allocator returns <code>NULL</code>
+In particular, the allocator returns <code>NULL</code>
 if and only if it cannot fulfill the request.
 
 

@@ -3232,7 +3329,7 @@
 Performs an arithmetic or bitwise operation over the two values
 (or one, in the case of negations)
 at the top of the stack,
-with the value at the top being the second operand,
+with the value on the top being the second operand,
 pops these values, and pushes the result of the operation.
 The function follows the semantics of the corresponding Lua operator
 (that is, it may call metamethods).

@@ -3290,9 +3387,9 @@
 that is, the first argument is pushed first.
 Finally you call <a href="#lua_call"><code>lua_call</code></a>;
 <code>nargs</code> is the number of arguments that you pushed onto the stack.
-All arguments and the function value are popped from the stack
-when the function is called.
-The function results are pushed onto the stack when the function returns.
+When the function returns,
+all arguments and the function value are popped
+and the function results are pushed onto the stack.
 The number of results is adjusted to <code>nresults</code>,
 unless <code>nresults</code> is <a name="pdf-LUA_MULTRET"><code>LUA_MULTRET</code></a>.
 In this case, all results from the function are pushed;

@@ -3372,7 +3469,7 @@
 and its last argument is at index <code>lua_gettop(L)</code>.
 To return values to Lua, a C&nbsp;function just pushes them onto the stack,
 in direct order (the first result is pushed first),
-and returns the number of results.
+and returns in C the number of results.
 Any other value in the stack below the results will be properly
 discarded by Lua.
 Like a Lua function, a C&nbsp;function called by Lua can also return

@@ -3409,11 +3506,11 @@
 <pre>int lua_checkstack (lua_State *L, int n);</pre>
 
 <p>
-Ensures that the stack has space for at least <code>n</code> extra slots
-(that is, that you can safely push up to <code>n</code> values into it).
+Ensures that the stack has space for at least <code>n</code> extra slots,
+that is, that you can safely push up to <code>n</code> values into it.
 It returns false if it cannot fulfill the request,
 either because it would cause the stack
-to be larger than a fixed maximum size
+to be greater than a fixed maximum size
 (typically at least several thousand elements) or
 because it cannot allocate memory for the extra space.
 This function never shrinks the stack;

@@ -3432,6 +3529,9 @@
 Destroys all objects in the given Lua state
 (calling the corresponding garbage-collection metamethods, if any)
 and frees all dynamic memory used by this state.
+
+
+<p>
 On several platforms, you may not need to call this function,
 because all resources are naturally released when the host program ends.
 On the other hand, long-running programs that create multiple states,

@@ -3476,7 +3576,7 @@
 
 <p>
 Concatenates the <code>n</code> values at the top of the stack,
-pops them, and leaves the result at the top.
+pops them, and leaves the result on the top.
 If <code>n</code>&nbsp;is&nbsp;1, the result is the single value on the stack
 (that is, the function does nothing);
 if <code>n</code> is 0, the result is the empty string.

@@ -3512,7 +3612,7 @@
 parameter <code>nrec</code> is a hint for how many other elements
 the table will have.
 Lua may use these hints to preallocate memory for the new table.
-This preallocation is useful for performance when you know in advance
+This preallocation may help performance when you know in advance
 how many elements the table will have.
 Otherwise you can use the function <a href="#lua_newtable"><code>lua_newtable</code></a>.
 

@@ -3565,7 +3665,7 @@
 
 <p>
 Generates a Lua error,
-using the value at the top of the stack as the error object.
+using the value on the top of the stack as the error object.
 This function does a long jump,
 and therefore never returns
 (see <a href="#luaL_error"><code>luaL_error</code></a>).

@@ -3575,7 +3675,7 @@
 
 
 <hr><h3><a name="lua_gc"><code>lua_gc</code></a></h3><p>
-<span class="apii">[-0, +0, <em>v</em>]</span>
+<span class="apii">[-0, +0, &ndash;]</span>
 <pre>int lua_gc (lua_State *L, int what, int data);</pre>
 
 <p>

@@ -3635,10 +3735,6 @@
 see <a href="#pdf-collectgarbage"><code>collectgarbage</code></a>.
 
 
-<p>
-This function may raise errors when calling finalizers.
-
-
 
 
 

@@ -3749,7 +3845,7 @@
 <p>
 Pushes onto the stack the value <code>t[k]</code>,
 where <code>t</code> is the value at the given index
-and <code>k</code> is the value at the top of the stack.
+and <code>k</code> is the value on the top of the stack.
 
 
 <p>

@@ -4076,12 +4172,6 @@
 <li><b><a href="#pdf-LUA_ERRMEM"><code>LUA_ERRMEM</code></a>: </b>
 memory allocation (out-of-memory) error;</li>
 
-<li><b><a href="#pdf-LUA_ERRGCMM"><code>LUA_ERRGCMM</code></a>: </b>
-error while running a <code>__gc</code> metamethod.
-(This error has no relation with the chunk being loaded.
-It is generated by the garbage collector.)
-</li>
-
 </ul>
 
 <p>

@@ -4126,11 +4216,11 @@
 <pre>lua_State *lua_newstate (lua_Alloc f, void *ud);</pre>
 
 <p>
-Creates a new thread running in a new, independent state.
-Returns <code>NULL</code> if it cannot create the thread or the state
+Creates a new independent state and returns its main thread.
+Returns <code>NULL</code> if it cannot create the state
 (due to lack of memory).
 The argument <code>f</code> is the allocator function;
-Lua does all memory allocation for this state
+Lua will do all memory allocation for this state
 through this function (see <a href="#lua_Alloc"><code>lua_Alloc</code></a>).
 The second argument, <code>ud</code>, is an opaque pointer that Lua
 passes to the allocator in every call.

@@ -4178,7 +4268,7 @@
 
 <p>
 This function creates and pushes on the stack a new full userdata,
-with <code>nuvalue</code> associated Lua values (called <code>user values</code>)
+with <code>nuvalue</code> associated Lua values, called <code>user values</code>,
 plus an associated block of raw memory with <code>size</code> bytes.
 (The user values can be set and read with the functions
 <a href="#lua_setiuservalue"><code>lua_setiuservalue</code></a> and <a href="#lua_getiuservalue"><code>lua_getiuservalue</code></a>.)

@@ -4197,14 +4287,14 @@
 
 <p>
 Pops a key from the stack,
-and pushes a key&ndash;value pair from the table at the given index
-(the "next" pair after the given key).
+and pushes a key&ndash;value pair from the table at the given index,
+the "next" pair after the given key.
 If there are no more elements in the table,
-then <a href="#lua_next"><code>lua_next</code></a> returns 0 (and pushes nothing).
+then <a href="#lua_next"><code>lua_next</code></a> returns 0 and pushes nothing.
 
 
 <p>
-A typical traversal looks like this:
+A typical table traversal looks like this:
 
 <pre>
      /* table is in the stack at index 't' */

@@ -4221,7 +4311,7 @@
 
 <p>
 While traversing a table,
-do not call <a href="#lua_tolstring"><code>lua_tolstring</code></a> directly on a key,
+avoid calling <a href="#lua_tolstring"><code>lua_tolstring</code></a> directly on a key,
 unless you know that the key is actually a string.
 Recall that <a href="#lua_tolstring"><code>lua_tolstring</code></a> may change
 the value at the given index;

@@ -4258,15 +4348,14 @@
 <pre>int lua_numbertointeger (lua_Number n, lua_Integer *p);</pre>
 
 <p>
-Converts a Lua float to a Lua integer.
-This macro assumes that <code>n</code> has an integral value.
+Tries to convert a Lua float to a Lua integer;
+the float <code>n</code> must have an integral value.
 If that value is within the range of Lua integers,
 it is converted to an integer and assigned to <code>*p</code>.
 The macro results in a boolean indicating whether the
 conversion was successful.
 (Note that this range test can be tricky to do
-correctly without this macro,
-due to roundings.)
+correctly without this macro, due to rounding.)
 
 
 <p>

@@ -4306,7 +4395,7 @@
 <em>message handler</em>.
 (This index cannot be a pseudo-index.)
 In case of runtime errors,
-this function will be called with the error object
+this handler will be called with the error object
 and its return value will be the object
 returned on the stack by <a href="#lua_pcall"><code>lua_pcall</code></a>.
 

@@ -4340,13 +4429,6 @@
 error while running the message handler.
 </li>
 
-<li><b><a name="pdf-LUA_ERRGCMM"><code>LUA_ERRGCMM</code></a>: </b>
-error while running a <code>__gc</code> metamethod.
-For such errors, Lua does not call the message handler
-(as this kind of error typically has no relation
-with the function being called).
-</li>
-
 </ul>
 
 

@@ -4413,11 +4495,12 @@
 <p>
 When a C&nbsp;function is created,
 it is possible to associate some values with it,
-thus creating a C&nbsp;closure (see <a href="#4.4">&sect;4.4</a>);
-these values are then accessible to the function whenever it is called.
-To associate values with a C&nbsp;function,
-first these values must be pushed onto the stack
-(when there are multiple values, the first value is pushed first).
+the so called upvalues;
+these upvalues are then accessible to the function whenever it is called.
+This association is called a C&nbsp;closure (see <a href="#4.4">&sect;4.4</a>).
+To create a C&nbsp;closure,
+first the initial values for its upvalues must be pushed onto the stack.
+(When there are multiple upvalues, the first value is pushed first.)
 Then <a href="#lua_pushcclosure"><code>lua_pushcclosure</code></a>
 is called to create and push the C&nbsp;function onto the stack,
 with the argument <code>n</code> telling how many values will be

@@ -4445,6 +4528,7 @@
 
 <p>
 Pushes a C&nbsp;function onto the stack.
+This function is equivalent to <a href="#lua_pushcclosure"><code>lua_pushcclosure</code></a> with no upvalues.
 
 
 

@@ -4471,7 +4555,7 @@
 '<code>%s</code>' (inserts a zero-terminated string, with no size restrictions),
 '<code>%f</code>' (inserts a <a href="#lua_Number"><code>lua_Number</code></a>),
 '<code>%I</code>' (inserts a <a href="#lua_Integer"><code>lua_Integer</code></a>),
-'<code>%p</code>' (inserts a pointer as a hexadecimal numeral),
+'<code>%p</code>' (inserts a pointer),
 '<code>%d</code>' (inserts an <code>int</code>),
 '<code>%c</code>' (inserts an <code>int</code> as a one-byte character), and
 '<code>%U</code>' (inserts a <code>long int</code> as a UTF-8 byte sequence).

@@ -4535,6 +4619,7 @@
 <p>
 This macro is equivalent to <a href="#lua_pushstring"><code>lua_pushstring</code></a>,
 but should be used only when <code>s</code> is a literal string.
+(Lua may optimize this case.)
 
 
 

@@ -4547,7 +4632,7 @@
 <p>
 Pushes the string pointed to by <code>s</code> with size <code>len</code>
 onto the stack.
-Lua makes (or reuses) an internal copy of the given string,
+Lua will make or reuse an internal copy of the given string,
 so the memory at <code>s</code> can be freed or reused immediately after
 the function returns.
 The string can contain any binary data,

@@ -4590,7 +4675,7 @@
 <p>
 Pushes the zero-terminated string pointed to by <code>s</code>
 onto the stack.
-Lua makes (or reuses) an internal copy of the given string,
+Lua will make or reuse an internal copy of the given string,
 so the memory at <code>s</code> can be freed or reused immediately after
 the function returns.
 

@@ -4651,7 +4736,7 @@
 <p>
 Returns 1 if the two values in indices <code>index1</code> and
 <code>index2</code> are primitively equal
-(that is, without calling the <code>__eq</code> metamethod).
+(that is, equal without calling the <code>__eq</code> metamethod).
 Otherwise returns&nbsp;0.
 Also returns&nbsp;0 if any of the indices are not valid.
 

@@ -4718,8 +4803,8 @@
 for tables, this is the result of the length operator ('<code>#</code>')
 with no metamethods;
 for userdata, this is the size of the block of memory allocated
-for the userdata;
-for other values, it is&nbsp;0.
+for the userdata.
+For other values, this call returns&nbsp;0.
 
 
 

@@ -4744,7 +4829,7 @@
 <p>
 Does the equivalent of <code>t[i] = v</code>,
 where <code>t</code> is the table at the given index
-and <code>v</code> is the value at the top of the stack.
+and <code>v</code> is the value on the top of the stack.
 
 
 <p>

@@ -4764,7 +4849,7 @@
 Does the equivalent of <code>t[p] = v</code>,
 where <code>t</code> is the table at the given index,
 <code>p</code> is encoded as a light userdata,
-and <code>v</code> is the value at the top of the stack.
+and <code>v</code> is the value on the top of the stack.
 
 
 <p>

@@ -4783,8 +4868,8 @@
 
 <p>
 The reader function used by <a href="#lua_load"><code>lua_load</code></a>.
-Every time it needs another piece of the chunk,
-<a href="#lua_load"><code>lua_load</code></a> calls the reader,
+Every time <a href="#lua_load"><code>lua_load</code></a> needs another piece of the chunk,
+it calls the reader,
 passing along its <code>data</code> parameter.
 The reader must return a pointer to a block of memory
 with a new piece of the chunk

@@ -4842,6 +4927,23 @@
 
 
 
+<hr><h3><a name="lua_resetthread"><code>lua_resetthread</code></a></h3><p>
+<span class="apii">[-0, +?, &ndash;]</span>
+<pre>int lua_resetthread (lua_State *L);</pre>
+
+<p>
+Resets a thread, cleaning its call stack and closing all pending
+to-be-closed variables.
+Returns a status code:
+<a href="#pdf-LUA_OK"><code>LUA_OK</code></a> for no errors in closing methods,
+or an error status otherwise.
+In case of error,
+leave the error object on the stack,
+
+
+
+
+
 <hr><h3><a name="lua_resume"><code>lua_resume</code></a></h3><p>
 <span class="apii">[-?, +?, &ndash;]</span>
 <pre>int lua_resume (lua_State *L, lua_State *from, int nargs,

@@ -4858,29 +4960,22 @@
 with <code>nargs</code> being the number of arguments.
 This call returns when the coroutine suspends or finishes its execution.
 When it returns,
-<code>nresults</code> is updated and
+<code>*nresults</code> is updated and
 the top of the stack contains
-the <code>nresults</code> values passed to <a href="#lua_yield"><code>lua_yield</code></a>
+the <code>*nresults</code> values passed to <a href="#lua_yield"><code>lua_yield</code></a>
 or returned by the body function.
 <a href="#lua_resume"><code>lua_resume</code></a> returns
 <a href="#pdf-LUA_YIELD"><code>LUA_YIELD</code></a> if the coroutine yields,
 <a href="#pdf-LUA_OK"><code>LUA_OK</code></a> if the coroutine finishes its execution
 without errors,
 or an error code in case of errors (see <a href="#lua_pcall"><code>lua_pcall</code></a>).
-
-
-<p>
 In case of errors,
-the stack is not unwound,
-so you can use the debug API over it.
-The error object is on the top of the stack.
+the error object is on the top of the stack.
 
 
 <p>
-To resume a coroutine,
-you remove all results from the last <a href="#lua_yield"><code>lua_yield</code></a>,
-put on its stack only the values to
-be passed as results from <code>yield</code>,
+To resume a coroutine, you clear its stack,
+push only the values to be passed as results from <code>yield</code>,
 and then call <a href="#lua_resume"><code>lua_resume</code></a>.
 
 

@@ -4932,7 +5027,7 @@
 <p>
 Does the equivalent to <code>t[k] = v</code>,
 where <code>t</code> is the value at the given index
-and <code>v</code> is the value at the top of the stack.
+and <code>v</code> is the value on the top of the stack.
 
 
 <p>

@@ -4963,7 +5058,7 @@
 <p>
 Does the equivalent to <code>t[n] = v</code>,
 where <code>t</code> is the value at the given index
-and <code>v</code> is the value at the top of the stack.
+and <code>v</code> is the value on the top of the stack.
 
 
 <p>

@@ -4975,6 +5070,20 @@
 
 
 
+<hr><h3><a name="lua_setiuservalue"><code>lua_setiuservalue</code></a></h3><p>
+<span class="apii">[-1, +0, &ndash;]</span>
+<pre>int lua_setiuservalue (lua_State *L, int index, int n);</pre>
+
+<p>
+Pops a value from the stack and sets it as
+the new <code>n</code>-th user value associated to the
+full userdata at the given index.
+Returns 0 if the userdata does not have that value.
+
+
+
+
+
 <hr><h3><a name="lua_setmetatable"><code>lua_setmetatable</code></a></h3><p>
 <span class="apii">[-1, +0, &ndash;]</span>
 <pre>void lua_setmetatable (lua_State *L, int index);</pre>

@@ -4994,7 +5103,7 @@
 <p>
 Does the equivalent to <code>t[k] = v</code>,
 where <code>t</code> is the value at the given index,
-<code>v</code> is the value at the top of the stack,
+<code>v</code> is the value on the top of the stack,
 and <code>k</code> is the value just below the top.
 
 

@@ -5014,7 +5123,7 @@
 <p>
 Accepts any index, or&nbsp;0,
 and sets the stack top to this index.
-If the new top is larger than the old one,
+If the new top is greater than the old one,
 then the new elements are filled with <b>nil</b>.
 If <code>index</code> is&nbsp;0, then all stack elements are removed.
 

@@ -5022,15 +5131,15 @@
 
 
 
-<hr><h3><a name="lua_setiuservalue"><code>lua_setiuservalue</code></a></h3><p>
-<span class="apii">[-1, +0, &ndash;]</span>
-<pre>int lua_setiuservalue (lua_State *L, int index, int n);</pre>
+<hr><h3><a name="lua_setwarnf"><code>lua_setwarnf</code></a></h3><p>
+<span class="apii">[-0, +0, &ndash;]</span>
+<pre>void lua_setwarnf (lua_State *L, lua_WarnFunction f, void *ud);</pre>
 
 <p>
-Pops a value from the stack and sets it as
-the new <code>n</code>-th user value associated to the
-full userdata at the given index.
-Returns 0 if the userdata does not have that value.
+Sets the warning function to be used by Lua to emit warnings
+(see <a href="#lua_WarnFunction"><code>lua_WarnFunction</code></a>).
+The <code>ud</code> parameter sets the value <code>ud</code> passed to
+the warning function.
 
 
 

@@ -5065,14 +5174,14 @@
 
 
 <p>
-The status can be 0 (<a href="#pdf-LUA_OK"><code>LUA_OK</code></a>) for a normal thread,
+The status can be <a href="#pdf-LUA_OK"><code>LUA_OK</code></a> for a normal thread,
 an error code if the thread finished the execution
 of a <a href="#lua_resume"><code>lua_resume</code></a> with an error,
 or <a name="pdf-LUA_YIELD"><code>LUA_YIELD</code></a> if the thread is suspended.
 
 
 <p>
-You can only call functions in threads with status <a href="#pdf-LUA_OK"><code>LUA_OK</code></a>.
+You can call functions only in threads with status <a href="#pdf-LUA_OK"><code>LUA_OK</code></a>.
 You can resume threads with status <a href="#pdf-LUA_OK"><code>LUA_OK</code></a>
 (to start a new coroutine) or <a href="#pdf-LUA_YIELD"><code>LUA_YIELD</code></a>
 (to resume a coroutine).

@@ -5133,6 +5242,39 @@
 
 
 
+<hr><h3><a name="lua_toclose"><code>lua_toclose</code></a></h3><p>
+<span class="apii">[-0, +0, <em>v</em>]</span>
+<pre>void lua_toclose (lua_State *L, int index);</pre>
+
+<p>
+Marks the given index in the stack as a
+to-be-closed "variable" (see <a href="#3.3.8">&sect;3.3.8</a>).
+Like a to-be-closed variable in Lua,
+the value at that index in the stack will be closed
+when it goes out of scope.
+Here, in the context of a C function,
+to go out of scope means that the running function returns to Lua,
+there is an error,
+or the index is removed from the stack through
+<a href="#lua_settop"><code>lua_settop</code></a> or <a href="#lua_pop"><code>lua_pop</code></a>.
+An index marked as to-be-closed should not be removed from the stack
+by any other function in the API except <a href="#lua_settop"><code>lua_settop</code></a> or <a href="#lua_pop"><code>lua_pop</code></a>.
+
+
+<p>
+This function should not be called for an index
+that is equal to or below an already marked to-be-closed index.
+
+
+<p>
+This function can raise an out-of-memory error.
+In that case, the value in the given index is immediately closed,
+as if it was already marked.
+
+
+
+
+
 <hr><h3><a name="lua_tointeger"><code>lua_tointeger</code></a></h3><p>
 <span class="apii">[-0, +0, &ndash;]</span>
 <pre>lua_Integer lua_tointeger (lua_State *L, int index);</pre>

@@ -5238,7 +5380,7 @@
 <p>
 Converts the value at the given index to a generic
 C&nbsp;pointer (<code>void*</code>).
-The value can be a userdata, a table, a thread, or a function;
+The value can be a userdata, a table, a thread, a string, or a function;
 otherwise, <code>lua_topointer</code> returns <code>NULL</code>.
 Different objects will give different pointers.
 There is no way to convert the pointer back to its original value.

@@ -5284,7 +5426,7 @@
 If the value at the given index is a full userdata,
 returns its memory-block address.
 If the value is a light userdata,
-returns its pointer.
+returns its value (a pointer).
 Otherwise, returns <code>NULL</code>.
 
 

@@ -5297,7 +5439,7 @@
 
 <p>
 Returns the type of the value in the given valid index,
-or <code>LUA_TNONE</code> for a non-valid (but acceptable) index.
+or <code>LUA_TNONE</code> for a non-valid but acceptable index.
 The types returned by <a href="#lua_type"><code>lua_type</code></a> are coded by the following constants
 defined in <code>lua.h</code>:
 <a name="pdf-LUA_TNIL"><code>LUA_TNIL</code></a>,

@@ -5344,6 +5486,7 @@
 <p>
 Returns the pseudo-index that represents the <code>i</code>-th upvalue of
 the running function (see <a href="#4.4">&sect;4.4</a>).
+<code>i</code> must be in the range <em>[1,256]</em>.
 
 
 

@@ -5360,6 +5503,35 @@
 
 
 
+<hr><h3><a name="lua_WarnFunction"><code>lua_WarnFunction</code></a></h3>
+<pre>typedef void (*lua_WarnFunction) (void *ud, const char *msg, int tocont);</pre>
+
+<p>
+The type of warning functions, called by Lua to emit warnings.
+The first parameter is an opaque pointer
+set by <a href="#lua_setwarnf"><code>lua_setwarnf</code></a>.
+The second parameter is the warning message.
+The third parameter is a boolean that
+indicates whether the message is
+to be continued by the message in the next call.
+
+
+
+
+
+<hr><h3><a name="lua_warning"><code>lua_warning</code></a></h3><p>
+<span class="apii">[-0, +0, &ndash;]</span>
+<pre>void lua_warning (lua_State *L, const char *msg, int tocont);</pre>
+
+<p>
+Emits a warning with the given message.
+A message in a call with <code>tocont</code> true should be
+continued in another call to this function.
+
+
+
+
+
 <hr><h3><a name="lua_Writer"><code>lua_Writer</code></a></h3>
 <pre>typedef int (*lua_Writer) (lua_State *L,
                            const void* p,

@@ -5368,11 +5540,11 @@
 
 <p>
 The type of the writer function used by <a href="#lua_dump"><code>lua_dump</code></a>.
-Every time it produces another piece of chunk,
-<a href="#lua_dump"><code>lua_dump</code></a> calls the writer,
+Every time <a href="#lua_dump"><code>lua_dump</code></a> produces another piece of chunk,
+it calls the writer,
 passing along the buffer to be written (<code>p</code>),
 its size (<code>sz</code>),
-and the <code>data</code> parameter supplied to <a href="#lua_dump"><code>lua_dump</code></a>.
+and the <code>ud</code> parameter supplied to <a href="#lua_dump"><code>lua_dump</code></a>.
 
 
 <p>

@@ -5469,7 +5641,7 @@
 <p>
 This function can raise an error if it is called from a thread
 with a pending C call with no continuation function
-(what is called a <em>C-call boundary</em>,
+(what is called a <em>C-call boundary</em>),
 or it is called from a thread that is not running inside a resume
 (typically the main thread).
 

@@ -5498,6 +5670,7 @@
   const char *namewhat;       /* (n) */
   const char *what;           /* (S) */
   const char *source;         /* (S) */
+  size_t srclen;              /* (S) */
   int currentline;            /* (l) */
   int linedefined;            /* (S) */
   int lastlinedefined;        /* (S) */

@@ -5518,7 +5691,7 @@
 <a href="#lua_getstack"><code>lua_getstack</code></a> fills only the private part
 of this structure, for later use.
 To fill the other fields of <a href="#lua_Debug"><code>lua_Debug</code></a> with useful information,
-call <a href="#lua_getinfo"><code>lua_getinfo</code></a>.
+you must call <a href="#lua_getinfo"><code>lua_getinfo</code></a>.
 
 
 <p>

@@ -5527,7 +5700,7 @@
 <ul>
 
 <li><b><code>source</code>: </b>
-the name of the chunk that created the function.
+the source of the chunk that created the function.
 If <code>source</code> starts with a '<code>@</code>',
 it means that the function was defined in a file where
 the file name follows the '<code>@</code>'.

@@ -5538,6 +5711,10 @@
 <code>source</code> is that string.
 </li>
 
+<li><b><code>srclen</code>: </b>
+The length of the string <code>source</code>.
+</li>
+
 <li><b><code>short_src</code>: </b>
 a "printable" version of <code>source</code>, to be used in error messages.
 </li>

@@ -5738,7 +5915,8 @@
 </ul>
 
 <p>
-This function returns 0 if given an invalid option in <code>what</code>.
+This function returns 0 to signal an invalid option in <code>what</code>;
+even then the valid options are handled correctly.
 
 
 

@@ -5770,7 +5948,7 @@
 
 <p>
 In the second case, <code>ar</code> must be <code>NULL</code> and the function
-to be inspected must be at the top of the stack.
+to be inspected must be on the top of the stack.
 In this case, only parameters of Lua functions are visible
 (as there is no information about what variables are active)
 and no values are pushed onto the stack.

@@ -5800,9 +5978,9 @@
 Level&nbsp;0 is the current running function,
 whereas level <em>n+1</em> is the function that has called level <em>n</em>
 (except for tail calls, which do not count on the stack).
-When there are no errors, <a href="#lua_getstack"><code>lua_getstack</code></a> returns 1;
-when called with a level greater than the stack depth,
-it returns 0.
+When called with a level greater than the stack depth,
+<a href="#lua_getstack"><code>lua_getstack</code></a> returns 0;
+otherwise it returns 1.
 
 
 

@@ -5829,12 +6007,6 @@
 and that are consequently included in its closure.)
 
 
-<p>
-Upvalues have no particular order,
-as they are active through the whole function.
-They are numbered in an arbitrary order.
-
-
 
 
 

@@ -5915,25 +6087,23 @@
 
 <li><b>The return hook: </b> is called when the interpreter returns from a function.
 The hook is called just before Lua leaves the function.
-There is no standard way to access the values
-to be returned by the function.
 </li>
 
 <li><b>The line hook: </b> is called when the interpreter is about to
 start the execution of a new line of code,
 or when it jumps back in the code (even to the same line).
-(This event only happens while Lua is executing a Lua function.)
+This event only happens while Lua is executing a Lua function.
 </li>
 
 <li><b>The count hook: </b> is called after the interpreter executes every
 <code>count</code> instructions.
-(This event only happens while Lua is executing a Lua function.)
+This event only happens while Lua is executing a Lua function.
 </li>
 
 </ul>
 
 <p>
-A hook is disabled by setting <code>mask</code> to zero.
+Hooks are disabled by setting <code>mask</code> to zero.
 
 
 

@@ -5945,7 +6115,7 @@
 
 <p>
 Sets the value of a local variable of a given activation record.
-It assigns the value at the top of the stack
+It assigns the value on the top of the stack
 to the variable and returns its name.
 It also pops the value from the stack.
 

@@ -5957,7 +6127,7 @@
 
 
 <p>
-Parameters <code>ar</code> and <code>n</code> are as in function <a href="#lua_getlocal"><code>lua_getlocal</code></a>.
+Parameters <code>ar</code> and <code>n</code> are as in the function <a href="#lua_getlocal"><code>lua_getlocal</code></a>.
 
 
 

@@ -5969,7 +6139,7 @@
 
 <p>
 Sets the value of a closure's upvalue.
-It assigns the value at the top of the stack
+It assigns the value on the top of the stack
 to the upvalue and returns its name.
 It also pops the value from the stack.
 

@@ -5980,7 +6150,8 @@
 
 
 <p>
-Parameters <code>funcindex</code> and <code>n</code> are as in function <a href="#lua_getupvalue"><code>lua_getupvalue</code></a>.
+Parameters <code>funcindex</code> and <code>n</code> are as in
+the function <a href="#lua_getupvalue"><code>lua_getupvalue</code></a>.
 
 
 

@@ -6004,7 +6175,8 @@
 
 
 <p>
-Parameters <code>funcindex</code> and <code>n</code> are as in function <a href="#lua_getupvalue"><code>lua_getupvalue</code></a>,
+Parameters <code>funcindex</code> and <code>n</code> are as in
+the function <a href="#lua_getupvalue"><code>lua_getupvalue</code></a>,
 but <code>n</code> cannot be greater than the number of upvalues.
 
 

@@ -6094,6 +6266,21 @@
 
 
 
+<hr><h3><a name="luaL_addgsub"><code>luaL_addgsub</code></a></h3><p>
+<span class="apii">[-0, +0, <em>m</em>]</span>
+<pre>const void luaL_addgsub (luaL_Buffer *B, const char *s,
+                         const char *p, const char *r);</pre>
+
+<p>
+Adds a copy of the string <code>s</code> to the buffer <code>B</code>,
+replacing any occurrence of the string <code>p</code>
+with the string <code>r</code>.
+(see <a href="#luaL_Buffer"><code>luaL_Buffer</code></a>).
+
+
+
+
+
 <hr><h3><a name="luaL_addlstring"><code>luaL_addlstring</code></a></h3><p>
 <span class="apii">[-?, +?, <em>m</em>]</span>
 <pre>void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l);</pre>

@@ -6139,7 +6326,7 @@
 <pre>void luaL_addvalue (luaL_Buffer *B);</pre>
 
 <p>
-Adds the value at the top of the stack
+Adds the value on the top of the stack
 to the buffer <code>B</code>
 (see <a href="#luaL_Buffer"><code>luaL_Buffer</code></a>).
 Pops the value.

@@ -6188,6 +6375,22 @@
 
 
 
+<hr><h3><a name="luaL_argexpected"><code>luaL_argexpected</code></a></h3><p>
+<span class="apii">[-0, +0, <em>v</em>]</span>
+<pre>void luaL_argexpected (lua_State *L,
+                       int cond,
+                       int arg,
+                       const char *tname);</pre>
+
+<p>
+Checks whether <code>cond</code> is true.
+If it is not, raises an error about the type of the argument <code>arg</code>
+with a standard message (see <a href="#luaL_typeerror"><code>luaL_typeerror</code></a>).
+
+
+
+
+
 <hr><h3><a name="luaL_Buffer"><code>luaL_Buffer</code></a></h3>
 <pre>typedef struct luaL_Buffer luaL_Buffer;</pre>
 

@@ -6218,7 +6421,7 @@
 </ul>
 
 <p>
-If you know beforehand the total size of the resulting string,
+If you know beforehand the maximum size of the resulting string,
 you can use the buffer like this:
 
 <ul>

@@ -6233,7 +6436,8 @@
 <li>
 Finish by calling <code>luaL_pushresultsize(&amp;b, sz)</code>,
 where <code>sz</code> is the total size of the resulting string
-copied into that space.
+copied into that space (which may be less than or
+equal to the preallocated size).
 </li>
 
 </ul>

@@ -6250,14 +6454,27 @@
 the stack is at the same level
 it was immediately after the previous buffer operation.
 (The only exception to this rule is <a href="#luaL_addvalue"><code>luaL_addvalue</code></a>.)
-After calling <a href="#luaL_pushresult"><code>luaL_pushresult</code></a> the stack is back to its
-level when the buffer was initialized,
+After calling <a href="#luaL_pushresult"><code>luaL_pushresult</code></a>,
+the stack is back to its level when the buffer was initialized,
 plus the final string on its top.
 
 
 
 
 
+<hr><h3><a name="luaL_buffaddr"><code>luaL_buffaddr</code></a></h3><p>
+<span class="apii">[-0, +0, &ndash;]</span>
+<pre>char *luaL_buffaddr (luaL_Buffer *B);</pre>
+
+<p>
+Returns the address of the current contents of buffer <code>B</code>.
+Note that any addition to the buffer may invalidate this address.
+(see <a href="#luaL_Buffer"><code>luaL_Buffer</code></a>).
+
+
+
+
+
 <hr><h3><a name="luaL_buffinit"><code>luaL_buffinit</code></a></h3><p>
 <span class="apii">[-0, +0, &ndash;]</span>
 <pre>void luaL_buffinit (lua_State *L, luaL_Buffer *B);</pre>

@@ -6272,6 +6489,18 @@
 
 
 
+<hr><h3><a name="luaL_bufflen"><code>luaL_bufflen</code></a></h3><p>
+<span class="apii">[-0, +0, &ndash;]</span>
+<pre>size_t luaL_bufflen (luaL_Buffer *B);</pre>
+
+<p>
+Returns the length of the current contents of buffer <code>B</code>.
+(see <a href="#luaL_Buffer"><code>luaL_Buffer</code></a>).
+
+
+
+
+
 <hr><h3><a name="luaL_buffinitsize"><code>luaL_buffinitsize</code></a></h3><p>
 <span class="apii">[-?, +?, <em>m</em>]</span>
 <pre>char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz);</pre>

@@ -6299,7 +6528,7 @@
 In this case this function returns true and pushes onto the
 stack the value returned by the call.
 If there is no metatable or no metamethod,
-this function returns false (without pushing any value on the stack).
+this function returns false without pushing any value on the stack.
 
 
 

@@ -6324,7 +6553,7 @@
 <p>
 Checks whether the function argument <code>arg</code> is an integer
 (or can be converted to an integer)
-and returns this integer cast to a <a href="#lua_Integer"><code>lua_Integer</code></a>.
+and returns this integer.
 
 
 

@@ -6337,7 +6566,7 @@
 <p>
 Checks whether the function argument <code>arg</code> is a string
 and returns this string;
-if <code>l</code> is not <code>NULL</code> fills <code>*l</code>
+if <code>l</code> is not <code>NULL</code> fills its referent
 with the string's length.
 
 

@@ -6355,7 +6584,7 @@
 
 <p>
 Checks whether the function argument <code>arg</code> is a number
-and returns this number.
+and returns this number converted to a <code>lua_Number</code>.
 
 
 

@@ -6598,8 +6827,8 @@
                        const char *r);</pre>
 
 <p>
-Creates a copy of string <code>s</code> by replacing
-any occurrence of the string <code>p</code>
+Creates a copy of string <code>s</code>,
+replacing any occurrence of the string <code>p</code>
 with the string <code>r</code>.
 Pushes the resulting string on the stack and returns it.
 

@@ -6616,7 +6845,7 @@
 as a number;
 it is equivalent to the '<code>#</code>' operator in Lua (see <a href="#3.4.7">&sect;3.4.7</a>).
 Raises an error if the result of the operation is not an integer.
-(This case only can happen through metamethods.)
+(This case can only happen through metamethods.)
 
 
 

@@ -6654,7 +6883,7 @@
 This function returns the same results as <a href="#lua_load"><code>lua_load</code></a>.
 <code>name</code> is the chunk name,
 used for debug information and error messages.
-The string <code>mode</code> works as in function <a href="#lua_load"><code>lua_load</code></a>.
+The string <code>mode</code> works as in the function <a href="#lua_load"><code>lua_load</code></a>.
 
 
 

@@ -6686,7 +6915,7 @@
 
 
 <p>
-The string <code>mode</code> works as in function <a href="#lua_load"><code>lua_load</code></a>.
+The string <code>mode</code> works as in the function <a href="#lua_load"><code>lua_load</code></a>.
 
 
 <p>

@@ -6732,7 +6961,7 @@
 
 <p>
 Creates a new table and registers there
-the functions in list <code>l</code>.
+the functions in the list <code>l</code>.
 
 
 <p>

@@ -6785,7 +7014,8 @@
 
 
 <p>
-In both cases pushes onto the stack the final value associated
+In both cases,
+the function pushes onto the stack the final value associated
 with <code>tname</code> in the registry.
 
 

@@ -6799,10 +7029,9 @@
 <p>
 Creates a new Lua state.
 It calls <a href="#lua_newstate"><code>lua_newstate</code></a> with an
-allocator based on the standard&nbsp;C <code>realloc</code> function
-and then sets a panic function (see <a href="#4.6">&sect;4.6</a>) that prints
-an error message to the standard error output in case of fatal
-errors.
+allocator based on the standard&nbsp;C allocation functions
+and then sets a warning function and a panic function (see <a href="#4.6">&sect;4.6</a>)
+that print messages to the standard error output.
 
 
 <p>

@@ -6838,7 +7067,7 @@
 the macro results in the default <code>dflt</code>.
 Otherwise, it results in the result of calling <code>func</code>
 with the state <code>L</code> and the argument index <code>arg</code> as
-parameters.
+arguments.
 Note that it evaluates the expression <code>dflt</code> only if needed.
 
 

@@ -6853,7 +7082,7 @@
 
 <p>
 If the function argument <code>arg</code> is an integer
-(or convertible to an integer),
+(or it is convertible to an integer),
 returns this integer.
 If this argument is absent or is <b>nil</b>,
 returns <code>d</code>.

@@ -6880,7 +7109,7 @@
 
 <p>
 If <code>l</code> is not <code>NULL</code>,
-fills the position <code>*l</code> with the result's length.
+fills its referent with the result's length.
 If the result is <code>NULL</code>
 (only possible when returning <code>d</code> and <code>d == NULL</code>),
 its length is considered zero.

@@ -6900,7 +7129,7 @@
 
 <p>
 If the function argument <code>arg</code> is a number,
-returns this number.
+returns this number as a <code>lua_Number</code>.
 If this argument is absent or is <b>nil</b>,
 returns <code>d</code>.
 Otherwise, raises an error.

@@ -6984,20 +7213,20 @@
 <p>
 Creates and returns a <em>reference</em>,
 in the table at index <code>t</code>,
-for the object at the top of the stack (and pops the object).
+for the object on the top of the stack (and pops the object).
 
 
 <p>
 A reference is a unique integer key.
-As long as you do not manually add integer keys into table <code>t</code>,
+As long as you do not manually add integer keys into the table <code>t</code>,
 <a href="#luaL_ref"><code>luaL_ref</code></a> ensures the uniqueness of the key it returns.
-You can retrieve an object referred by reference <code>r</code>
+You can retrieve an object referred by the reference <code>r</code>
 by calling <code>lua_rawgeti(L, t, r)</code>.
-Function <a href="#luaL_unref"><code>luaL_unref</code></a> frees a reference and its associated object.
+The function <a href="#luaL_unref"><code>luaL_unref</code></a> frees a reference.
 
 
 <p>
-If the object at the top of the stack is <b>nil</b>,
+If the object on the top of the stack is <b>nil</b>,
 <a href="#luaL_ref"><code>luaL_ref</code></a> returns the constant <a name="pdf-LUA_REFNIL"><code>LUA_REFNIL</code></a>.
 The constant <a name="pdf-LUA_NOREF"><code>LUA_NOREF</code></a> is guaranteed to be different
 from any reference returned by <a href="#luaL_ref"><code>luaL_ref</code></a>.

@@ -7031,14 +7260,14 @@
 
 <p>
 If <code>package.loaded[modname]</code> is not true,
-calls function <code>openf</code> with string <code>modname</code> as an argument
+calls the function <code>openf</code> with the string <code>modname</code> as an argument
 and sets the call result to <code>package.loaded[modname]</code>,
 as if that function has been called through <a href="#pdf-require"><code>require</code></a>.
 
 
 <p>
 If <code>glb</code> is true,
-also stores the module into global <code>modname</code>.
+also stores the module into the global <code>modname</code>.
 
 
 <p>

@@ -7075,7 +7304,7 @@
 <pre>void luaL_setmetatable (lua_State *L, const char *tname);</pre>
 
 <p>
-Sets the metatable of the object at the top of the stack
+Sets the metatable of the object on the top of the stack
 as the metatable associated with name <code>tname</code>
 in the registry (see <a href="#luaL_newmetatable"><code>luaL_newmetatable</code></a>).
 

@@ -7090,8 +7319,8 @@
 } luaL_Stream;</pre>
 
 <p>
-The standard representation for file handles,
-which is used by the standard I/O library.
+The standard representation for file handles
+used by the standard I/O library.
 
 
 <p>

@@ -7105,14 +7334,14 @@
 <p>
 This userdata must start with the structure <code>luaL_Stream</code>;
 it can contain other data after this initial structure.
-Field <code>f</code> points to the corresponding C stream
+The field <code>f</code> points to the corresponding C stream
 (or it can be <code>NULL</code> to indicate an incompletely created handle).
-Field <code>closef</code> points to a Lua function
+The field <code>closef</code> points to a Lua function
 that will be called to close the stream
 when the handle is closed or collected;
 this function receives the file handle as its sole argument and
-must return either <b>true</b> (in case of success)
-or <b>nil</b> plus an error message (in case of error).
+must return either <b>true</b>, in case of success,
+or <b>nil</b> plus an error message, in case of error.
 Once Lua calls this field,
 it changes the field value to <code>NULL</code>
 to signal that the handle is closed.

@@ -7164,7 +7393,7 @@
 
 <p>
 Creates and pushes a traceback of the stack <code>L1</code>.
-If <code>msg</code> is not <code>NULL</code> it is appended
+If <code>msg</code> is not <code>NULL</code>, it is appended
 at the beginning of the traceback.
 The <code>level</code> parameter tells at which level
 to start the traceback.

@@ -7173,6 +7402,23 @@
 
 
 
+<hr><h3><a name="luaL_typeerror"><code>luaL_typeerror</code></a></h3><p>
+<span class="apii">[-0, +0, <em>v</em>]</span>
+<pre>const char *luaL_typeerror (lua_State *L,
+                                      int arg,
+                                      const char *tname);</pre>
+
+<p>
+Raises a type error for the argument <code>arg</code>
+of the C&nbsp;function that called it,
+using a standard message;
+<code>tname</code> is a "name" for the expected type.
+This function never returns.
+
+
+
+
+
 <hr><h3><a name="luaL_typename"><code>luaL_typename</code></a></h3><p>
 <span class="apii">[-0, +0, &ndash;]</span>
 <pre>const char *luaL_typename (lua_State *L, int index);</pre>

@@ -7189,7 +7435,7 @@
 <pre>void luaL_unref (lua_State *L, int t, int ref);</pre>
 
 <p>
-Releases reference <code>ref</code> from the table at index <code>t</code>
+Releases the reference <code>ref</code> from the table at index <code>t</code>
 (see <a href="#luaL_ref"><code>luaL_ref</code></a>).
 The entry is removed from the table,
 so that the referred object can be collected.

@@ -7230,16 +7476,16 @@
 
 
 
-<h1>6 &ndash; <a name="6">Standard Libraries</a></h1>
+<h1>6 &ndash; <a name="6">The Standard Libraries</a></h1>
 
 <p>
 The standard Lua libraries provide useful functions
-that are implemented directly through the C&nbsp;API.
+that are implemented in&nbsp;C through the C&nbsp;API.
 Some of these functions provide essential services to the language
 (e.g., <a href="#pdf-type"><code>type</code></a> and <a href="#pdf-getmetatable"><code>getmetatable</code></a>);
-others provide access to "outside" services (e.g., I/O);
+others provide access to outside services (e.g., I/O);
 and others could be implemented in Lua itself,
-but are quite useful or have critical performance requirements that
+but that for different reasons
 deserve an implementation in C (e.g., <a href="#pdf-table.sort"><code>table.sort</code></a>).
 
 

@@ -7295,7 +7541,7 @@
 <a name="pdf-luaopen_package"><code>luaopen_package</code></a> (for the package library),
 <a name="pdf-luaopen_coroutine"><code>luaopen_coroutine</code></a> (for the coroutine library),
 <a name="pdf-luaopen_string"><code>luaopen_string</code></a> (for the string library),
-<a name="pdf-luaopen_utf8"><code>luaopen_utf8</code></a> (for the UTF8 library),
+<a name="pdf-luaopen_utf8"><code>luaopen_utf8</code></a> (for the UTF-8 library),
 <a name="pdf-luaopen_table"><code>luaopen_table</code></a> (for the table library),
 <a name="pdf-luaopen_math"><code>luaopen_math</code></a> (for the mathematical library),
 <a name="pdf-luaopen_io"><code>luaopen_io</code></a> (for the I/O library),

@@ -7358,8 +7604,7 @@
 returns the total memory in use by Lua in Kbytes.
 The value has a fractional part,
 so that it multiplied by 1024
-gives the exact number of bytes in use by Lua
-(except for overflows).
+gives the exact number of bytes in use by Lua.
 </li>
 
 <li><b>"<code>step</code>": </b>

@@ -7385,6 +7630,7 @@
 the garbage-collector pause,
 the step multiplier,
 and the step size.
+A zero means to not change that value.
 </li>
 
 <li><b>"<code>generational</code>": </b>

@@ -7392,6 +7638,7 @@
 This option can be followed by two numbers:
 the garbage-collector minor multiplier
 and the major multiplier.
+A zero means to not change that value.
 </li>
 
 <li><b>"<code>isrunning</code>": </b>

@@ -7399,7 +7646,10 @@
 (i.e., not stopped).
 </li>
 
-</ul>
+</ul><p>
+See <a href="#2.5">&sect;2.5</a> for more details about garbage collection
+and some of these options.
+
 
 
 

@@ -7410,7 +7660,8 @@
 <code>dofile</code> executes the contents of the standard input (<code>stdin</code>).
 Returns all values returned by the chunk.
 In case of errors, <code>dofile</code> propagates the error
-to its caller (that is, <code>dofile</code> does not run in protected mode).
+to its caller.
+(That is, <code>dofile</code> does not run in protected mode.)
 
 
 

@@ -7419,7 +7670,7 @@
 <hr><h3><a name="pdf-error"><code>error (message [, level])</code></a></h3>
 Terminates the last protected function called
 and returns <code>message</code> as the error object.
-Function <code>error</code> never returns.
+This function never returns.
 
 
 <p>

@@ -7503,17 +7754,23 @@
 
 
 <p>
-If the resulting function has upvalues,
-the first upvalue is set to the value of <code>env</code>,
-if that parameter is given,
-or to the value of the global environment.
-Other upvalues are initialized with <b>nil</b>.
-(When you load a main chunk,
+When you load a main chunk,
 the resulting function will always have exactly one upvalue,
 the <code>_ENV</code> variable (see <a href="#2.2">&sect;2.2</a>).
 However,
 when you load a binary chunk created from a function (see <a href="#pdf-string.dump"><code>string.dump</code></a>),
-the resulting function can have an arbitrary number of upvalues.)
+the resulting function can have an arbitrary number of upvalues,
+and there is no guarantee that its first upvalue will be
+the <code>_ENV</code> variable.
+(A non-main function may not even have an <code>_ENV</code> upvalue.)
+
+
+<p>
+Regardless, if the resulting function has any upvalues,
+its first upvalue is set to the value of <code>env</code>,
+if that parameter is given,
+or to the value of the global environment.
+Other upvalues are initialized with <b>nil</b>.
 All upvalues are fresh, that is,
 they are not shared with any other function.
 

@@ -7564,7 +7821,7 @@
 Allows a program to traverse all fields of a table.
 Its first argument is a table and its second argument
 is an index in this table.
-<code>next</code> returns the next index of the table
+A call to <code>next</code> returns the next index of the table
 and its associated value.
 When called with <b>nil</b> as its second argument,
 <code>next</code> returns an initial index

@@ -7627,7 +7884,7 @@
 
 
 <p>
-Calls function <code>f</code> with
+Calls the function <code>f</code> with
 the given arguments in <em>protected mode</em>.
 This means that any error inside&nbsp;<code>f</code> is not propagated;
 instead, <code>pcall</code> catches the error

@@ -7636,7 +7893,7 @@
 which is true if the call succeeds without errors.
 In such case, <code>pcall</code> also returns all results from the call,
 after this first result.
-In case of any error, <code>pcall</code> returns <b>false</b> plus the error message.
+In case of any error, <code>pcall</code> returns <b>false</b> plus the error object.
 
 
 

@@ -7645,8 +7902,12 @@
 <hr><h3><a name="pdf-print"><code>print (&middot;&middot;&middot;)</code></a></h3>
 Receives any number of arguments
 and prints their values to <code>stdout</code>,
-using the <a href="#pdf-tostring"><code>tostring</code></a> function to convert each argument to a string.
-<code>print</code> is not intended for formatted output,
+converting each argument to a string
+following the same rules of <a href="#pdf-tostring"><code>tostring</code></a>.
+
+
+<p>
+The function <code>print</code> is not intended for formatted output,
 but only as a quick way to show a value,
 for instance for debugging.
 For complete control over the output,

@@ -7719,8 +7980,6 @@
 
 <p>
 Sets the metatable for the given table.
-(To change the metatable of other types from Lua code,
-you must use the debug library (<a href="#6.10">&sect;6.10</a>).)
 If <code>metatable</code> is <b>nil</b>,
 removes the metatable of the given table.
 If the original metatable has a <code>__metatable</code> field,

@@ -7731,6 +7990,11 @@
 This function returns <code>table</code>.
 
 
+<p>
+To change the metatable of other types from Lua code,
+you must use the debug library (<a href="#6.10">&sect;6.10</a>).
+
+
 
 
 <p>

@@ -7749,7 +8013,7 @@
 <p>
 The conversion of strings can result in integers or floats,
 according to the lexical conventions of Lua (see <a href="#3.1">&sect;3.1</a>).
-(The string may have leading and trailing spaces and a sign.)
+The string may have leading and trailing spaces and a sign.
 
 
 <p>

@@ -7812,6 +8076,19 @@
 
 
 <p>
+<hr><h3><a name="pdf-warn"><code>warn (message [, tocont])</code></a></h3>
+
+
+<p>
+Emits a warning with the given message.
+A message in a call with <code>tocont</code> true should be
+continued in another call to this function.
+The default for <code>tocont</code> is false.
+
+
+
+
+<p>
 <hr><h3><a name="pdf-xpcall"><code>xpcall (f, msgh [, arg1, &middot;&middot;&middot;])</code></a></h3>
 
 

@@ -7847,21 +8124,37 @@
 
 
 <p>
-<hr><h3><a name="pdf-coroutine.isyieldable"><code>coroutine.isyieldable ()</code></a></h3>
+<hr><h3><a name="pdf-coroutine.isyieldable"><code>coroutine.isyieldable ([co])</code></a></h3>
 
 
 <p>
-Returns true when the running coroutine can yield.
+Returns true when the coroutine <code>co</code> can yield.
+The default for <code>co</code> is the running coroutine.
 
 
 <p>
-A running coroutine is yieldable if it is not the main thread and
+A coroutine is yieldable if it is not the main thread and
 it is not inside a non-yieldable C&nbsp;function.
 
 
 
 
 <p>
+<hr><h3><a name="pdf-coroutine.kill"><code>coroutine.kill (co)</code></a></h3>
+
+
+<p>
+Kills coroutine <code>co</code>,
+closing all its pending to-be-closed variables
+and putting the coroutine in a dead state.
+In case of error closing some variable,
+returns <b>false</b> plus the error object;
+otherwise returns <b>true</b>.
+
+
+
+
+<p>
 <hr><h3><a name="pdf-coroutine.resume"><code>coroutine.resume (co [, val1, &middot;&middot;&middot;])</code></a></h3>
 
 

@@ -7904,7 +8197,7 @@
 
 
 <p>
-Returns the status of coroutine <code>co</code>, as a string:
+Returns the status of the coroutine <code>co</code>, as a string:
 <code>"running"</code>,
 if the coroutine is running (that is, it called <code>status</code>);
 <code>"suspended"</code>, if the coroutine is suspended in a call to <code>yield</code>,

@@ -7922,14 +8215,15 @@
 
 
 <p>
-Creates a new coroutine, with body <code>f</code>.
+Creates a new coroutine, with body <code>f</code>;
 <code>f</code> must be a function.
 Returns a function that resumes the coroutine each time it is called.
-Any arguments passed to the function behave as the
+Any arguments passed to this function behave as the
 extra arguments to <code>resume</code>.
-Returns the same values returned by <code>resume</code>,
+The function returns the same values returned by <code>resume</code>,
 except the first boolean.
-In case of error, propagates the error.
+In case of error,
+the function kills the coroutine and propagates the error.
 
 
 

@@ -7955,7 +8249,7 @@
 facilities for loading modules in Lua.
 It exports one function directly in the global environment:
 <a href="#pdf-require"><code>require</code></a>.
-Everything else is exported in a table <a name="pdf-package"><code>package</code></a>.
+Everything else is exported in the table <a name="pdf-package"><code>package</code></a>.
 
 
 <p>

@@ -7968,13 +8262,17 @@
 to determine whether <code>modname</code> is already loaded.
 If it is, then <code>require</code> returns the value stored
 at <code>package.loaded[modname]</code>.
+(The absence of a second result in this case
+signals that this call did not have to load the module.)
 Otherwise, it tries to find a <em>loader</em> for the module.
 
 
 <p>
 To find a loader,
-<code>require</code> is guided by the <a href="#pdf-package.searchers"><code>package.searchers</code></a> sequence.
-By changing this sequence,
+<code>require</code> is guided by the table <a href="#pdf-package.searchers"><code>package.searchers</code></a>.
+Each item in this table is a search function,
+that searches for the module in a particular way.
+By changing this table,
 we can change how <code>require</code> looks for a module.
 The following explanation is based on the default configuration
 for <a href="#pdf-package.searchers"><code>package.searchers</code></a>.

@@ -7995,9 +8293,14 @@
 <p>
 Once a loader is found,
 <code>require</code> calls the loader with two arguments:
-<code>modname</code> and an extra value dependent on how it got the loader.
-(If the loader came from a file,
-this extra value is the file name.)
+<code>modname</code> and an extra value,
+a <em>loader data</em>,
+also returned by the searcher.
+The loader data can be any value useful to the module;
+for the default searchers,
+it indicates where the loader was found.
+(For instance, if the loader came from a file,
+this extra value is the file path.)
 If the loader returns any non-nil value,
 <code>require</code> assigns the returned value to <code>package.loaded[modname]</code>.
 If the loader does not return a non-nil value and

@@ -8005,6 +8308,9 @@
 then <code>require</code> assigns <b>true</b> to this entry.
 In any case, <code>require</code> returns the
 final value of <code>package.loaded[modname]</code>.
+Besides that value, <code>require</code> also returns as a second result
+the loader data returned by the searcher,
+which indicates how <code>require</code> found the module.
 
 
 <p>

@@ -8140,7 +8446,7 @@
 the environment variable <a name="pdf-LUA_PATH"><code>LUA_PATH</code></a> or
 with a default path defined in <code>luaconf.h</code>,
 if those environment variables are not defined.
-Any "<code>;;</code>" in the value of the environment variable
+A "<code>;;</code>" in the value of the environment variable
 is replaced by the default path.
 
 

@@ -8168,7 +8474,7 @@
 
 
 <p>
-A table used by <a href="#pdf-require"><code>require</code></a> to control how to load modules.
+A table used by <a href="#pdf-require"><code>require</code></a> to control how to find modules.
 
 
 <p>

@@ -8176,10 +8482,14 @@
 When looking for a module,
 <a href="#pdf-require"><code>require</code></a> calls each of these searchers in ascending order,
 with the module name (the argument given to <a href="#pdf-require"><code>require</code></a>) as its
-sole parameter.
-The function can return another function (the module <em>loader</em>)
-plus an extra value that will be passed to that loader,
-or a string explaining why it did not find that module
+sole argument.
+If the searcher finds the module,
+it returns another function, the module <em>loader</em>,
+plus an extra value, a <em>loader data</em>,
+that will be passed to that loader and
+returned as a second result by <a href="#pdf-require"><code>require</code></a>.
+If it cannot find the module,
+it returns a string explaining why
 (or <b>nil</b> if it has nothing to say).
 
 

@@ -8242,9 +8552,15 @@
 
 <p>
 All searchers except the first one (preload) return as the extra value
-the file name where the module was found,
+the file path where the module was found,
 as returned by <a href="#pdf-package.searchpath"><code>package.searchpath</code></a>.
-The first searcher returns no extra value.
+The first searcher always returns the string "<code>:preload:</code>".
+
+
+<p>
+Searchers should raise no errors and have no side effects in Lua.
+(They may have side effects in C,
+for instance by linking the application with a library.)
 
 
 

@@ -8369,8 +8685,10 @@
 <p>
 Functions with upvalues have only their number of upvalues saved.
 When (re)loaded,
-those upvalues receive fresh instances containing <b>nil</b>.
-(You can use the debug library to serialize
+those upvalues receive fresh instances.
+(See the <a href="#pdf-load"><code>load</code></a> function for details about
+how these upvalues are initialized.
+You can use the debug library to serialize
 and reload the upvalues of a function
 in a way adequate to your needs.)
 

@@ -8412,16 +8730,16 @@
 
 <p>
 Returns a formatted version of its variable number of arguments
-following the description given in its first argument (which must be a string).
+following the description given in its first argument,
+which must be a string.
 The format string follows the same rules as the ISO&nbsp;C function <code>sprintf</code>.
-The only differences are that the options/modifiers
-<code>*</code>, <code>h</code>, <code>L</code>, <code>l</code>, <code>n</code>,
-and <code>p</code> are not supported
-and that there is an extra option, <code>q</code>.
+The only differences are that the conversion specifiers and modifiers
+<code>*</code>, <code>h</code>, <code>L</code>, <code>l</code>, and <code>n</code> are not supported
+and that there is an extra specifier, <code>q</code>.
 
 
 <p>
-The <code>q</code> option formats booleans, nil, numbers, and strings
+The specifier <code>q</code> formats booleans, nil, numbers, and strings
 in a way that the result is a valid constant in Lua source code.
 Booleans and nil are written in the obvious way
 (<code>true</code>, <code>false</code>, <code>nil</code>).

@@ -8440,38 +8758,53 @@
 <pre>
      "a string with \"quotes\" and \
       new line"
-</pre>
+</pre><p>
+This specifier does not support modifiers (flags, width, length).
+
 
 <p>
-Options
+The conversion specifiers
 <code>A</code>, <code>a</code>, <code>E</code>, <code>e</code>, <code>f</code>,
 <code>G</code>, and <code>g</code> all expect a number as argument.
-Options <code>c</code>, <code>d</code>,
+The specifiers <code>c</code>, <code>d</code>,
 <code>i</code>, <code>o</code>, <code>u</code>, <code>X</code>, and <code>x</code>
 expect an integer.
 When Lua is compiled with a C89 compiler,
-options <code>A</code> and <code>a</code> (hexadecimal floats)
-do not support any modifier (flags, width, length).
+the specifiers <code>A</code> and <code>a</code> (hexadecimal floats)
+do not support modifiers.
 
 
 <p>
-Option <code>s</code> expects a string;
+The specifier <code>s</code> expects a string;
 if its argument is not a string,
 it is converted to one following the same rules of <a href="#pdf-tostring"><code>tostring</code></a>.
-If the option has any modifier (flags, width, length),
-the string argument should not contain embedded zeros.
+If the specifier has any modifier,
+the corresponding string argument should not contain embedded zeros.
+
+
+<p>
+The specifier <code>p</code> formats the pointer
+returned by <a href="#lua_topointer"><code>lua_topointer</code></a>.
+That gives a unique string identifier for tables, userdata,
+threads, strings, and functions.
+For other values (numbers, nil, booleans),
+this specifier results in a string representing
+the pointer <code>NULL</code>.
 
 
 
 
 <p>
-<hr><h3><a name="pdf-string.gmatch"><code>string.gmatch (s, pattern)</code></a></h3>
+<hr><h3><a name="pdf-string.gmatch"><code>string.gmatch (s, pattern [, init])</code></a></h3>
 Returns an iterator function that,
 each time it is called,
 returns the next captures from <code>pattern</code> (see <a href="#6.4.1">&sect;6.4.1</a>)
 over the string <code>s</code>.
 If <code>pattern</code> specifies no captures,
 then the whole match is produced in each call.
+A third, optional numeric argument <code>init</code> specifies
+where to start the search;
+its default value is&nbsp;1 and can be negative.
 
 
 <p>

@@ -8520,9 +8853,9 @@
 The character&nbsp;<code>%</code> works as an escape character:
 any sequence in <code>repl</code> of the form <code>%<em>d</em></code>,
 with <em>d</em> between 1 and 9,
-stands for the value of the <em>d</em>-th captured substring.
-The sequence <code>%0</code> stands for the whole match.
-The sequence <code>%%</code> stands for a single&nbsp;<code>%</code>.
+stands for the value of the <em>d</em>-th captured substring;
+the sequence <code>%0</code> stands for the whole match;
+the sequence <code>%%</code> stands for a single&nbsp;<code>%</code>.
 
 
 <p>

@@ -8581,6 +8914,9 @@
 
 <p>
 <hr><h3><a name="pdf-string.len"><code>string.len (s)</code></a></h3>
+
+
+<p>
 Receives a string and returns its length.
 The empty string <code>""</code> has length 0.
 Embedded zeros are counted,

@@ -8591,6 +8927,9 @@
 
 <p>
 <hr><h3><a name="pdf-string.lower"><code>string.lower (s)</code></a></h3>
+
+
+<p>
 Receives a string and returns a copy of this string with all
 uppercase letters changed to lowercase.
 All other characters are left unchanged.

@@ -8601,8 +8940,11 @@
 
 <p>
 <hr><h3><a name="pdf-string.match"><code>string.match (s, pattern [, init])</code></a></h3>
+
+
+<p>
 Looks for the first <em>match</em> of
-<code>pattern</code> (see <a href="#6.4.1">&sect;6.4.1</a>) in the string <code>s</code>.
+the <code>pattern</code> (see <a href="#6.4.1">&sect;6.4.1</a>) in the string <code>s</code>.
 If it finds one, then <code>match</code> returns
 the captures from the pattern;
 otherwise it returns <b>nil</b>.

@@ -8621,7 +8963,7 @@
 
 <p>
 Returns a binary string containing the values <code>v1</code>, <code>v2</code>, etc.
-packed (that is, serialized in binary form)
+serialized in binary form (packed)
 according to the format string <code>fmt</code> (see <a href="#6.4.2">&sect;6.4.2</a>).
 
 

@@ -8642,6 +8984,9 @@
 
 <p>
 <hr><h3><a name="pdf-string.rep"><code>string.rep (s, n [, sep])</code></a></h3>
+
+
+<p>
 Returns a string that is the concatenation of <code>n</code> copies of
 the string <code>s</code> separated by the string <code>sep</code>.
 The default value for <code>sep</code> is the empty string

@@ -8658,6 +9003,9 @@
 
 <p>
 <hr><h3><a name="pdf-string.reverse"><code>string.reverse (s)</code></a></h3>
+
+
+<p>
 Returns a string that is the string <code>s</code> reversed.
 
 

@@ -8665,6 +9013,9 @@
 
 <p>
 <hr><h3><a name="pdf-string.sub"><code>string.sub (s, i [, j])</code></a></h3>
+
+
+<p>
 Returns the substring of <code>s</code> that
 starts at <code>i</code>  and continues until <code>j</code>;
 <code>i</code> and <code>j</code> can be negative.

@@ -8708,6 +9059,9 @@
 
 <p>
 <hr><h3><a name="pdf-string.upper"><code>string.upper (s)</code></a></h3>
+
+
+<p>
 Receives a string and returns a copy of this string with all
 lowercase letters changed to uppercase.
 All other characters are left unchanged.

@@ -8770,8 +9124,7 @@
 This is the standard way to escape the magic characters.
 Any non-alphanumeric character
 (including all punctuation characters, even the non-magical)
-can be preceded by a '<code>%</code>'
-when used to represent itself in a pattern.
+can be preceded by a '<code>%</code>' to represent itself in a pattern.
 </li>
 
 <li><b><code>[<em>set</em>]</code>: </b>

@@ -8836,19 +9189,19 @@
 
 <li>
 a single character class followed by '<code>*</code>',
-which matches zero or more repetitions of characters in the class.
+which matches sequences of zero or more characters in the class.
 These repetition items will always match the longest possible sequence;
 </li>
 
 <li>
 a single character class followed by '<code>+</code>',
-which matches one or more repetitions of characters in the class.
+which matches sequences of one or more characters in the class.
 These repetition items will always match the longest possible sequence;
 </li>
 
 <li>
 a single character class followed by '<code>-</code>',
-which also matches zero or more repetitions of characters in the class.
+which also matches sequences of zero or more characters in the class.
 Unlike '<code>*</code>',
 these repetition items will always match the shortest possible sequence;
 </li>

@@ -8912,7 +9265,7 @@
 Captures are numbered according to their left parentheses.
 For instance, in the pattern <code>"(a*(.)%w(%s*))"</code>,
 the part of the string matching <code>"a*(.)%w(%s*)"</code> is
-stored as the first capture (and therefore has number&nbsp;1);
+stored as the first capture, and therefore has number&nbsp;1;
 the character matching "<code>.</code>" is captured with number&nbsp;2,
 and the part matching "<code>%s*</code>" has number&nbsp;3.
 

@@ -8932,14 +9285,14 @@
 match multiple occurrences of the given pattern in the subject.
 For these functions,
 a new match is considered valid only
-if it ends at least one byte after the previous match.
+if it ends at least one byte after the end of the previous match.
 In other words, the pattern machine never accepts the
 empty string as a match immediately after another match.
 As an example,
 consider the results of the following code:
 
 <pre>
-     &gt; string.gsub("abc", "()a*()", print)
+     &gt; string.gsub("abc", "()a*()", print);
      --&gt; 1   2
      --&gt; 3   3
      --&gt; 4   4

@@ -9004,8 +9357,8 @@
 (A "<code>[<em>n</em>]</code>" means an optional integral numeral.)
 Except for padding, spaces, and configurations
 (options "<code>xX &lt;=&gt;!</code>"),
-each option corresponds to an argument (in <a href="#pdf-string.pack"><code>string.pack</code></a>)
-or a result (in <a href="#pdf-string.unpack"><code>string.unpack</code></a>).
+each option corresponds to an argument in <a href="#pdf-string.pack"><code>string.pack</code></a>
+or a result in <a href="#pdf-string.unpack"><code>string.unpack</code></a>.
 
 
 <p>

@@ -9014,6 +9367,8 @@
 All integral options check overflows;
 <a href="#pdf-string.pack"><code>string.pack</code></a> checks whether the given value fits in the given size;
 <a href="#pdf-string.unpack"><code>string.unpack</code></a> checks whether the read value fits in a Lua integer.
+For the unsigned options,
+Lua integers are treated as unsigned values too.
 
 
 <p>

@@ -9024,6 +9379,13 @@
 
 
 <p>
+Native endianness assumes that the whole system is
+either big or little endian.
+The packing functions will not emulate correctly the behavior
+of mixed-endian formats.
+
+
+<p>
 Alignment works as follows:
 For each option,
 the format gets extra padding until the data starts

@@ -9036,7 +9398,7 @@
 
 <p>
 All padding is filled with zeros by <a href="#pdf-string.pack"><code>string.pack</code></a>
-(and ignored by <a href="#pdf-string.unpack"><code>string.unpack</code></a>).
+and ignored by <a href="#pdf-string.unpack"><code>string.unpack</code></a>.
 
 
 

@@ -9065,7 +9427,29 @@
 
 
 <p>
+Functions that create byte sequences
+accept all values up to <code>0x7FFFFFFF</code>,
+as defined in the original UTF-8 specification;
+that implies byte sequences of up to six bytes.
+
+
+<p>
+Functions that interpret byte sequences only accept
+valid sequences (well formed and not overlong).
+By default, they only accept byte sequences
+that result in valid Unicode code points,
+rejecting values greater than <code>10FFFF</code> and surrogates.
+A boolean argument <code>lax</code>, when available,
+lifts these checks,
+so that all values up to <code>0x7FFFFFFF</code> are accepted.
+(Not well formed and overlong sequences are still rejected.)
+
+
+<p>
 <hr><h3><a name="pdf-utf8.char"><code>utf8.char (&middot;&middot;&middot;)</code></a></h3>
+
+
+<p>
 Receives zero or more integers,
 converts each one to its corresponding UTF-8 byte sequence
 and returns a string with the concatenation of all these sequences.

@@ -9075,7 +9459,10 @@
 
 <p>
 <hr><h3><a name="pdf-utf8.charpattern"><code>utf8.charpattern</code></a></h3>
-The pattern (a string, not a function) "<code>[\0-\x7F\xC2-\xF4][\x80-\xBF]*</code>"
+
+
+<p>
+The pattern (a string, not a function) "<code>[\0-\x7F\xC2-\xFD][\x80-\xBF]*</code>"
 (see <a href="#6.4.1">&sect;6.4.1</a>),
 which matches exactly one UTF-8 byte sequence,
 assuming that the subject is a valid UTF-8 string.

@@ -9084,7 +9471,7 @@
 
 
 <p>
-<hr><h3><a name="pdf-utf8.codes"><code>utf8.codes (s)</code></a></h3>
+<hr><h3><a name="pdf-utf8.codes"><code>utf8.codes (s [, lax])</code></a></h3>
 
 
 <p>

@@ -9093,7 +9480,7 @@
 <pre>
      for p, c in utf8.codes(s) do <em>body</em> end
 </pre><p>
-will iterate over all characters in string <code>s</code>,
+will iterate over all UTF-8 characters in string <code>s</code>,
 with <code>p</code> being the position (in bytes) and <code>c</code> the code point
 of each character.
 It raises an error if it meets any invalid byte sequence.

@@ -9102,8 +9489,11 @@
 
 
 <p>
-<hr><h3><a name="pdf-utf8.codepoint"><code>utf8.codepoint (s [, i [, j]])</code></a></h3>
-Returns the codepoints (as integers) from all characters in <code>s</code>
+<hr><h3><a name="pdf-utf8.codepoint"><code>utf8.codepoint (s [, i [, j [, lax]]])</code></a></h3>
+
+
+<p>
+Returns the code points (as integers) from all characters in <code>s</code>
 that start between byte position <code>i</code> and <code>j</code> (both included).
 The default for <code>i</code> is 1 and for <code>j</code> is <code>i</code>.
 It raises an error if it meets any invalid byte sequence.

@@ -9112,7 +9502,10 @@
 
 
 <p>
-<hr><h3><a name="pdf-utf8.len"><code>utf8.len (s [, i [, j]])</code></a></h3>
+<hr><h3><a name="pdf-utf8.len"><code>utf8.len (s [, i [, j [, lax]]])</code></a></h3>
+
+
+<p>
 Returns the number of UTF-8 characters in string <code>s</code>
 that start between positions <code>i</code> and <code>j</code> (both inclusive).
 The default for <code>i</code> is 1 and for <code>j</code> is -1.

@@ -9124,6 +9517,9 @@
 
 <p>
 <hr><h3><a name="pdf-utf8.offset"><code>utf8.offset (s, n [, i])</code></a></h3>
+
+
+<p>
 Returns the position (in bytes) where the encoding of the
 <code>n</code>-th character of <code>s</code>
 (counting from position <code>i</code>) starts.

@@ -9191,7 +9587,7 @@
 <code>list[pos], list[pos+1], &middot;&middot;&middot;, list[#list]</code>.
 The default value for <code>pos</code> is <code>#list+1</code>,
 so that a call <code>table.insert(t,x)</code> inserts <code>x</code> at the end
-of list <code>t</code>.
+of the list <code>t</code>.
 
 
 

@@ -9201,7 +9597,7 @@
 
 
 <p>
-Moves elements from table <code>a1</code> to table <code>a2</code>,
+Moves elements from the table <code>a1</code> to the table <code>a2</code>,
 performing the equivalent to the following
 multiple assignment:
 <code>a2[t],&middot;&middot;&middot; = a1[f],&middot;&middot;&middot;,a1[e]</code>.

@@ -9247,7 +9643,7 @@
 <p>
 The default value for <code>pos</code> is <code>#list</code>,
 so that a call <code>table.remove(l)</code> removes the last element
-of list <code>l</code>.
+of the list <code>l</code>.
 
 
 

@@ -9257,7 +9653,7 @@
 
 
 <p>
-Sorts list elements in a given order, <em>in-place</em>,
+Sorts the list elements in a given order, <em>in-place</em>,
 from <code>list[1]</code> to <code>list[#list]</code>.
 If <code>comp</code> is given,
 then it must be a function that receives two list elements

@@ -9311,8 +9707,8 @@
 Functions with the annotation "<code>integer/float</code>" give
 integer results for integer arguments
 and float results for float (or mixed) arguments.
-Rounding functions
-(<a href="#pdf-math.ceil"><code>math.ceil</code></a>, <a href="#pdf-math.floor"><code>math.floor</code></a>, and <a href="#pdf-math.modf"><code>math.modf</code></a>)
+the rounding functions
+<a href="#pdf-math.ceil"><code>math.ceil</code></a>, <a href="#pdf-math.floor"><code>math.floor</code></a>, and <a href="#pdf-math.modf"><code>math.modf</code></a>
 return an integer when the result fits in the range of an integer,
 or a float otherwise.
 

@@ -9322,7 +9718,7 @@
 
 
 <p>
-Returns the absolute value of <code>x</code>. (integer/float)
+Returns the maximum value between <code>x</code> and <code>-x</code>. (integer/float)
 
 
 

@@ -9354,9 +9750,9 @@
 <p>
 
 Returns the arc tangent of <code>y/x</code> (in radians),
-but uses the signs of both parameters to find the
+but uses the signs of both arguments to find the
 quadrant of the result.
-(It also handles correctly the case of <code>x</code> being zero.)
+It also handles correctly the case of <code>x</code> being zero.
 
 
 <p>

@@ -9372,7 +9768,7 @@
 
 
 <p>
-Returns the smallest integral value larger than or equal to <code>x</code>.
+Returns the smallest integral value greater than or equal to <code>x</code>.
 
 
 

@@ -9413,7 +9809,7 @@
 
 
 <p>
-Returns the largest integral value smaller than or equal to <code>x</code>.
+Returns the largest integral value less than or equal to <code>x</code>.
 
 
 

@@ -9435,7 +9831,7 @@
 
 <p>
 The float value <code>HUGE_VAL</code>,
-a value larger than any other numeric value.
+a value greater than any other numeric value.
 
 
 

@@ -9458,7 +9854,7 @@
 
 <p>
 Returns the argument with the maximum value,
-according to the Lua operator <code>&lt;</code>. (integer/float)
+according to the Lua operator <code>&lt;</code>.
 
 
 

@@ -9476,7 +9872,7 @@
 
 <p>
 Returns the argument with the minimum value,
-according to the Lua operator <code>&lt;</code>. (integer/float)
+according to the Lua operator <code>&lt;</code>.
 
 
 

@@ -9537,20 +9933,16 @@
 
 
 <p>
-Lua initializes its pseudo-random generator with
-a weak attempt for ``randomness'',
+Lua initializes its pseudo-random generator with the equivalent of
+a call to <a href="#pdf-math.randomseed"><code>math.randomseed</code></a> with no arguments,
 so that <code>math.random</code> should generate
 different sequences of results each time the program runs.
-To ensure a required level of randomness to the initial state
-(or contrarily, to have a deterministic sequence,
-for instance when debugging a program),
-you should call <a href="#pdf-math.randomseed"><code>math.randomseed</code></a> explicitly.
 
 
 <p>
 The results from this function have good statistical qualities,
 but they are not cryptographically secure.
-(For instance, there are no garanties that it is hard
+(For instance, there are no guarantees that it is hard
 to predict future results based on the observation of
 some number of previous results.)
 

@@ -9558,16 +9950,28 @@
 
 
 <p>
-<hr><h3><a name="pdf-math.randomseed"><code>math.randomseed (x [, y])</code></a></h3>
+<hr><h3><a name="pdf-math.randomseed"><code>math.randomseed ([x [, y]])</code></a></h3>
 
 
 <p>
-Sets <code>x</code> and <code>y</code> as the "seed"
-for the pseudo-random generator:
+When called with at least one argument,
+the integer parameters <code>x</code> and <code>y</code> are
+joined into a 128-bit <em>seed</em> that
+is used to reinitialize the pseudo-random generator;
 equal seeds produce equal sequences of numbers.
 The default for <code>y</code> is zero.
 
 
+<p>
+When called with no arguments,
+Lua generates a seed with
+a weak attempt for randomness.
+To ensure a required level of randomness to the initial state
+(or contrarily, to have a deterministic sequence,
+for instance when debugging a program),
+you should call <a href="#pdf-math.randomseed"><code>math.randomseed</code></a> with explicit arguments.
+
+
 
 
 <p>

@@ -9647,7 +10051,7 @@
 The first one uses implicit file handles;
 that is, there are operations to set a default input file and a
 default output file,
-and all input/output operations are over these default files.
+and all input/output operations are done over these default files.
 The second style uses explicit file handles.
 
 

@@ -9660,6 +10064,12 @@
 
 
 <p>
+The metatable for file handles provides metamethods
+for <code>__gc</code> and <code>__close</code> that try
+to close the file when called.
+
+
+<p>
 The table <code>io</code> also provides
 three predefined file handles with their usual meanings from C:
 <a name="pdf-io.stdin"><code>io.stdin</code></a>, <a name="pdf-io.stdout"><code>io.stdout</code></a>, and <a name="pdf-io.stderr"><code>io.stderr</code></a>.

@@ -9668,9 +10078,9 @@
 
 <p>
 Unless otherwise stated,
-all I/O functions return <b>nil</b> on failure
-(plus an error message as a second result and
-a system-dependent error code as a third result)
+all I/O functions return <b>nil</b> on failure,
+plus an error message as a second result and
+a system-dependent error code as a third result,
 and some value different from <b>nil</b> on success.
 On non-POSIX systems,
 the computation of the error message and error code

@@ -9709,7 +10119,7 @@
 and sets its handle as the default input file.
 When called with a file handle,
 it simply sets this file handle as the default input file.
-When called without parameters,
+When called without arguments,
 it returns the current default input file.
 
 

@@ -9730,6 +10140,13 @@
 works like <code>file:lines(&middot;&middot;&middot;)</code> over the opened file.
 When the iterator function detects the end of file,
 it returns no values (to finish the loop) and automatically closes the file.
+Besides the iterator function,
+<code>io.lines</code> returns three other values:
+two <b>nil</b> values as placeholders,
+plus the created file handle.
+Therefore, when used in a generic <b>for</b> loop,
+the file is closed also if the loop is interrupted by an
+error or a <b>break</b>.
 
 
 <p>

@@ -9795,7 +10212,7 @@
 
 
 <p>
-Starts program <code>prog</code> in a separated process and returns
+Starts the program <code>prog</code> in a separated process and returns
 a file handle that you can use to read data from this program
 (if <code>mode</code> is <code>"r"</code>, the default)
 or to write data to this program

@@ -9919,7 +10336,7 @@
 or <b>nil</b> if it cannot read data with the specified format.
 (In this latter case,
 the function does not read subsequent formats.)
-When called without parameters,
+When called without arguments,
 it uses a default format that reads the next line
 (see below).
 

@@ -9936,7 +10353,8 @@
 This format always reads the longest input sequence that
 is a valid prefix for a numeral;
 if that prefix does not form a valid numeral
-(e.g., an empty string, "<code>0x</code>", or "<code>3.4e-</code>"),
+(e.g., an empty string, "<code>0x</code>", or "<code>3.4e-</code>")
+or it is too long (more than 200 characters),
 it is discarded and the format returns <b>nil</b>.
 </li>
 

@@ -10031,8 +10449,8 @@
 </li>
 
 </ul><p>
-For the last two cases, <code>size</code>
-specifies the size of the buffer, in bytes.
+For the last two cases,
+<code>size</code> is a hint for the size of the buffer, in bytes.
 The default is an appropriate size.
 
 

@@ -10113,10 +10531,9 @@
 
 
 <p>
-When called without arguments,
-<code>date</code> returns a reasonable date and time representation that depends on
-the host system and on the current locale.
-(More specifically, <code>os.date()</code> is equivalent to <code>os.date("%c")</code>.)
+If <code>format</code> is absent, it defaults to "<code>%c</code>",
+which gives a reasonable date and time representation
+using the current locale.
 
 
 <p>

@@ -10402,8 +10819,8 @@
 <p>
 Returns the current hook settings of the thread, as three values:
 the current hook function, the current hook mask,
-and the current hook count
-(as set by the <a href="#pdf-debug.sethook"><code>debug.sethook</code></a> function).
+and the current hook count,
+as set by the <a href="#pdf-debug.sethook"><code>debug.sethook</code></a> function.
 
 
 

@@ -10422,7 +10839,7 @@
 level&nbsp;1 is the function that called <code>getinfo</code>
 (except for tail calls, which do not count on the stack);
 and so on.
-If <code>f</code> is a number larger than the number of active functions,
+If <code>f</code> is a number greater than the number of active functions,
 then <code>getinfo</code> returns <b>nil</b>.
 
 

@@ -10459,7 +10876,7 @@
 This function returns the name and the value of the local variable
 with index <code>local</code> of the function at level <code>f</code> of the stack.
 This function accesses not only explicit local variables,
-but also parameters, temporaries, etc.
+but also parameters and temporary values.
 
 
 <p>

@@ -10467,8 +10884,8 @@
 following the order that they are declared in the code,
 counting only the variables that are active
 in the current scope of the function.
-Negative indices refer to vararg parameters;
--1 is the first vararg parameter.
+Negative indices refer to vararg arguments;
+-1 is the first vararg argument.
 The function returns <b>nil</b> if there is no variable with the given index,
 and raises an error when called with a level out of range.
 (You can call <a href="#pdf-debug.getinfo"><code>debug.getinfo</code></a> to check whether the level is valid.)

@@ -10544,7 +10961,7 @@
 
 
 <p>
-Sets the given function as a hook.
+Sets the given function as the debug hook.
 The string <code>mask</code> and the number <code>count</code> describe
 when the hook will be called.
 The string mask may have any combination of the following characters,

@@ -10568,16 +10985,15 @@
 <p>
 When the hook is called, its first parameter is a string
 describing the event that has triggered its call:
-<code>"call"</code> (or <code>"tail call"</code>),
-<code>"return"</code>,
+<code>"call"</code>, <code>"tail call"</code>, <code>"return"</code>,
 <code>"line"</code>, and <code>"count"</code>.
 For line events,
 the hook also gets the new line number as its second parameter.
 Inside a hook,
 you can call <code>getinfo</code> with level&nbsp;2 to get more information about
-the running function
-(level&nbsp;0 is the <code>getinfo</code> function,
-and level&nbsp;1 is the hook function).
+the running function.
+(Level&nbsp;0 is the <code>getinfo</code> function,
+and level&nbsp;1 is the hook function.)
 
 
 

@@ -10708,7 +11124,7 @@
 called simply <code>lua</code>,
 is provided with the standard distribution.
 The standalone interpreter includes
-all standard libraries, including the debug library.
+all standard libraries.
 Its usage is:
 
 <pre>

@@ -10734,7 +11150,7 @@
 
 
 <p>
-When called without option <code>-E</code>,
+When called without the option <code>-E</code>,
 the interpreter checks for an environment variable <a name="pdf-LUA_INIT_5_4"><code>LUA_INIT_5_4</code></a>
 (or <a name="pdf-LUA_INIT"><code>LUA_INIT</code></a> if the versioned name is not defined)
 before running any argument.

@@ -10744,7 +11160,7 @@
 
 
 <p>
-When called with option <code>-E</code>,
+When called with the option <code>-E</code>,
 besides ignoring <code>LUA_INIT</code>,
 Lua also ignores
 the values of <code>LUA_PATH</code> and <code>LUA_CPATH</code>,

@@ -10797,10 +11213,10 @@
 </pre><p>
 will print "<code>-e</code>".
 If there is a script,
-the script is called with parameters
+the script is called with arguments
 <code>arg[1]</code>, &middot;&middot;&middot;, <code>arg[#arg]</code>.
-(Like all chunks in Lua,
-the script is compiled as a vararg function.)
+Like all chunks in Lua,
+the script is compiled as a vararg function.
 
 
 <p>

@@ -10831,6 +11247,7 @@
 the interpreter calls this metamethod to produce the final message.
 Otherwise, the interpreter converts the error object to a string
 and adds a stack traceback to it.
+Warnings are simply printed in the standard error output.
 
 
 <p>

@@ -10844,8 +11261,7 @@
 <p>
 To allow the use of Lua as a
 script interpreter in Unix systems,
-the standalone interpreter skips
-the first line of a chunk if it starts with <code>#</code>.
+Lua skips the first line of a file chunk if it starts with <code>#</code>.
 Therefore, Lua scripts can be made into executable programs
 by using <code>chmod +x</code> and the&nbsp;<code>#!</code> form,
 as in

@@ -10853,7 +11269,7 @@
 <pre>
      #!/usr/local/bin/lua
 </pre><p>
-(Of course,
+Of course,
 the location of the Lua interpreter may be different in your machine.
 If <code>lua</code> is in your <code>PATH</code>,
 then

@@ -10861,7 +11277,7 @@
 <pre>
      #!/usr/bin/env lua
 </pre><p>
-is a more portable solution.)
+is a more portable solution.
 
 
 

@@ -10870,10 +11286,20 @@
 <p>
 Here we list the incompatibilities that you may find when moving a program
 from Lua&nbsp;5.3 to Lua&nbsp;5.4.
+
+
+<p>
 You can avoid some incompatibilities by compiling Lua with
 appropriate options (see file <code>luaconf.h</code>).
 However,
 all these compatibility options will be removed in the future.
+More often than not,
+compatibility issues arise when these compatibility options
+are removed.
+So, whenever you have the chance,
+you should try to test your code with a version of Lua compiled
+with all compatibility options turned off.
+That will ease transitions to newer versions of Lua.
 
 
 <p>

@@ -10882,7 +11308,7 @@
 such as the numeric values for constants
 or the implementation of functions as macros.
 Therefore,
-you should not assume that binaries are compatible between
+you should never assume that binaries are compatible between
 different Lua versions.
 Always recompile clients of the Lua API when
 using a new version.

@@ -10900,7 +11326,7 @@
 
 
 
-<h2>8.1 &ndash; <a name="8.1">Changes in the Language</a></h2>
+<h2>8.1 &ndash; <a name="8.1">Incompatibilities in the Language</a></h2>
 <ul>
 
 <li>

@@ -10917,26 +11343,65 @@
 not a float.
 </li>
 
+<li>
+The use of the <code>__lt</code> metamethod to emulate <code>__le</code>
+has been removed.
+When needed, this metamethod must be explicitly defined.
+</li>
+
+<li>
+The semantics of the numerical <b>for</b> loop
+over integers changed in some details.
+In particular, the control variable never wraps around.
+</li>
+
+<li>
+A label for a <b>goto</b> cannot be declared where a label with the same
+name is visible, even if this other label is declared in an enclosing
+block.
+</li>
+
+<li>
+When finalizing an object,
+Lua does not ignore <code>__gc</code> metamethods that are not functions.
+Any value will be called, if present.
+(Non-callable values will generate a warning,
+like any other error when calling a finalizer.)
+</li>
+
 </ul>
 
 
 
 
-<h2>8.2 &ndash; <a name="8.2">Changes in the Libraries</a></h2>
+<h2>8.2 &ndash; <a name="8.2">Incompatibilities in the Libraries</a></h2>
 <ul>
 
 <li>
+The function <a href="#pdf-print"><code>print</code></a> does not call <a href="#pdf-tostring"><code>tostring</code></a>
+to format its arguments;
+instead, it has this functionality hardwired.
+You should use <code>__tostring</code> to modify how values are printed.
+</li>
+
+<li>
 The pseudo-random number generator used by the function <a href="#pdf-math.random"><code>math.random</code></a>
 now starts with a somewhat random seed.
 Moreover, it uses a different algorithm.
 </li>
 
+<li>
+By default, the decoding functions in the <a href="#pdf-utf8"><code>utf8</code></a> library
+do not accept surrogates as valid code points.
+An extra parameter in these functions makes them more permissive.
+</li>
+
 </ul>
 
 
 
 
-<h2>8.3 &ndash; <a name="8.3">Changes in the API</a></h2>
+<h2>8.3 &ndash; <a name="8.3">Incompatibilities in the API</a></h2>
 
 
 <ul>

@@ -10951,25 +11416,33 @@
 
 
 <p>
-(For compatibility, the old names still work as macros assuming
-one single user value.)
+For compatibility, the old names still work as macros assuming
+one single user value.
+Note, however, that userdata with zero user values
+are more efficient memory-wise.
 </li>
 
 <li>
 The function <a href="#lua_resume"><code>lua_resume</code></a> has an extra parameter.
 This out parameter returns the number of values on
 the top of the stack that were yielded or returned by the coroutine.
-(In older versions,
+(In previous versions,
 those values were the entire stack.)
 </li>
 
 <li>
 The function <a href="#lua_version"><code>lua_version</code></a> returns the version number,
 instead of an address of the version number.
-(The Lua core should work correctly with libraries using their
+The Lua core should work correctly with libraries using their
 own static copies of the same core,
 so there is no need to check whether they are using the same
-address space.)
+address space.
+</li>
+
+<li>
+The constant <code>LUA_ERRGCMM</code> was removed.
+Errors in finalizers are never propagated;
+instead, they generate a warning.
 </li>
 
 </ul>

@@ -11012,7 +11485,8 @@
 		 <b>for</b> namelist <b>in</b> explist <b>do</b> block <b>end</b> | 
 		 <b>function</b> funcname funcbody | 
 		 <b>local</b> <b>function</b> Name funcbody | 
-		 <b>local</b> namelist [&lsquo;<b>=</b>&rsquo; explist] 
+		 <b>local</b> namelist [&lsquo;<b>=</b>&rsquo; explist] | 
+		 <b>local</b> &lsquo;<b>&lt;</b>&rsquo; Name &lsquo;<b>&gt;</b>&rsquo; Name &lsquo;<b>=</b>&rsquo; exp 
 
 	retstat ::= <b>return</b> [explist] [&lsquo;<b>;</b>&rsquo;]
 

@@ -11070,10 +11544,10 @@
 
 <P CLASS="footer">
 Last update:
-Mon Jun 18 17:05:33 -03 2018
+Wed May 29 08:06:33 -03 2019
 </P>
 <!--
-Last change: revised for Lua 5.4.0 (work2)
+Last change: revised for Lua 5.4.0 (alpha)
 -->
 
 </body></html>

doc/readme.html

@@ -110,7 +110,7 @@
 <OL>
 <LI>
 Open a terminal window and move to
-the top-level directory, which is named <TT>lua-5.4.0-work2</TT>.
+the top-level directory, which is named <TT>lua-5.4.0-alpha</TT>.
 The <TT>Makefile</TT> there controls both the build process and the installation process.
 <P>
 <LI>

@@ -118,9 +118,13 @@
   The platforms currently supported are:
 <P>
 <P CLASS="display">
-   aix bsd c89 freebsd generic linux macosx mingw posix solaris
+   aix bsd c89 freebsd generic guess linux linux-readline macosx mingw posix solaris
 </P>
 <P>
+  If your platform is a common Unix-like platform,
+  just do "<KBD>make guess</KBD>".
+  The <TT>Makefile</TT> will guess your platform and build Lua for it.
+<P>
   If your platform is listed, just do "<KBD>make xxx</KBD>", where xxx
   is your platform name.
 <P>

@@ -139,7 +143,7 @@
   after building Lua. This will run the interpreter and print its version.
 </OL>
 <P>
-If you're running Linux and get compilation errors,
+If you're running Linux and get compilation errors when building for <TT>linux-readline</TT>,
 make sure you have installed the <TT>readline</TT> development package
 (which is probably named <TT>libreadline-dev</TT> or <TT>readline-devel</TT>).
 If you get link errors after that,

@@ -150,11 +154,11 @@
   Once you have built Lua, you may want to install it in an official
   place in your system. In this case, do "<KBD>make install</KBD>". The official
   place and the way to install files are defined in the <TT>Makefile</TT>. You'll
-  probably need the right permissions to install files, and so make need to do "<KBD>sudo make install</KBD>".
+  probably need the right permissions to install files, and so may need to do "<KBD>sudo make install</KBD>".
 
 <P>
   To build and install Lua in one step, do "<KBD>make xxx install</KBD>",
-  where xxx is your platform name.
+  where xxx is your platform name, including "guess".
 
 <P>
   To install Lua locally, do "<KBD>make local</KBD>".

@@ -265,10 +269,19 @@
 <H3>Main changes</H3>
 <UL>
 <LI> new generational mode for garbage collection
+<LI> to-be-closed variables
+<LI> const variables
 <LI> userdata can have multiple user values
+<LI> new implementation for math.random
+<LI> warning system
 <LI> debug information about function arguments and returns
-<LI> new implementation for <CODE>math.random</CODE>
-
+<LI> new semantics for the integer 'for' loop
+<LI> optional 'init' argument to 'string.gmatch'
+<LI> new functions 'lua_resetthread' and 'coroutine.kill'
+<LI> coersions string->number moved to the string library
+<LI> allocation function allowed to fail when shrinking a memory block
+<LI> new format '%p' in 'string.format'
+<LI> utf8 library accepts codepoints up to 2^31
 </UL>
 
 <H2><A NAME="license">License</A></H2>

@@ -289,7 +302,7 @@
 <A HREF="http://www.lua.org/license.html">this</A>.
 
 <BLOCKQUOTE STYLE="padding-bottom: 0em">
-Copyright &copy; 1994&ndash;2018 Lua.org, PUC-Rio.
+Copyright &copy; 1994&ndash;2019 Lua.org, PUC-Rio.
 
 <P>
 Permission is hereby granted, free of charge, to any person obtaining a copy

@@ -316,10 +329,10 @@
 
 <P CLASS="footer">
 Last update:
-Mon Jun 18 17:08:42 -03 2018
+Wed May 29 16:02:01 BRT 2019
 </P>
 <!--
-Last change: revised for Lua 5.4.0 (work2)
+Last change: revised for Lua 5.4.0 (alpha)
 -->
 
 </BODY>

src/Makefile

@@ -26,7 +26,7 @@
 
 # == END OF USER SETTINGS -- NO NEED TO CHANGE ANYTHING BELOW THIS LINE =======
 
-PLATS= aix bsd c89 freebsd generic linux linux-readline macosx mingw posix solaris
+PLATS= aix bsd c89 freebsd generic guess linux linux-readline macosx mingw posix solaris
 
 LUA_A=	liblua.a
 CORE_O=	lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o lundump.o lvm.o lzio.o

@@ -85,7 +85,11 @@
 	@echo "Please do 'make PLATFORM' where PLATFORM is one of these:"
 	@echo "   $(PLATS)"
 
-aix:
+guess:
+	@echo Guessing `uname`
+	@$(MAKE) `uname`
+
+AIX aix:
 	$(MAKE) $(ALL) CC="xlc" CFLAGS="-O2 -DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-ldl" SYSLDFLAGS="-brtl -bexpall"
 
 bsd:

@@ -97,12 +101,12 @@
 	@echo '*** C89 does not guarantee 64-bit integers for Lua.'
 	@echo ''
 
-freebsd:
+FreeBSD NetBSD OpenBSD freebsd:
 	$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX -DLUA_USE_READLINE -I/usr/include/edit" SYSLIBS="-Wl,-E -ledit" CC="cc"
 
 generic: $(ALL)
 
-linux:	linux-noreadline
+Linux linux:	linux-noreadline
 
 linux-noreadline:
 	$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -ldl"

@@ -110,7 +114,7 @@
 linux-readline:
 	$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX -DLUA_USE_READLINE" SYSLIBS="-Wl,-E -ldl -lreadline"
 
-macosx:
+Darwin macos macosx:
 	$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_MACOSX -DLUA_USE_READLINE" SYSLIBS="-lreadline"
 
 mingw:

@@ -122,7 +126,7 @@
 posix:
 	$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX"
 
-solaris:
+SunOS solaris:
 	$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN -D_REENTRANT" SYSLIBS="-ldl"
 
 # list targets that do not create files (but not all makes understand .PHONY)

@@ -149,8 +153,8 @@
  lparser.h lstring.h ltable.h lundump.h lvm.h
 ldump.o: ldump.c lprefix.h lua.h luaconf.h lobject.h llimits.h lstate.h \
  ltm.h lzio.h lmem.h lundump.h
-lfunc.o: lfunc.c lprefix.h lua.h luaconf.h lfunc.h lobject.h llimits.h \
- lgc.h lstate.h ltm.h lzio.h lmem.h
+lfunc.o: lfunc.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
+ llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h
 lgc.o: lgc.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
  llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h
 linit.o: linit.c lprefix.h lua.h luaconf.h lualib.h lauxlib.h

@@ -182,8 +186,8 @@
 ltm.o: ltm.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
  llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h lstring.h ltable.h lvm.h
 lua.o: lua.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
-luac.o: luac.c lprefix.h lua.h luaconf.h lauxlib.h lobject.h llimits.h \
- lstate.h ltm.h lzio.h lmem.h lundump.h ldebug.h lopcodes.h
+luac.o: luac.c lprefix.h lua.h luaconf.h lauxlib.h ldebug.h lstate.h \
+ lobject.h llimits.h ltm.h lzio.h lmem.h lopcodes.h lopnames.h lundump.h
 lundump.o: lundump.c lprefix.h lua.h luaconf.h ldebug.h lstate.h \
  lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.h \
  lundump.h

src/lapi.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lapi.c,v 2.295 2018/06/18 12:08:10 roberto Exp $
+** $Id: lapi.c $
 ** Lua API
 ** See Copyright Notice in lua.h
 */

@@ -38,7 +38,11 @@
 
 
 
-/* test for a valid index */
+/*
+** Test for a valid index.
+** '!ttisnil(o)' implies 'o != &G(L)->nilvalue', so it is not needed.
+** However, it covers the most common cases in a faster way.
+*/
 #define isvalid(L, o)	(!ttisnil(o) || o != &G(L)->nilvalue)
 
 

@@ -169,15 +173,17 @@
   StkId func = L->ci->func;
   lua_lock(L);
   if (idx >= 0) {
+    StkId newtop = (func + 1) + idx;
     api_check(L, idx <= L->stack_last - (func + 1), "new top too large");
-    while (L->top < (func + 1) + idx)
+    while (L->top < newtop)
       setnilvalue(s2v(L->top++));
-    L->top = (func + 1) + idx;
+    L->top = newtop;
   }
   else {
     api_check(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top");
     L->top += idx+1;  /* 'subtract' index (index is negative) */
   }
+  luaF_close(L, L->top, LUA_OK);
   lua_unlock(L);
 }
 

@@ -408,8 +414,7 @@
 }
 
 
-LUA_API void *lua_touserdata (lua_State *L, int idx) {
-  const TValue *o = index2value(L, idx);
+static void *touserdata (const TValue *o) {
   switch (ttype(o)) {
     case LUA_TUSERDATA: return getudatamem(uvalue(o));
     case LUA_TLIGHTUSERDATA: return pvalue(o);

@@ -418,23 +423,37 @@
 }
 
 
+LUA_API void *lua_touserdata (lua_State *L, int idx) {
+  const TValue *o = index2value(L, idx);
+  return touserdata(o);
+}
+
+
 LUA_API lua_State *lua_tothread (lua_State *L, int idx) {
   const TValue *o = index2value(L, idx);
   return (!ttisthread(o)) ? NULL : thvalue(o);
 }
 
 
+/*
+** Returns a pointer to the internal representation of an object.
+** Note that ANSI C does not allow the conversion of a pointer to
+** function to a 'void*', so the conversion here goes through
+** a 'size_t'. (As the returned pointer is only informative, this
+** conversion should not be a problem.)
+*/
 LUA_API const void *lua_topointer (lua_State *L, int idx) {
   const TValue *o = index2value(L, idx);
   switch (ttypetag(o)) {
-    case LUA_TTABLE: return hvalue(o);
-    case LUA_TLCL: return clLvalue(o);
-    case LUA_TCCL: return clCvalue(o);
     case LUA_TLCF: return cast_voidp(cast_sizet(fvalue(o)));
-    case LUA_TTHREAD: return thvalue(o);
-    case LUA_TUSERDATA: return getudatamem(uvalue(o));
-    case LUA_TLIGHTUSERDATA: return pvalue(o);
-    default: return NULL;
+    case LUA_TUSERDATA: case LUA_TLIGHTUSERDATA:
+      return touserdata(o);
+    default: {
+      if (iscollectable(o))
+        return gcvalue(o);
+      else
+        return NULL;
+    }
   }
 }
 

@@ -917,8 +936,8 @@
   api_checknelems(L, 1);
   o = index2value(L, idx);
   api_check(L, ttisfulluserdata(o), "full userdata expected");
-  if (!(0 < n && n <= uvalue(o)->nuvalue))
-    res = 0;
+  if (!(cast_uint(n) - 1u < cast_uint(uvalue(o)->nuvalue)))
+    res = 0;  /* 'n' not in [1, uvalue(o)->nuvalue] */
   else {
     setobj(L, &uvalue(o)->uv[n - 1].uv, s2v(L->top - 1));
     luaC_barrierback(L, gcvalue(o), s2v(L->top - 1));

@@ -950,7 +969,7 @@
   api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread");
   checkresults(L, nargs, nresults);
   func = L->top - (nargs+1);
-  if (k != NULL && L->nny == 0) {  /* need to prepare continuation? */
+  if (k != NULL && yieldable(L)) {  /* need to prepare continuation? */
     L->ci->u.c.k = k;  /* save continuation */
     L->ci->u.c.ctx = ctx;  /* save context */
     luaD_call(L, func, nresults);  /* do the call */

@@ -998,7 +1017,7 @@
     func = savestack(L, o);
   }
   c.func = L->top - (nargs+1);  /* function to be called */
-  if (k == NULL || L->nny > 0) {  /* no continuation or no yieldable? */
+  if (k == NULL || !yieldable(L)) {  /* no continuation or no yieldable? */
     c.nresults = nresults;  /* do a 'conventional' protected call */
     status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func);
   }

@@ -1135,22 +1154,21 @@
       break;
     }
     case LUA_GCGEN: {
-      int oldmode = g->gckind;
       int minormul = va_arg(argp, int);
       int majormul = va_arg(argp, int);
+      res = isdecGCmodegen(g) ? LUA_GCGEN : LUA_GCINC;
       if (minormul != 0)
         g->genminormul = minormul;
       if (majormul != 0)
         setgcparam(g->genmajormul, majormul);
       luaC_changemode(L, KGC_GEN);
-      res = (oldmode == KGC_GEN) ? LUA_GCGEN : LUA_GCINC;
       break;
     }
     case LUA_GCINC: {
-      int oldmode = g->gckind;
       int pause = va_arg(argp, int);
       int stepmul = va_arg(argp, int);
       int stepsize = va_arg(argp, int);
+      res = isdecGCmodegen(g) ? LUA_GCGEN : LUA_GCINC;
       if (pause != 0)
         setgcparam(g->gcpause, pause);
       if (stepmul != 0)

@@ -1158,7 +1176,6 @@
       if (stepsize != 0)
         g->gcstepsize = stepsize;
       luaC_changemode(L, KGC_INC);
-      res = (oldmode == KGC_GEN) ? LUA_GCGEN : LUA_GCINC;
       break;
     }
     default: res = -1;  /* invalid option */

@@ -1201,6 +1218,22 @@
 }
 
 
+LUA_API void lua_toclose (lua_State *L, int idx) {
+  int nresults;
+  StkId o;
+  lua_lock(L);
+  o = index2stack(L, idx);
+  nresults = L->ci->nresults;
+  api_check(L, L->openupval == NULL || uplevel(L->openupval) <= o,
+               "marked index below or equal new one");
+  luaF_newtbcupval(L, o);  /* create new to-be-closed upvalue */
+  if (!hastocloseCfunc(nresults))  /* function not marked yet? */
+    L->ci->nresults = codeNresults(nresults);  /* mark it */
+  lua_assert(hastocloseCfunc(L->ci->nresults));
+  lua_unlock(L);
+}
+
+
 LUA_API void lua_concat (lua_State *L, int n) {
   lua_lock(L);
   api_checknelems(L, n);

@@ -1245,6 +1278,22 @@
 }
 
 
+void lua_setwarnf (lua_State *L, lua_WarnFunction f, void *ud) {
+  lua_lock(L);
+  G(L)->ud_warn = ud;
+  G(L)->warnf = f;
+  lua_unlock(L);
+}
+
+
+void lua_warning (lua_State *L, const char *msg, int tocont) {
+  lua_lock(L);
+  luaE_warning(L, msg, tocont);
+  lua_unlock(L);
+}
+
+
+
 LUA_API void *lua_newuserdatauv (lua_State *L, size_t size, int nuvalue) {
   Udata *u;
   lua_lock(L);

@@ -1264,7 +1313,8 @@
   switch (ttypetag(fi)) {
     case LUA_TCCL: {  /* C closure */
       CClosure *f = clCvalue(fi);
-      if (!(1 <= n && n <= f->nupvalues)) return NULL;
+      if (!(cast_uint(n) - 1u < cast_uint(f->nupvalues)))
+        return NULL;  /* 'n' not in [1, f->nupvalues] */
       *val = &f->upvalue[n-1];
       if (owner) *owner = obj2gco(f);
       return "";

@@ -1273,11 +1323,12 @@
       LClosure *f = clLvalue(fi);
       TString *name;
       Proto *p = f->p;
-      if (!(1 <= n && n <= p->sizeupvalues)) return NULL;
+      if (!(cast_uint(n) - 1u  < cast_uint(p->sizeupvalues)))
+        return NULL;  /* 'n' not in [1, p->sizeupvalues] */
       *val = f->upvals[n-1]->v;
       if (owner) *owner = obj2gco(f->upvals[n - 1]);
       name = p->upvalues[n-1].name;
-      return (name == NULL) ? "(*no name)" : getstr(name);
+      return (name == NULL) ? "(no name)" : getstr(name);
     }
     default: return NULL;  /* not a closure */
   }

src/lapi.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lapi.h,v 2.12 2017/11/07 13:25:26 roberto Exp $
+** $Id: lapi.h $
 ** Auxiliary functions from Lua API
 ** See Copyright Notice in lua.h
 */

@@ -15,10 +15,23 @@
 				"stack overflow");}
 
 #define adjustresults(L,nres) \
-    { if ((nres) == LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; }
+    { if ((nres) <= LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; }
 
 #define api_checknelems(L,n)	api_check(L, (n) < (L->top - L->ci->func), \
 				  "not enough elements in the stack")
 
 
+/*
+** To reduce the overhead of returning from C functions, the presence of
+** to-be-closed variables in these functions is coded in the CallInfo's
+** field 'nresults', in a way that functions with no to-be-closed variables
+** with zero, one, or "all" wanted results have no overhead. Functions
+** with other number of wanted results, as well as functions with
+** variables to be closed, have an extra check.
+*/
+
+#define hastocloseCfunc(n)	((n) < LUA_MULTRET)
+
+#define codeNresults(n)		(-(n) - 3)
+
 #endif

src/lauxlib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lauxlib.c,v 1.295 2018/06/18 12:08:10 roberto Exp $
+** $Id: lauxlib.c $
 ** Auxiliary functions for building Lua libraries
 ** See Copyright Notice in lua.h
 */

@@ -27,6 +27,12 @@
 #include "lauxlib.h"
 
 
+#if !defined(MAX_SIZET)
+/* maximum value for size_t */
+#define MAX_SIZET	((size_t)(~(size_t)0))
+#endif
+
+
 /*
 ** {======================================================
 ** Traceback

@@ -40,8 +46,8 @@
 
 
 /*
-** search for 'objidx' in table at index -1.
-** return 1 + string at top if find a good name.
+** Search for 'objidx' in table at index -1. ('objidx' must be an
+** absolute index.) Return 1 + string at top if it found a good name.
 */
 static int findfield (lua_State *L, int objidx, int level) {
   if (level == 0 || !lua_istable(L, -1))

@@ -54,10 +60,10 @@
         return 1;
       }
       else if (findfield(L, objidx, level - 1)) {  /* try recursively */
-        lua_remove(L, -2);  /* remove table (but keep name) */
-        lua_pushliteral(L, ".");
-        lua_insert(L, -2);  /* place '.' between the two names */
-        lua_concat(L, 3);
+        /* stack: lib_name, lib_table, field_name (top) */
+        lua_pushliteral(L, ".");  /* place '.' between the two names */
+        lua_replace(L, -3);  /* (in the slot ocupied by table) */
+        lua_concat(L, 3);  /* lib_name.field_name */
         return 1;
       }
     }

@@ -80,8 +86,8 @@
       lua_pushstring(L, name + 3);  /* push name without prefix */
       lua_remove(L, -2);  /* remove original name */
     }
-    lua_copy(L, -1, top + 1);  /* move name to proper place */
-    lua_pop(L, 2);  /* remove pushed values */
+    lua_copy(L, -1, top + 1);  /* copy name to proper place */
+    lua_settop(L, top + 1);  /* remove table "loaded" an name copy */
     return 1;
   }
   else {

@@ -124,32 +130,37 @@
 
 LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1,
                                 const char *msg, int level) {
+  luaL_Buffer b;
   lua_Debug ar;
-  int top = lua_gettop(L);
   int last = lastlevel(L1);
-  int n1 = (last - level > LEVELS1 + LEVELS2) ? LEVELS1 : -1;
-  if (msg)
-    lua_pushfstring(L, "%s\n", msg);
-  luaL_checkstack(L, 10, NULL);
-  lua_pushliteral(L, "stack traceback:");
+  int limit2show = (last - level > LEVELS1 + LEVELS2) ? LEVELS1 : -1;
+  luaL_buffinit(L, &b);
+  if (msg) {
+    luaL_addstring(&b, msg);
+    luaL_addchar(&b, '\n');
+  }
+  luaL_addstring(&b, "stack traceback:");
   while (lua_getstack(L1, level++, &ar)) {
-    if (n1-- == 0) {  /* too many levels? */
-      lua_pushliteral(L, "\n\t...");  /* add a '...' */
-      level = last - LEVELS2 + 1;  /* and skip to last ones */
+    if (limit2show-- == 0) {  /* too many levels? */
+      int n = last - level - LEVELS2 + 1;  /* number of levels to skip */
+      lua_pushfstring(L, "\n\t...\t(skipping %d levels)", n);
+      luaL_addvalue(&b);  /* add warning about skip */
+      level += n;  /* and skip to last levels */
     }
     else {
       lua_getinfo(L1, "Slnt", &ar);
-      lua_pushfstring(L, "\n\t%s:", ar.short_src);
-      if (ar.currentline > 0)
-        lua_pushfstring(L, "%d:", ar.currentline);
-      lua_pushliteral(L, " in ");
+      if (ar.currentline <= 0)
+        lua_pushfstring(L, "\n\t%s: in ", ar.short_src);
+      else
+        lua_pushfstring(L, "\n\t%s:%d: in ", ar.short_src, ar.currentline);
+      luaL_addvalue(&b);
       pushfuncname(L, &ar);
+      luaL_addvalue(&b);
       if (ar.istailcall)
-        lua_pushliteral(L, "\n\t(...tail calls...)");
-      lua_concat(L, lua_gettop(L) - top);
+        luaL_addstring(&b, "\n\t(...tail calls...)");
     }
   }
-  lua_concat(L, lua_gettop(L) - top);
+  luaL_pushresult(&b);
 }
 
 /* }====================================================== */

@@ -179,7 +190,7 @@
 }
 
 
-static int typeerror (lua_State *L, int arg, const char *tname) {
+int luaL_typeerror (lua_State *L, int arg, const char *tname) {
   const char *msg;
   const char *typearg;  /* name for the type of the actual argument */
   if (luaL_getmetafield(L, arg, "__name") == LUA_TSTRING)

@@ -194,7 +205,7 @@
 
 
 static void tag_error (lua_State *L, int arg, int tag) {
-  typeerror(L, arg, lua_typename(L, tag));
+  luaL_typeerror(L, arg, lua_typename(L, tag));
 }
 
 

@@ -290,6 +301,7 @@
 /* }====================================================== */
 
 
+
 /*
 ** {======================================================
 ** Userdata's metatable manipulation

@@ -332,7 +344,7 @@
 
 LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) {
   void *p = luaL_testudata(L, ud, tname);
-  if (p == NULL) typeerror(L, ud, tname);
+  luaL_argexpected(L, p != NULL, ud, tname);
   return p;
 }
 

@@ -463,10 +475,8 @@
   lua_Alloc allocf = lua_getallocf(L, &ud);
   UBox *box = (UBox *)lua_touserdata(L, idx);
   void *temp = allocf(ud, box->box, box->bsize, newsize);
-  if (temp == NULL && newsize > 0) {  /* allocation error? */
-    resizebox(L, idx, 0);  /* free buffer */
+  if (temp == NULL && newsize > 0)  /* allocation error? */
     luaL_error(L, "not enough memory for buffer allocation");
-  }
   box->box = temp;
   box->bsize = newsize;
   return temp;

@@ -479,16 +489,20 @@
 }
 
 
-static void *newbox (lua_State *L, size_t newsize) {
+static const luaL_Reg boxmt[] = {  /* box metamethods */
+  {"__gc", boxgc},
+  {"__close", boxgc},
+  {NULL, NULL}
+};
+
+
+static void newbox (lua_State *L) {
   UBox *box = (UBox *)lua_newuserdatauv(L, sizeof(UBox), 0);
   box->box = NULL;
   box->bsize = 0;
-  if (luaL_newmetatable(L, "_UBOX*")) {  /* creating metatable? */
-    lua_pushcfunction(L, boxgc);
-    lua_setfield(L, -2, "__gc");  /* metatable.__gc = boxgc */
-  }
+  if (luaL_newmetatable(L, "_UBOX*"))  /* creating metatable? */
+    luaL_setfuncs(L, boxmt, 0);  /* set its metamethods */
   lua_setmetatable(L, -2);
-  return resizebox(L, -1, newsize);
 }
 
 

@@ -500,34 +514,60 @@
 
 
 /*
-** returns a pointer to a free area with at least 'sz' bytes
+** Compute new size for buffer 'B', enough to accommodate extra 'sz'
+** bytes.
 */
-LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) {
-  lua_State *L = B->L;
-  if (B->size - B->n < sz) {  /* not enough space? */
+static size_t newbuffsize (luaL_Buffer *B, size_t sz) {
+  size_t newsize = B->size * 2;  /* double buffer size */
+  if (MAX_SIZET - sz < B->n)  /* overflow in (B->n + sz)? */
+    return luaL_error(B->L, "buffer too large");
+  if (newsize < B->n + sz)  /* double is not big enough? */
+    newsize = B->n + sz;
+  return newsize;
+}
+
+
+/*
+** Returns a pointer to a free area with at least 'sz' bytes in buffer
+** 'B'. 'boxidx' is the relative position in the stack where the
+** buffer's box is or should be.
+*/
+static char *prepbuffsize (luaL_Buffer *B, size_t sz, int boxidx) {
+  if (B->size - B->n >= sz)  /* enough space? */
+    return B->b + B->n;
+  else {
+    lua_State *L = B->L;
     char *newbuff;
-    size_t newsize = B->size * 2;  /* double buffer size */
-    if (newsize - B->n < sz)  /* not big enough? */
-      newsize = B->n + sz;
-    if (newsize < B->n || newsize - B->n < sz)
-      luaL_error(L, "buffer too large");
+    size_t newsize = newbuffsize(B, sz);
     /* create larger buffer */
-    if (buffonstack(B))
-      newbuff = (char *)resizebox(L, -1, newsize);
-    else {  /* no buffer yet */
-      newbuff = (char *)newbox(L, newsize);
+    if (buffonstack(B))  /* buffer already has a box? */
+      newbuff = (char *)resizebox(L, boxidx, newsize);  /* resize it */
+    else {  /* no box yet */
+      lua_pushnil(L);  /* reserve slot for final result */
+      newbox(L);  /* create a new box */
+      /* move box (and slot) to its intended position */
+      lua_rotate(L, boxidx - 1, 2);
+      lua_toclose(L, boxidx);
+      newbuff = (char *)resizebox(L, boxidx, newsize);
       memcpy(newbuff, B->b, B->n * sizeof(char));  /* copy original content */
     }
     B->b = newbuff;
     B->size = newsize;
+    return newbuff + B->n;
   }
-  return &B->b[B->n];
+}
+
+/*
+** returns a pointer to a free area with at least 'sz' bytes
+*/
+LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) {
+  return prepbuffsize(B, sz, -1);
 }
 
 
 LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) {
   if (l > 0) {  /* avoid 'memcpy' when 's' can be NULL */
-    char *b = luaL_prepbuffsize(B, l);
+    char *b = prepbuffsize(B, l, -1);
     memcpy(b, s, l * sizeof(char));
     luaL_addsize(B, l);
   }

@@ -543,8 +583,8 @@
   lua_State *L = B->L;
   lua_pushlstring(L, B->b, B->n);
   if (buffonstack(B)) {
-    resizebox(L, -2, 0);  /* delete old buffer */
-    lua_remove(L, -2);  /* remove its header from the stack */
+    lua_copy(L, -1, -3);  /* move string to reserved slot */
+    lua_pop(L, 2);  /* pop string and box (closing the box) */
   }
 }
 

@@ -555,14 +595,23 @@
 }
 
 
+/*
+** 'luaL_addvalue' is the only function in the Buffer system where the
+** box (if existent) is not on the top of the stack. So, instead of
+** calling 'luaL_addlstring', it replicates the code using -2 as the
+** last argument to 'prepbuffsize', signaling that the box is (or will
+** be) bellow the string being added to the buffer. (Box creation can
+** trigger an emergency GC, so we should not remove the string from the
+** stack before we have the space guaranteed.)
+*/
 LUALIB_API void luaL_addvalue (luaL_Buffer *B) {
   lua_State *L = B->L;
-  size_t l;
-  const char *s = lua_tolstring(L, -1, &l);
-  if (buffonstack(B))
-    lua_insert(L, -2);  /* put value below buffer */
-  luaL_addlstring(B, s, l);
-  lua_remove(L, (buffonstack(B)) ? -2 : -1);  /* remove value */
+  size_t len;
+  const char *s = lua_tolstring(L, -1, &len);
+  char *b = prepbuffsize(B, len, -2);
+  memcpy(b, s, len * sizeof(char));
+  luaL_addsize(B, len);
+  lua_pop(L, 1);  /* pop string */
 }
 
 

@@ -576,7 +625,7 @@
 
 LUALIB_API char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz) {
   luaL_buffinit(L, B);
-  return luaL_prepbuffsize(B, sz);
+  return prepbuffsize(B, sz, -1);
 }
 
 /* }====================================================== */

@@ -854,9 +903,13 @@
   luaL_checkstack(L, nup, "too many upvalues");
   for (; l->name != NULL; l++) {  /* fill the table with given functions */
     int i;
-    for (i = 0; i < nup; i++)  /* copy upvalues to the top */
-      lua_pushvalue(L, -nup);
-    lua_pushcclosure(L, l->func, nup);  /* closure with those upvalues */
+    if (l->func == NULL)  /* place holder? */
+      lua_pushboolean(L, 0);
+    else {
+      for (i = 0; i < nup; i++)  /* copy upvalues to the top */
+        lua_pushvalue(L, -nup);
+      lua_pushcclosure(L, l->func, nup);  /* closure with those upvalues */
+    }
     lua_setfield(L, -(nup + 2), l->name);
   }
   lua_pop(L, nup);  /* remove upvalues */

@@ -907,18 +960,24 @@
 }
 
 
-LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p,
-                                                               const char *r) {
+LUALIB_API void luaL_addgsub (luaL_Buffer *b, const char *s,
+                                     const char *p, const char *r) {
   const char *wild;
   size_t l = strlen(p);
-  luaL_Buffer b;
-  luaL_buffinit(L, &b);
   while ((wild = strstr(s, p)) != NULL) {
-    luaL_addlstring(&b, s, wild - s);  /* push prefix */
-    luaL_addstring(&b, r);  /* push replacement in place of pattern */
+    luaL_addlstring(b, s, wild - s);  /* push prefix */
+    luaL_addstring(b, r);  /* push replacement in place of pattern */
     s = wild + l;  /* continue after 'p' */
   }
-  luaL_addstring(&b, s);  /* push last suffix */
+  luaL_addstring(b, s);  /* push last suffix */
+}
+
+
+LUALIB_API const char *luaL_gsub (lua_State *L, const char *s,
+                                  const char *p, const char *r) {
+  luaL_Buffer b;
+  luaL_buffinit(L, &b);
+  luaL_addgsub(&b, s, p, r);
   luaL_pushresult(&b);
   return lua_tostring(L, -1);
 }

@@ -942,9 +1001,31 @@
 }
 
 
+/*
+** Emit a warning. '*previoustocont' signals whether previous message
+** was to be continued by the current one.
+*/
+static void warnf (void *ud, const char *message, int tocont) {
+  int *previoustocont = (int *)ud;
+  if (!*previoustocont)  /* previous message was the last? */
+    lua_writestringerror("%s", "Lua warning: ");  /* start a new warning */
+  lua_writestringerror("%s", message);  /* write message */
+  if (!tocont)  /* is this the last part? */
+    lua_writestringerror("%s", "\n");  /* finish message with end-of-line */
+  *previoustocont = tocont;
+}
+
+
 LUALIB_API lua_State *luaL_newstate (void) {
   lua_State *L = lua_newstate(l_alloc, NULL);
-  if (L) lua_atpanic(L, &panic);
+  if (L) {
+    int *previoustocont;  /* space for warning state */
+    lua_atpanic(L, &panic);
+    previoustocont = (int *)lua_newuserdatauv(L, sizeof(int), 0);
+    luaL_ref(L, LUA_REGISTRYINDEX);  /* make sure it won't be collected */
+    *previoustocont = 0;  /* next message starts a new warning */
+    lua_setwarnf(L, warnf, previoustocont);
+  }
   return L;
 }
 

src/lauxlib.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lauxlib.h,v 1.134 2018/02/27 18:47:32 roberto Exp $
+** $Id: lauxlib.h $
 ** Auxiliary functions for building Lua libraries
 ** See Copyright Notice in lua.h
 */

@@ -19,6 +19,8 @@
 #define	LUA_GNAME	"_G"
 
 
+typedef struct luaL_Buffer luaL_Buffer;
+
 
 /* extra error code for 'luaL_loadfilex' */
 #define LUA_ERRFILE     (LUA_ERRERR+1)

@@ -48,6 +50,7 @@
 LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e);
 LUALIB_API const char *(luaL_tolstring) (lua_State *L, int idx, size_t *len);
 LUALIB_API int (luaL_argerror) (lua_State *L, int arg, const char *extramsg);
+LUALIB_API int (luaL_typeerror) (lua_State *L, int arg, const char *tname);
 LUALIB_API const char *(luaL_checklstring) (lua_State *L, int arg,
                                                           size_t *l);
 LUALIB_API const char *(luaL_optlstring) (lua_State *L, int arg,

@@ -77,6 +80,7 @@
 LUALIB_API int (luaL_fileresult) (lua_State *L, int stat, const char *fname);
 LUALIB_API int (luaL_execresult) (lua_State *L, int stat);
 
+
 /* predefined references */
 #define LUA_NOREF       (-2)
 #define LUA_REFNIL      (-1)

@@ -97,8 +101,10 @@
 
 LUALIB_API lua_Integer (luaL_len) (lua_State *L, int idx);
 
-LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p,
-                                                  const char *r);
+LUALIB_API void luaL_addgsub (luaL_Buffer *b, const char *s,
+                                     const char *p, const char *r);
+LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s,
+                                    const char *p, const char *r);
 
 LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup);
 

@@ -125,6 +131,10 @@
 
 #define luaL_argcheck(L, cond,arg,extramsg)	\
 		((void)((cond) || luaL_argerror(L, (arg), (extramsg))))
+
+#define luaL_argexpected(L,cond,arg,tname)	\
+		((void)((cond) || luaL_typeerror(L, (arg), (tname))))
+
 #define luaL_checkstring(L,n)	(luaL_checklstring(L, (n), NULL))
 #define luaL_optstring(L,n,d)	(luaL_optlstring(L, (n), (d), NULL))
 

@@ -149,7 +159,7 @@
 ** =======================================================
 */
 
-typedef struct luaL_Buffer {
+struct luaL_Buffer {
   char *b;  /* buffer address */
   size_t size;  /* buffer size */
   size_t n;  /* number of characters in buffer */

@@ -158,7 +168,11 @@
     LUAI_MAXALIGN;  /* ensure maximum alignment for buffer */
     char b[LUAL_BUFFERSIZE];  /* initial buffer */
   } init;
-} luaL_Buffer;
+};
+
+
+#define luaL_bufflen(bf)	((bf)->n)
+#define luaL_buffaddr(bf)	((bf)->b)
 
 
 #define luaL_addchar(B,c) \

src/lbaselib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lbaselib.c,v 1.323 2018/03/07 15:55:38 roberto Exp $
+** $Id: lbaselib.c $
 ** Basic library
 ** See Copyright Notice in lua.h
 */

@@ -24,18 +24,12 @@
 static int luaB_print (lua_State *L) {
   int n = lua_gettop(L);  /* number of arguments */
   int i;
-  lua_getglobal(L, "tostring");
-  for (i=1; i<=n; i++) {
-    const char *s;
+  for (i = 1; i <= n; i++) {  /* for each argument */
     size_t l;
-    lua_pushvalue(L, -1);  /* function to be called */
-    lua_pushvalue(L, i);   /* value to print */
-    lua_call(L, 1, 1);
-    s = lua_tolstring(L, -1, &l);  /* get result */
-    if (s == NULL)
-      return luaL_error(L, "'tostring' must return a string to 'print'");
-    if (i>1) lua_writestring("\t", 1);
-    lua_writestring(s, l);
+    const char *s = luaL_tolstring(L, i, &l);  /* convert it to string */
+    if (i > 1)  /* not the first element? */
+      lua_writestring("\t", 1);  /* add a tab before it */
+    lua_writestring(s, l);  /* print it */
     lua_pop(L, 1);  /* pop result */
   }
   lua_writeline();

@@ -43,6 +37,13 @@
 }
 
 
+static int luaB_warn (lua_State *L) {
+  const char *msg = luaL_checkstring(L, 1);
+  lua_warning(L, msg, lua_toboolean(L, 2));
+  return 0;
+}
+
+
 #define SPACECHARS	" \f\n\r\t\v"
 
 static const char *b_str2int (const char *s, int base, lua_Integer *pn) {

@@ -68,7 +69,6 @@
 
 static int luaB_tonumber (lua_State *L) {
   if (lua_isnoneornil(L, 2)) {  /* standard conversion? */
-    luaL_checkany(L, 1);
     if (lua_type(L, 1) == LUA_TNUMBER) {  /* already a number? */
       lua_settop(L, 1);  /* yes; return it */
       return 1;

@@ -79,6 +79,7 @@
       if (s != NULL && lua_stringtonumber(L, s) == l + 1)
         return 1;  /* successful conversion to number */
       /* else not a number */
+      luaL_checkany(L, 1);  /* (but there must be some parameter) */
     }
   }
   else {

@@ -125,8 +126,7 @@
 static int luaB_setmetatable (lua_State *L) {
   int t = lua_type(L, 2);
   luaL_checktype(L, 1, LUA_TTABLE);
-  luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
-                    "nil or table expected");
+  luaL_argexpected(L, t == LUA_TNIL || t == LUA_TTABLE, 2, "nil or table");
   if (luaL_getmetafield(L, 1, "__metatable") != LUA_TNIL)
     return luaL_error(L, "cannot change a protected metatable");
   lua_settop(L, 2);

@@ -145,8 +145,8 @@
 
 static int luaB_rawlen (lua_State *L) {
   int t = lua_type(L, 1);
-  luaL_argcheck(L, t == LUA_TTABLE || t == LUA_TSTRING, 1,
-                   "table or string expected");
+  luaL_argexpected(L, t == LUA_TTABLE || t == LUA_TSTRING, 1,
+                      "table or string");
   lua_pushinteger(L, lua_rawlen(L, 1));
   return 1;
 }

@@ -483,6 +483,7 @@
   {"pairs", luaB_pairs},
   {"pcall", luaB_pcall},
   {"print", luaB_print},
+  {"warn", luaB_warn},
   {"rawequal", luaB_rawequal},
   {"rawlen", luaB_rawlen},
   {"rawget", luaB_rawget},

src/lcode.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lcode.c,v 2.161 2018/04/04 14:23:41 roberto Exp $
+** $Id: lcode.c $
 ** Code generator for Lua
 ** See Copyright Notice in lua.h
 */

@@ -179,8 +179,8 @@
 ** Code a "conditional jump", that is, a test or comparison opcode
 ** followed by a jump. Return jump position.
 */
-static int condjump (FuncState *fs, OpCode op, int A, int B, int k) {
-  luaK_codeABCk(fs, op, A, B, 0, k);
+static int condjump (FuncState *fs, OpCode op, int A, int B, int C, int k) {
+  luaK_codeABCk(fs, op, A, B, C, k);
   return luaK_jump(fs);
 }
 

@@ -276,43 +276,18 @@
 
 
 /*
-** Correct a jump list to jump to 'target'. If 'hasclose' is true,
-** 'target' contains an OP_CLOSE instruction (see first assert).
-** Only the jumps with ('m' == true) need that close; other jumps
-** avoid it jumping to the next instruction.
+** MAXimum number of successive Instructions WiTHout ABSolute line
+** information.
 */
-void luaK_patchgoto (FuncState *fs, int list, int target, int hasclose) {
-  lua_assert(!hasclose || GET_OPCODE(fs->f->code[target]) == OP_CLOSE);
-  while (list != NO_JUMP) {
-    int next = getjump(fs, list);
-    lua_assert(!GETARG_m(fs->f->code[list]) || hasclose);
-    patchtestreg(fs, list, NO_REG);  /* do not generate values */
-    if (!hasclose || GETARG_m(fs->f->code[list]))
-      fixjump(fs, list, target);
-    else  /* there is a CLOSE instruction but jump does not need it */
-      fixjump(fs, list, target + 1);  /* avoid CLOSE instruction */
-    list = next;
-  }
-}
-
-
-/*
-** Mark (using the 'm' arg) all jumps in 'list' to close upvalues. Mark
-** will instruct 'luaK_patchgoto' to make these jumps go to OP_CLOSE
-** instructions.
-*/
-void luaK_patchclose (FuncState *fs, int list) {
-  for (; list != NO_JUMP; list = getjump(fs, list)) {
-    lua_assert(GET_OPCODE(fs->f->code[list]) == OP_JMP);
-    SETARG_m(fs->f->code[list], 1);
-  }
-}
-
-
 #if !defined(MAXIWTHABS)
 #define MAXIWTHABS	120
 #endif
 
+
+/* limit for difference between lines in relative line info. */
+#define LIMLINEDIFF	0x80
+
+
 /*
 ** Save line info for a new instruction. If difference from last line
 ** does not fit in a byte, of after that many instructions, save a new

@@ -320,14 +295,15 @@
 ** in 'lineinfo' signals the existence of this absolute information.)
 ** Otherwise, store the difference from last line in 'lineinfo'.
 */
-static void savelineinfo (FuncState *fs, Proto *f, int pc, int line) {
+static void savelineinfo (FuncState *fs, Proto *f, int line) {
   int linedif = line - fs->previousline;
-  if (abs(linedif) >= 0x80 || fs->iwthabs++ > MAXIWTHABS) {
+  int pc = fs->pc - 1;  /* last instruction coded */
+  if (abs(linedif) >= LIMLINEDIFF || fs->iwthabs++ > MAXIWTHABS) {
     luaM_growvector(fs->ls->L, f->abslineinfo, fs->nabslineinfo,
                     f->sizeabslineinfo, AbsLineInfo, MAX_INT, "lines");
     f->abslineinfo[fs->nabslineinfo].pc = pc;
     f->abslineinfo[fs->nabslineinfo++].line = line;
-    linedif = ABSLINEINFO;  /* signal there is absolute information */
+    linedif = ABSLINEINFO;  /* signal that there is absolute information */
     fs->iwthabs = 0;  /* restart counter */
   }
   luaM_growvector(fs->ls->L, f->lineinfo, pc, f->sizelineinfo, ls_byte,

@@ -338,6 +314,37 @@
 
 
 /*
+** Remove line information from the last instruction.
+** If line information for that instruction is absolute, set 'iwthabs'
+** above its max to force the new (replacing) instruction to have
+** absolute line info, too.
+*/
+static void removelastlineinfo (FuncState *fs) {
+  Proto *f = fs->f;
+  int pc = fs->pc - 1;  /* last instruction coded */
+  if (f->lineinfo[pc] != ABSLINEINFO) {  /* relative line info? */
+    fs->previousline -= f->lineinfo[pc];  /* last line saved */
+    fs->iwthabs--;
+  }
+  else {  /* absolute line information */
+    fs->nabslineinfo--;  /* remove it */
+    lua_assert(f->abslineinfo[fs->nabslineinfo].pc = pc);
+    fs->iwthabs = MAXIWTHABS + 1;  /* force next line info to be absolute */
+  }
+}
+
+
+/*
+** Remove the last instruction created, correcting line information
+** accordingly.
+*/
+static void removelastinstruction (FuncState *fs) {
+  removelastlineinfo(fs);
+  fs->pc--;
+}
+
+
+/*
 ** Emit instruction 'i', checking for array sizes and saving also its
 ** line information. Return 'i' position.
 */

@@ -346,9 +353,9 @@
   /* put new instruction in code array */
   luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction,
                   MAX_INT, "opcodes");
-  f->code[fs->pc] = i;
-  savelineinfo(fs, f, fs->pc, fs->ls->lastline);
-  return fs->pc++;
+  f->code[fs->pc++] = i;
+  savelineinfo(fs, f, fs->ls->lastline);
+  return fs->pc - 1;  /* index of new instruction */
 }
 
 

@@ -364,10 +371,6 @@
 }
 
 
-#define codeABsC(fs,o,a,b,c,k)	luaK_codeABCk(fs,o,a,b,((c) + OFFSET_sC),k)
-
-
-
 /*
 ** Format and emit an 'iABx' instruction.
 */

@@ -675,11 +678,12 @@
 void luaK_dischargevars (FuncState *fs, expdesc *e) {
   switch (e->k) {
     case VLOCAL: {  /* already in a register */
+      e->u.info = e->u.var.idx;
       e->k = VNONRELOC;  /* becomes a non-relocatable value */
       break;
     }
     case VUPVAL: {  /* move value to some (pending) register */
-      e->u.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0);
+      e->u.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.var.idx, 0);
       e->k = VRELOC;
       break;
     }

@@ -796,7 +800,7 @@
 
 /*
 ** Ensures final expression result (which includes results from its
-** jump ** lists) is in register 'reg'.
+** jump lists) is in register 'reg'.
 ** If expression has jumps, need to patch these jumps either to
 ** its final position or to "load" instructions (for those tests
 ** that do not produce values).

@@ -811,8 +815,9 @@
     int p_t = NO_JUMP;  /* position of an eventual LOAD true */
     if (need_value(fs, e->t) || need_value(fs, e->f)) {
       int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs);
-      p_f = code_loadbool(fs, reg, 0, 1);
-      p_t = code_loadbool(fs, reg, 1, 0);
+      p_f = code_loadbool(fs, reg, 0, 1);  /* load false and skip next i. */
+      p_t = code_loadbool(fs, reg, 1, 0);  /* load true */
+      /* jump around these booleans if 'e' is not a test */
       luaK_patchtohere(fs, fj);
     }
     final = luaK_getlabel(fs);

@@ -878,30 +883,45 @@
 
 
 /*
+** Try to make 'e' a K expression with an index in the range of R/K
+** indices. Return true iff succeeded.
+*/
+static int luaK_exp2K (FuncState *fs, expdesc *e) {
+  if (!hasjumps(e)) {
+    int info;
+    switch (e->k) {  /* move constants to 'k' */
+      case VTRUE: info = boolK(fs, 1); break;
+      case VFALSE: info = boolK(fs, 0); break;
+      case VNIL: info = nilK(fs); break;
+      case VKINT: info = luaK_intK(fs, e->u.ival); break;
+      case VKFLT: info = luaK_numberK(fs, e->u.nval); break;
+      case VK: info = e->u.info; break;
+      default: return 0;  /* not a constant */
+    }
+    if (info <= MAXINDEXRK) {  /* does constant fit in 'argC'? */
+      e->k = VK;  /* make expression a 'K' expression */
+      e->u.info = info;
+      return 1;
+    }
+  }
+  /* else, expression doesn't fit; leave it unchanged */
+  return 0;
+}
+
+
+/*
 ** Ensures final expression result is in a valid R/K index
 ** (that is, it is either in a register or in 'k' with an index
 ** in the range of R/K indices).
-** Returns 1 if expression is K, 0 otherwise.
+** Returns 1 iff expression is K.
 */
 int luaK_exp2RK (FuncState *fs, expdesc *e) {
-  luaK_exp2val(fs, e);
-  switch (e->k) {  /* move constants to 'k' */
-    case VTRUE: e->u.info = boolK(fs, 1); goto vk;
-    case VFALSE: e->u.info = boolK(fs, 0); goto vk;
-    case VNIL: e->u.info = nilK(fs); goto vk;
-    case VKINT: e->u.info = luaK_intK(fs, e->u.ival); goto vk;
-    case VKFLT: e->u.info = luaK_numberK(fs, e->u.nval); goto vk;
-    case VK:
-     vk:
-      e->k = VK;
-      if (e->u.info <= MAXINDEXRK)  /* constant fits in 'argC'? */
-        return 1;
-      else break;
-    default: break;
+  if (luaK_exp2K(fs, e))
+    return 1;
+  else {  /* not a constant in the right range: put it in a register */
+    luaK_exp2anyreg(fs, e);
+    return 0;
   }
-  /* not a constant in the right range: put it in a register */
-  luaK_exp2anyreg(fs, e);
-  return 0;
 }
 
 

@@ -919,12 +939,12 @@
   switch (var->k) {
     case VLOCAL: {
       freeexp(fs, ex);
-      exp2reg(fs, ex, var->u.info);  /* compute 'ex' into proper place */
+      exp2reg(fs, ex, var->u.var.idx);  /* compute 'ex' into proper place */
       return;
     }
     case VUPVAL: {
       int e = luaK_exp2anyreg(fs, ex);
-      luaK_codeABC(fs, OP_SETUPVAL, e, var->u.info, 0);
+      luaK_codeABC(fs, OP_SETUPVAL, e, var->u.var.idx, 0);
       break;
     }
     case VINDEXUP: {

@@ -986,14 +1006,14 @@
   if (e->k == VRELOC) {
     Instruction ie = getinstruction(fs, e);
     if (GET_OPCODE(ie) == OP_NOT) {
-      fs->pc--;  /* remove previous OP_NOT */
-      return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond);
+      removelastinstruction(fs);  /* remove previous OP_NOT */
+      return condjump(fs, OP_TEST, GETARG_B(ie), 0, 0, !cond);
     }
     /* else go through */
   }
   discharge2anyreg(fs, e);
   freeexp(fs, e);
-  return condjump(fs, OP_TESTSET, NO_REG, e->u.info, cond);
+  return condjump(fs, OP_TESTSET, NO_REG, e->u.info, 0, cond);
 }
 
 

@@ -1121,13 +1141,15 @@
 
 /*
 ** Check whether expression 'e' is a literal integer or float in
-** proper range to fit in register sC
+** proper range to fit in a register (sB or sC).
 */
-static int isSCnumber (expdesc *e, lua_Integer *i) {
+static int isSCnumber (expdesc *e, lua_Integer *i, int *isfloat) {
   if (e->k == VKINT)
     *i = e->u.ival;
   else if (!(e->k == VKFLT && floatI(e->u.nval, i)))
     return 0;  /* not a number */
+  else
+    *isfloat = 1;
   if (!hasjumps(e) && fitsC(*i)) {
     *i += OFFSET_sC;
     return 1;

@@ -1144,25 +1166,30 @@
 ** values in registers.
 */
 void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
-  lua_assert(!hasjumps(t) && (vkisinreg(t->k) || t->k == VUPVAL));
+  lua_assert(!hasjumps(t) &&
+             (t->k == VLOCAL || t->k == VNONRELOC || t->k == VUPVAL));
   if (t->k == VUPVAL && !isKstr(fs, k))  /* upvalue indexed by non string? */
     luaK_exp2anyreg(fs, t);  /* put it in a register */
-  t->u.ind.t = t->u.info;  /* register or upvalue index */
   if (t->k == VUPVAL) {
+    t->u.ind.t = t->u.var.idx;  /* upvalue index */
     t->u.ind.idx = k->u.info;  /* literal string */
     t->k = VINDEXUP;
   }
-  else if (isKstr(fs, k)) {
-    t->u.ind.idx = k->u.info;  /* literal string */
-    t->k = VINDEXSTR;
-  }
-  else if (isCint(k)) {
-    t->u.ind.idx = cast_int(k->u.ival);  /* integer constant in proper range */
-    t->k = VINDEXI;
-  }
   else {
-    t->u.ind.idx = luaK_exp2anyreg(fs, k);  /* register */
-    t->k = VINDEXED;
+    /* register index of the table */
+    t->u.ind.t = (t->k == VLOCAL) ? t->u.var.idx: t->u.info;
+    if (isKstr(fs, k)) {
+      t->u.ind.idx = k->u.info;  /* literal string */
+      t->k = VINDEXSTR;
+    }
+    else if (isCint(k)) {
+      t->u.ind.idx = cast_int(k->u.ival);  /* int. constant in proper range */
+      t->k = VINDEXI;
+    }
+    else {
+      t->u.ind.idx = luaK_exp2anyreg(fs, k);  /* register */
+      t->k = VINDEXED;
+    }
   }
 }
 

@@ -1225,8 +1252,19 @@
 }
 
 
+/*
+** Emit code for binary expressions that "produce values"
+** (everything but logical operators 'and'/'or' and comparison
+** operators).
+** Expression to produce final result will be encoded in 'e1'.
+** Because 'luaK_exp2anyreg' can free registers, its calls must be
+** in "stack order" (that is, first on 'e2', which may have more
+** recent registers to be released).
+*/
 static void finishbinexpval (FuncState *fs, expdesc *e1, expdesc *e2,
-                             int pc, int line) {
+                             OpCode op, int v2, int k, int line) {
+  int v1 = luaK_exp2anyreg(fs, e1);
+  int pc = luaK_codeABCk(fs, op, 0, v1, v2, k);
   freeexps(fs, e1, e2);
   e1->u.info = pc;
   e1->k = VRELOC;  /* all those operations are relocatable */

@@ -1235,20 +1273,13 @@
 
 
 /*
-** Emit code for binary expressions that "produce values"
-** (everything but logical operators 'and'/'or' and comparison
-** operators).
-** Expression to produce final result will be encoded in 'e1'.
-** Because 'luaK_exp2anyreg' can free registers, its calls must be
-** in "stack order" (that is, first on 'e2', which may have more
-** recent registers to be released).
+** Emit code for binary expressions that "produce values" over
+** two registers.
 */
 static void codebinexpval (FuncState *fs, OpCode op,
                            expdesc *e1, expdesc *e2, int line) {
   int v2 = luaK_exp2anyreg(fs, e2);  /* both operands are in registers */
-  int v1 = luaK_exp2anyreg(fs, e1);
-  int pc = luaK_codeABC(fs, op, 0, v1, v2);  /* generate opcode */
-  finishbinexpval(fs, e1, e2, pc, line);
+  finishbinexpval(fs, e1, e2, op, v2, 0, line);
 }
 
 

@@ -1257,41 +1288,48 @@
 */
 static void codebini (FuncState *fs, OpCode op,
                        expdesc *e1, expdesc *e2, int k, int line) {
-  int v2 = cast_int(e2->u.ival);  /* immediate operand */
-  int v1 = luaK_exp2anyreg(fs, e1);
-  int pc = codeABsC(fs, op, 0, v1, v2, k);  /* generate opcode */
-  finishbinexpval(fs, e1, e2, pc, line);
+  int v2 = cast_int(e2->u.ival) + OFFSET_sC;  /* immediate operand */
+  finishbinexpval(fs, e1, e2, op, v2, k, line);
+}
+
+
+static void swapexps (expdesc *e1, expdesc *e2) {
+  expdesc temp = *e1; *e1 = *e2; *e2 = temp;  /* swap 'e1' and 'e2' */
 }
 
 
 /*
 ** Code arithmetic operators ('+', '-', ...). If second operand is a
 ** constant in the proper range, use variant opcodes with immediate
-** operands.
+** operands or K operands.
 */
 static void codearith (FuncState *fs, OpCode op,
                        expdesc *e1, expdesc *e2, int flip, int line) {
-  if (!isSCint(e2))
-    codebinexpval(fs, op, e1, e2, line);  /* use standard operators */
-  else  /* use immediate operators */
+  if (isSCint(e2))  /* immediate operand? */
     codebini(fs, cast(OpCode, op - OP_ADD + OP_ADDI), e1, e2, flip, line);
-}
-
-
-static void swapexps (expdesc *e1, expdesc *e2) {
-  expdesc temp = *e1; *e1 = *e2; *e2 = temp;  /* swap 'e1' and 'e2' */
+  else if (tonumeral(e2, NULL) && luaK_exp2K(fs, e2)) {  /* K operand? */
+    int v2 = e2->u.info;  /* K index */
+    op = cast(OpCode, op - OP_ADD + OP_ADDK);
+    finishbinexpval(fs, e1, e2, op, v2, flip, line);
+  }
+  else {  /* 'e2' is neither an immediate nor a K operand */
+    if (flip)
+      swapexps(e1, e2);  /* back to original order */
+    codebinexpval(fs, op, e1, e2, line);  /* use standard operators */
+  }
 }
 
 
 /*
 ** Code commutative operators ('+', '*'). If first operand is a
-** constant, change order of operands to use immediate operator.
+** numeric constant, change order of operands to try to use an
+** immediate or K operator.
 */
 static void codecommutative (FuncState *fs, OpCode op,
                              expdesc *e1, expdesc *e2, int line) {
   int flip = 0;
-  if (isSCint(e1)) {
-    swapexps(e1, e2);
+  if (tonumeral(e1, NULL)) {  /* is first operand a numeric constant? */
+    swapexps(e1, e2);  /* change order */
     flip = 1;
   }
   codearith(fs, op, e1, e2, flip, line);

@@ -1305,7 +1343,7 @@
 static void codebitwise (FuncState *fs, BinOpr opr,
                          expdesc *e1, expdesc *e2, int line) {
   int inv = 0;
-  int v1, v2, pc;
+  int v2;
   OpCode op;
   if (e1->k == VKINT && luaK_exp2RK(fs, e1)) {
     swapexps(e1, e2);  /* 'e2' will be the constant operand */

@@ -1316,12 +1354,10 @@
     codebinexpval(fs, op, e1, e2, line);  /* all-register opcodes */
     return;
   }
-  v1 = luaK_exp2anyreg(fs, e1);
   v2 = e2->u.info;  /* index in K array */
   op = cast(OpCode, opr - OPR_BAND + OP_BANDK);
   lua_assert(ttisinteger(&fs->f->k[v2]));
-  pc = luaK_codeABCk(fs, op, 0, v1, v2, inv);
-  finishbinexpval(fs, e1, e2, pc, line);
+  finishbinexpval(fs, e1, e2, op, v2, inv, line);
 }
 
 

@@ -1345,21 +1381,20 @@
 
 
 /*
-** Emit code for order comparisons.
-** When the first operand A is an integral value in the proper range,
-** change (A < B) to (B > A) and (A <= B) to (B >= A) so that
-** it can use an immediate operand.
+** Emit code for order comparisons. When using an immediate operand,
+** 'isfloat' tells whether the original value was a float.
 */
 static void codeorder (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) {
   int r1, r2;
   lua_Integer im;
-  if (isSCnumber(e2, &im)) {
+  int isfloat = 0;
+  if (isSCnumber(e2, &im, &isfloat)) {
     /* use immediate operand */
     r1 = luaK_exp2anyreg(fs, e1);
     r2 = cast_int(im);
     op = cast(OpCode, (op - OP_LT) + OP_LTI);
   }
-  else if (isSCnumber(e1, &im)) {
+  else if (isSCnumber(e1, &im, &isfloat)) {
     /* transform (A < B) to (B > A) and (A <= B) to (B >= A) */
     r1 = luaK_exp2anyreg(fs, e2);
     r2 = cast_int(im);

@@ -1370,7 +1405,7 @@
     r2 = luaK_exp2anyreg(fs, e2);
   }
   freeexps(fs, e1, e2);
-  e1->u.info = condjump(fs, op, r1, r2, 1);
+  e1->u.info = condjump(fs, op, r1, r2, isfloat, 1);
   e1->k = VJMP;
 }
 

@@ -1382,13 +1417,14 @@
 static void codeeq (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) {
   int r1, r2;
   lua_Integer im;
+  int isfloat = 0;  /* not needed here, but kept for symmetry */
   OpCode op;
   if (e1->k != VNONRELOC) {
     lua_assert(e1->k == VK || e1->k == VKINT || e1->k == VKFLT);
     swapexps(e1, e2);
   }
   r1 = luaK_exp2anyreg(fs, e1);  /* 1nd expression must be in register */
-  if (isSCnumber(e2, &im)) {
+  if (isSCnumber(e2, &im, &isfloat)) {
     op = OP_EQI;
     r2 = cast_int(im);  /* immediate operand */
   }

@@ -1401,7 +1437,7 @@
     r2 = luaK_exp2anyreg(fs, e2);
   }
   freeexps(fs, e1, e2);
-  e1->u.info = condjump(fs, op, r1, r2, (opr == OPR_EQ));
+  e1->u.info = condjump(fs, op, r1, r2, isfloat, (opr == OPR_EQ));
   e1->k = VJMP;
 }
 

@@ -1462,7 +1498,8 @@
     case OPR_LT: case OPR_LE:
     case OPR_GT: case OPR_GE: {
       lua_Integer dummy;
-      if (!isSCnumber(v, &dummy))
+      int dummy2;
+      if (!isSCnumber(v, &dummy, &dummy2))
         luaK_exp2anyreg(fs, v);
       /* else keep numeral, which may be an immediate operand */
       break;

@@ -1572,23 +1609,12 @@
 
 
 /*
-** Change line information associated with current position. If that
-** information is absolute, just change it and correct 'previousline'.
-** Otherwise, restore 'previousline' to its value before saving the
-** current position and than saves the line information again, with the
-** new line.
+** Change line information associated with current position, by removing
+** previous info and adding it again with new line.
 */
 void luaK_fixline (FuncState *fs, int line) {
-  Proto *f = fs->f;
-  if (f->lineinfo[fs->pc - 1] == ABSLINEINFO) {
-    lua_assert(f->abslineinfo[fs->nabslineinfo - 1].pc == fs->pc - 1);
-    f->abslineinfo[fs->nabslineinfo - 1].line = line;
-    fs->previousline = line;
-  }
-  else {
-    fs->previousline -= f->lineinfo[fs->pc - 1];  /* undo previous info. */
-    savelineinfo(fs, f, fs->pc - 1, line);  /* redo it */
-  }
+  removelastlineinfo(fs);
+  savelineinfo(fs, fs->f, line);
 }
 
 

@@ -1643,13 +1669,13 @@
     lua_assert(i == 0 || isOT(*(pc - 1)) == isIT(*pc));
     switch (GET_OPCODE(*pc)) {
       case OP_RETURN0: case OP_RETURN1: {
-        if (p->sizep == 0 && !p->is_vararg)
+        if (!(fs->needclose || p->is_vararg))
           break;  /* no extra work */
         /* else use OP_RETURN to do the extra work */
         SET_OPCODE(*pc, OP_RETURN);
       }  /* FALLTHROUGH */
       case OP_RETURN: case OP_TAILCALL: {
-        if (p->sizep > 0 || p->is_vararg) {
+        if (fs->needclose || p->is_vararg) {
           SETARG_C(*pc, p->is_vararg ? p->numparams + 1 : 0);
           SETARG_k(*pc, 1);  /* signal that there is extra work */
         }

src/lcode.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lcode.h,v 1.73 2018/04/04 14:23:41 roberto Exp $
+** $Id: lcode.h $
 ** Code generator for Lua
 ** See Copyright Notice in lua.h
 */

@@ -78,10 +78,7 @@
 LUAI_FUNC int luaK_jump (FuncState *fs);
 LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret);
 LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target);
-LUAI_FUNC void luaK_patchgoto (FuncState *fs, int list, int target,
-                               int hasclose);
 LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list);
-LUAI_FUNC void luaK_patchclose (FuncState *fs, int list);
 LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2);
 LUAI_FUNC int luaK_getlabel (FuncState *fs);
 LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v, int line);

src/lcorolib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lcorolib.c,v 1.11 2017/11/02 11:28:56 roberto Exp $
+** $Id: lcorolib.c $
 ** Coroutine Library
 ** See Copyright Notice in lua.h
 */

@@ -20,21 +20,21 @@
 
 static lua_State *getco (lua_State *L) {
   lua_State *co = lua_tothread(L, 1);
-  luaL_argcheck(L, co, 1, "thread expected");
+  luaL_argexpected(L, co, 1, "thread");
   return co;
 }
 
 
+/*
+** Resumes a coroutine. Returns the number of results for non-error
+** cases or -1 for errors.
+*/
 static int auxresume (lua_State *L, lua_State *co, int narg) {
   int status, nres;
   if (!lua_checkstack(co, narg)) {
     lua_pushliteral(L, "too many arguments to resume");
     return -1;  /* error flag */
   }
-  if (lua_status(co) == LUA_OK && lua_gettop(co) == 0) {
-    lua_pushliteral(L, "cannot resume dead coroutine");
-    return -1;  /* error flag */
-  }
   lua_xmove(L, co, narg);
   status = lua_resume(co, L, narg, &nres);
   if (status == LUA_OK || status == LUA_YIELD) {

@@ -74,8 +74,14 @@
   lua_State *co = lua_tothread(L, lua_upvalueindex(1));
   int r = auxresume(L, co, lua_gettop(L));
   if (r < 0) {
+    int stat = lua_status(co);
+    if (stat != LUA_OK && stat != LUA_YIELD) {
+      stat = lua_resetthread(co);  /* close variables in case of errors */
+      if (stat != LUA_OK)  /* error closing variables? */
+        lua_xmove(co, L, 1);  /* get new error object */
+    }
     if (lua_type(L, -1) == LUA_TSTRING) {  /* error object is a string? */
-      luaL_where(L, 1);  /* add extra info */
+      luaL_where(L, 1);  /* add extra info, if available */
       lua_insert(L, -2);
       lua_concat(L, 2);
     }

@@ -107,35 +113,47 @@
 }
 
 
-static int luaB_costatus (lua_State *L) {
-  lua_State *co = getco(L);
-  if (L == co) lua_pushliteral(L, "running");
+#define COS_RUN		0
+#define COS_DEAD	1
+#define COS_YIELD	2
+#define COS_NORM	3
+
+
+static const char *statname[] = {"running", "dead", "suspended", "normal"};
+
+
+static int auxstatus (lua_State *L, lua_State *co) {
+  if (L == co) return COS_RUN;
   else {
     switch (lua_status(co)) {
       case LUA_YIELD:
-        lua_pushliteral(L, "suspended");
-        break;
+        return COS_YIELD;
       case LUA_OK: {
         lua_Debug ar;
-        if (lua_getstack(co, 0, &ar) > 0)  /* does it have frames? */
-          lua_pushliteral(L, "normal");  /* it is running */
+        if (lua_getstack(co, 0, &ar))  /* does it have frames? */
+          return COS_NORM;  /* it is running */
         else if (lua_gettop(co) == 0)
-            lua_pushliteral(L, "dead");
+            return COS_DEAD;
         else
-          lua_pushliteral(L, "suspended");  /* initial state */
-        break;
+          return COS_YIELD;  /* initial state */
       }
       default:  /* some error occurred */
-        lua_pushliteral(L, "dead");
-        break;
+        return COS_DEAD;
     }
   }
+}
+
+
+static int luaB_costatus (lua_State *L) {
+  lua_State *co = getco(L);
+  lua_pushstring(L, statname[auxstatus(L, co)]);
   return 1;
 }
 
 
 static int luaB_yieldable (lua_State *L) {
-  lua_pushboolean(L, lua_isyieldable(L));
+  lua_State *co = lua_isnone(L, 1) ? L : getco(L);
+  lua_pushboolean(L, lua_isyieldable(co));
   return 1;
 }
 

@@ -147,6 +165,28 @@
 }
 
 
+static int luaB_kill (lua_State *L) {
+  lua_State *co = getco(L);
+  int status = auxstatus(L, co);
+  switch (status) {
+    case COS_DEAD: case COS_YIELD: {
+      status = lua_resetthread(co);
+      if (status == LUA_OK) {
+        lua_pushboolean(L, 1);
+        return 1;
+      }
+      else {
+        lua_pushboolean(L, 0);
+        lua_xmove(co, L, 1);  /* copy error message */
+        return 2;
+      }
+    }
+    default:  /* normal or running coroutine */
+      return luaL_error(L, "cannot kill a %s coroutine", statname[status]);
+  }
+}
+
+
 static const luaL_Reg co_funcs[] = {
   {"create", luaB_cocreate},
   {"resume", luaB_coresume},

@@ -155,6 +195,7 @@
   {"wrap", luaB_cowrap},
   {"yield", luaB_yield},
   {"isyieldable", luaB_yieldable},
+  {"kill", luaB_kill},
   {NULL, NULL}
 };
 

src/lctype.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lctype.c,v 1.12 2014/11/02 19:19:04 roberto Exp $
+** $Id: lctype.c $
 ** 'ctype' functions for Lua
 ** See Copyright Notice in lua.h
 */

src/lctype.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lctype.h,v 1.13 2018/06/18 12:51:05 roberto Exp $
+** $Id: lctype.h $
 ** 'ctype' functions for Lua
 ** See Copyright Notice in lua.h
 */

src/ldblib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldblib.c,v 1.155 2018/03/16 15:33:34 roberto Exp $
+** $Id: ldblib.c $
 ** Interface from Lua to its debug API
 ** See Copyright Notice in lua.h
 */

@@ -55,8 +55,7 @@
 
 static int db_setmetatable (lua_State *L) {
   int t = lua_type(L, 2);
-  luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
-                    "nil or table expected");
+  luaL_argexpected(L, t == LUA_TNIL || t == LUA_TTABLE, 2, "nil or table");
   lua_settop(L, 2);
   lua_setmetatable(L, 1);
   return 1;  /* return 1st argument */

@@ -168,7 +167,8 @@
     return luaL_argerror(L, arg+2, "invalid option");
   lua_newtable(L);  /* table to collect results */
   if (strchr(options, 'S')) {
-    settabss(L, "source", ar.source);
+    lua_pushlstring(L, ar.source, ar.srclen);
+    lua_setfield(L, -2, "source");
     settabss(L, "short_src", ar.short_src);
     settabsi(L, "linedefined", ar.linedefined);
     settabsi(L, "lastlinedefined", ar.lastlinedefined);

src/ldebug.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldebug.c,v 2.158 2018/06/08 19:06:59 roberto Exp $
+** $Id: ldebug.c $
 ** Debug Interface
 ** See Copyright Notice in lua.h
 */

@@ -192,15 +192,14 @@
     int nextra = ci->u.l.nextraargs;
     if (n <= nextra) {
       *pos = ci->func - nextra + (n - 1);
-      return "(*vararg)";  /* generic name for any vararg */
+      return "(vararg)";  /* generic name for any vararg */
     }
   }
   return NULL;  /* no such vararg */
 }
 
 
-static const char *findlocal (lua_State *L, CallInfo *ci, int n,
-                              StkId *pos) {
+const char *luaG_findlocal (lua_State *L, CallInfo *ci, int n, StkId *pos) {
   StkId base = ci->func + 1;
   const char *name = NULL;
   if (isLua(ci)) {

@@ -211,12 +210,15 @@
   }
   if (name == NULL) {  /* no 'standard' name? */
     StkId limit = (ci == L->ci) ? L->top : ci->next->func;
-    if (limit - base >= n && n > 0)  /* is 'n' inside 'ci' stack? */
-      name = "(*temporary)";  /* generic name for any valid slot */
+    if (limit - base >= n && n > 0) {  /* is 'n' inside 'ci' stack? */
+      /* generic name for any valid slot */
+      name = isLua(ci) ? "(temporary)" : "(C temporary)";
+    }
     else
       return NULL;  /* no name */
   }
-  *pos = base + (n - 1);
+  if (pos)
+    *pos = base + (n - 1);
   return name;
 }
 

@@ -232,7 +234,7 @@
   }
   else {  /* active function; get information through 'ar' */
     StkId pos = NULL;  /* to avoid warnings */
-    name = findlocal(L, ar->i_ci, n, &pos);
+    name = luaG_findlocal(L, ar->i_ci, n, &pos);
     if (name) {
       setobjs2s(L, L->top, pos);
       api_incr_top(L);

@@ -247,7 +249,7 @@
   StkId pos = NULL;  /* to avoid warnings */
   const char *name;
   lua_lock(L);
-  name = findlocal(L, ar->i_ci, n, &pos);
+  name = luaG_findlocal(L, ar->i_ci, n, &pos);
   if (name) {
     setobjs2s(L, pos, L->top - 1);
     L->top--;  /* pop value */

@@ -260,18 +262,26 @@
 static void funcinfo (lua_Debug *ar, Closure *cl) {
   if (noLuaClosure(cl)) {
     ar->source = "=[C]";
+    ar->srclen = LL("=[C]");
     ar->linedefined = -1;
     ar->lastlinedefined = -1;
     ar->what = "C";
   }
   else {
     const Proto *p = cl->l.p;
-    ar->source = p->source ? getstr(p->source) : "=?";
+    if (p->source) {
+      ar->source = getstr(p->source);
+      ar->srclen = tsslen(p->source);
+    }
+    else {
+      ar->source = "=?";
+      ar->srclen = LL("=?");
+    }
     ar->linedefined = p->linedefined;
     ar->lastlinedefined = p->lastlinedefined;
     ar->what = (ar->linedefined == 0) ? "main" : "Lua";
   }
-  luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE);
+  luaO_chunkid(ar->short_src, ar->source, ar->srclen);
 }
 
 

@@ -610,12 +620,18 @@
       tm = TM_NEWINDEX;
       break;
     case OP_ADDI: case OP_SUBI: case OP_MULI: case OP_MODI:
-    case OP_POWI: case OP_DIVI: case OP_IDIVI:
-    case OP_BANDK: case OP_BORK: case OP_BXORK: {
+    case OP_POWI: case OP_DIVI: case OP_IDIVI: {
       int offset = GET_OPCODE(i) - OP_ADDI;  /* ORDER OP */
       tm = cast(TMS, offset + TM_ADD);  /* ORDER TM */
       break;
     }
+    case OP_ADDK: case OP_SUBK: case OP_MULK: case OP_MODK:
+    case OP_POWK: case OP_DIVK: case OP_IDIVK:
+    case OP_BANDK: case OP_BORK: case OP_BXORK: {
+      int offset = GET_OPCODE(i) - OP_ADDK;  /* ORDER OP */
+      tm = cast(TMS, offset + TM_ADD);  /* ORDER TM */
+      break;
+    }
     case OP_ADD: case OP_SUB: case OP_MUL: case OP_MOD:
     case OP_POW: case OP_DIV: case OP_IDIV: case OP_BAND:
     case OP_BOR: case OP_BXOR: case OP_SHL: case OP_SHR: {

@@ -696,6 +712,12 @@
 }
 
 
+l_noret luaG_forerror (lua_State *L, const TValue *o, const char *what) {
+  luaG_runerror(L, "bad 'for' %s (number expected, got %s)",
+                   what, luaT_objtypename(L, o));
+}
+
+
 l_noret luaG_concaterror (lua_State *L, const TValue *p1, const TValue *p2) {
   if (ttisstring(p1) || cvt2str(p1)) p1 = p2;
   luaG_typeerror(L, p1, "concatenate");

@@ -736,7 +758,7 @@
                                         int line) {
   char buff[LUA_IDSIZE];
   if (src)
-    luaO_chunkid(buff, getstr(src), LUA_IDSIZE);
+    luaO_chunkid(buff, getstr(src), tsslen(src));
   else {  /* no source available; use "?" instead */
     buff[0] = '?'; buff[1] = '\0';
   }

src/ldebug.h

@@ -1,5 +1,5 @@
 /*
-** $Id: ldebug.h,v 2.18 2018/06/08 19:06:59 roberto Exp $
+** $Id: ldebug.h $
 ** Auxiliary functions from Debug Interface module
 ** See Copyright Notice in lua.h
 */

@@ -22,8 +22,12 @@
 #define ABSLINEINFO	(-0x80)
 
 LUAI_FUNC int luaG_getfuncline (const Proto *f, int pc);
+LUAI_FUNC const char *luaG_findlocal (lua_State *L, CallInfo *ci, int n,
+                                                    StkId *pos);
 LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o,
                                                 const char *opname);
+LUAI_FUNC l_noret luaG_forerror (lua_State *L, const TValue *o,
+                                               const char *what);
 LUAI_FUNC l_noret luaG_concaterror (lua_State *L, const TValue *p1,
                                                   const TValue *p2);
 LUAI_FUNC l_noret luaG_opinterror (lua_State *L, const TValue *p1,

src/ldo.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.c,v 2.202 2018/05/30 14:25:52 roberto Exp $
+** $Id: ldo.c $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */

@@ -88,17 +88,20 @@
 };
 
 
-static void seterrorobj (lua_State *L, int errcode, StkId oldtop) {
+void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) {
   switch (errcode) {
     case LUA_ERRMEM: {  /* memory error? */
-      TString *memerrmsg = luaS_newliteral(L, MEMERRMSG);
-      setsvalue2s(L, oldtop, memerrmsg); /* reuse preregistered msg. */
+      setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */
       break;
     }
     case LUA_ERRERR: {
       setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling"));
       break;
     }
+    case CLOSEPROTECT: {
+      setnilvalue(s2v(oldtop));  /* no error message */
+      break;
+    }
     default: {
       setobjs2s(L, oldtop, L->top - 1);  /* error message on current top */
       break;

@@ -115,6 +118,7 @@
   }
   else {  /* thread has no error handler */
     global_State *g = G(L);
+    errcode = luaF_close(L, L->stack, errcode);  /* close all upvalues */
     L->status = cast_byte(errcode);  /* mark it as dead */
     if (g->mainthread->errorJmp) {  /* main thread has a handler? */
       setobjs2s(L, g->mainthread->top++, L->top - 1);  /* copy error obj. */

@@ -122,7 +126,7 @@
     }
     else {  /* no handler at all; abort */
       if (g->panic) {  /* panic function? */
-        seterrorobj(L, errcode, L->top);  /* assume EXTRA_STACK */
+        luaD_seterrorobj(L, errcode, L->top);  /* assume EXTRA_STACK */
         if (L->ci->top < L->top)
           L->ci->top = L->top;  /* pushing msg. can break this invariant */
         lua_unlock(L);

@@ -135,8 +139,9 @@
 
 
 int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
-  unsigned short oldnCcalls = L->nCcalls - L->nci;
+  l_uint32 oldnCcalls = L->nCcalls - L->nci;
   struct lua_longjmp lj;
+  lua_assert(L->nCcalls >= L->nci);
   lj.status = LUA_OK;
   lj.previous = L->errorJmp;  /* chain new error handler */
   L->errorJmp = &lj;

@@ -366,32 +371,40 @@
 ** separated.
 */
 static void moveresults (lua_State *L, StkId res, int nres, int wanted) {
+  StkId firstresult;
+  int i;
   switch (wanted) {  /* handle typical cases separately */
     case 0:  /* no values needed */
       L->top = res;
-      break;
+      return;
     case 1:  /* one value needed */
       if (nres == 0)   /* no results? */
         setnilvalue(s2v(res));  /* adjust with nil */
       else
         setobjs2s(L, res, L->top - nres);  /* move it to proper place */
       L->top = res + 1;
-      break;
+      return;
     case LUA_MULTRET:
       wanted = nres;  /* we want all results */
-      /* FALLTHROUGH */
-    default: {  /* multiple results */
-      StkId firstresult = L->top - nres;  /* index of first result */
-      int i;
-      /* move all results to correct place */
-      for (i = 0; i < nres && i < wanted; i++)
-        setobjs2s(L, res + i, firstresult + i);
-      for (; i < wanted; i++)  /* complete wanted number of results */
-        setnilvalue(s2v(res + i));
-      L->top = res + wanted;  /* top points after the last result */
       break;
-    }
+    default:  /* multiple results (or to-be-closed variables) */
+      if (hastocloseCfunc(wanted)) {  /* to-be-closed variables? */
+        ptrdiff_t savedres = savestack(L, res);
+        luaF_close(L, res, LUA_OK);  /* may change the stack */
+        res = restorestack(L, savedres);
+        wanted = codeNresults(wanted);  /* correct value */
+        if (wanted == LUA_MULTRET)
+          wanted = nres;
+      }
+      break;
   }
+  firstresult = L->top - nres;  /* index of first result */
+  /* move all results to correct place */
+  for (i = 0; i < nres && i < wanted; i++)
+    setobjs2s(L, res + i, firstresult + i);
+  for (; i < wanted; i++)  /* complete wanted number of results */
+    setnilvalue(s2v(res + i));
+  L->top = res + wanted;  /* top points after the last result */
 }
 
 

@@ -501,12 +514,17 @@
 
 
 /*
-** Similar to 'luaD_call', but does not allow yields during the call
+** Similar to 'luaD_call', but does not allow yields during the call.
+** If there is a stack overflow, freeing all CI structures will
+** force the subsequent call to invoke 'luaE_extendCI', which then
+** will raise any errors.
 */
 void luaD_callnoyield (lua_State *L, StkId func, int nResults) {
-  L->nny++;
+  incXCcalls(L);
+  if (getCcalls(L) >= LUAI_MAXCSTACK)  /* possible stack overflow? */
+    luaE_freeCI(L);
   luaD_call(L, func, nResults);
-  L->nny--;
+  decXCcalls(L);
 }
 
 

@@ -518,7 +536,7 @@
   CallInfo *ci = L->ci;
   int n;
   /* must have a continuation and must be able to call it */
-  lua_assert(ci->u.c.k != NULL && L->nny == 0);
+  lua_assert(ci->u.c.k != NULL && yieldable(L));
   /* error status can only happen in a protected call */
   lua_assert((ci->callstatus & CIST_YPCALL) || status == LUA_YIELD);
   if (ci->callstatus & CIST_YPCALL) {  /* was inside a pcall? */

@@ -584,11 +602,11 @@
   if (ci == NULL) return 0;  /* no recovery point */
   /* "finish" luaD_pcall */
   oldtop = restorestack(L, ci->u2.funcidx);
-  luaF_close(L, oldtop);
-  seterrorobj(L, status, oldtop);
+  luaF_close(L, oldtop, status);  /* may change the stack */
+  oldtop = restorestack(L, ci->u2.funcidx);
+  luaD_seterrorobj(L, status, oldtop);
   L->ci = ci;
   L->allowhook = getoah(ci->callstatus);  /* restore original 'allowhook' */
-  L->nny = 0;  /* should be zero to be yieldable */
   luaD_shrinkstack(L);
   L->errfunc = ci->u.c.old_errfunc;
   return 1;  /* continue running the coroutine */

@@ -641,50 +659,48 @@
   }
 }
 
-
 LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs,
                                       int *nresults) {
   int status;
-  unsigned short oldnny = L->nny;  /* save "number of non-yieldable" calls */
   lua_lock(L);
   if (L->status == LUA_OK) {  /* may be starting a coroutine */
     if (L->ci != &L->base_ci)  /* not in base level? */
       return resume_error(L, "cannot resume non-suspended coroutine", nargs);
+    else if (L->top - (L->ci->func + 1) == nargs)  /* no function? */
+      return resume_error(L, "cannot resume dead coroutine", nargs);
   }
-  else if (L->status != LUA_YIELD)
+  else if (L->status != LUA_YIELD)  /* ended with errors? */
     return resume_error(L, "cannot resume dead coroutine", nargs);
-  L->nCcalls = (from) ? from->nCcalls + 1 : 1;
-  if (L->nCcalls >= LUAI_MAXCCALLS)
+  if (from == NULL)
+    L->nCcalls = 1;
+  else  /* correct 'nCcalls' for this thread */
+    L->nCcalls = getCcalls(from) - from->nci + L->nci + CSTACKCF;
+  if (L->nCcalls >= LUAI_MAXCSTACK)
     return resume_error(L, "C stack overflow", nargs);
   luai_userstateresume(L, nargs);
-  L->nny = 0;  /* allow yields */
   api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs);
   status = luaD_rawrunprotected(L, resume, &nargs);
-  if (unlikely(status == -1))  /* error calling 'lua_resume'? */
-    status = LUA_ERRRUN;
-  else {  /* continue running after recoverable errors */
-    while (errorstatus(status) && recover(L, status)) {
-      /* unroll continuation */
-      status = luaD_rawrunprotected(L, unroll, &status);
-    }
-    if (unlikely(errorstatus(status))) {  /* unrecoverable error? */
-      L->status = cast_byte(status);  /* mark thread as 'dead' */
-      seterrorobj(L, status, L->top);  /* push error message */
-      L->ci->top = L->top;
-    }
-    else lua_assert(status == L->status);  /* normal end or yield */
+   /* continue running after recoverable errors */
+  while (errorstatus(status) && recover(L, status)) {
+    /* unroll continuation */
+    status = luaD_rawrunprotected(L, unroll, &status);
+  }
+  if (likely(!errorstatus(status)))
+    lua_assert(status == L->status);  /* normal end or yield */
+  else {  /* unrecoverable error */
+    L->status = cast_byte(status);  /* mark thread as 'dead' */
+    luaD_seterrorobj(L, status, L->top);  /* push error message */
+    L->ci->top = L->top;
   }
   *nresults = (status == LUA_YIELD) ? L->ci->u2.nyield
                                     : cast_int(L->top - (L->ci->func + 1));
-  L->nny = oldnny;  /* restore 'nny' */
-  L->nCcalls--;
   lua_unlock(L);
   return status;
 }
 
 
 LUA_API int lua_isyieldable (lua_State *L) {
-  return (L->nny == 0);
+  return yieldable(L);
 }
 
 

@@ -694,7 +710,7 @@
   luai_userstateyield(L, nresults);
   lua_lock(L);
   api_checknelems(L, nresults);
-  if (unlikely(L->nny > 0)) {
+  if (unlikely(!yieldable(L))) {
     if (L != G(L)->mainthread)
       luaG_runerror(L, "attempt to yield across a C-call boundary");
     else

@@ -718,22 +734,26 @@
 }
 
 
+/*
+** Call the C function 'func' in protected mode, restoring basic
+** thread information ('allowhook', etc.) and in particular
+** its stack level in case of errors.
+*/
 int luaD_pcall (lua_State *L, Pfunc func, void *u,
                 ptrdiff_t old_top, ptrdiff_t ef) {
   int status;
   CallInfo *old_ci = L->ci;
   lu_byte old_allowhooks = L->allowhook;
-  unsigned short old_nny = L->nny;
   ptrdiff_t old_errfunc = L->errfunc;
   L->errfunc = ef;
   status = luaD_rawrunprotected(L, func, u);
   if (unlikely(status != LUA_OK)) {  /* an error occurred? */
     StkId oldtop = restorestack(L, old_top);
-    luaF_close(L, oldtop);  /* close possible pending closures */
-    seterrorobj(L, status, oldtop);
     L->ci = old_ci;
     L->allowhook = old_allowhooks;
-    L->nny = old_nny;
+    status = luaF_close(L, oldtop, status);
+    oldtop = restorestack(L, old_top);  /* previous call may change stack */
+    luaD_seterrorobj(L, status, oldtop);
     luaD_shrinkstack(L);
   }
   L->errfunc = old_errfunc;

@@ -784,7 +804,7 @@
                                         const char *mode) {
   struct SParser p;
   int status;
-  L->nny++;  /* cannot yield during parsing */
+  incnny(L);  /* cannot yield during parsing */
   p.z = z; p.name = name; p.mode = mode;
   p.dyd.actvar.arr = NULL; p.dyd.actvar.size = 0;
   p.dyd.gt.arr = NULL; p.dyd.gt.size = 0;

@@ -795,7 +815,7 @@
   luaM_freearray(L, p.dyd.actvar.arr, p.dyd.actvar.size);
   luaM_freearray(L, p.dyd.gt.arr, p.dyd.gt.size);
   luaM_freearray(L, p.dyd.label.arr, p.dyd.label.size);
-  L->nny--;
+  decnny(L);
   return status;
 }
 

src/ldo.h

@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.h,v 2.44 2018/05/22 12:02:36 roberto Exp $
+** $Id: ldo.h $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */

@@ -50,6 +50,7 @@
 /* type of protected functions, to be ran by 'runprotected' */
 typedef void (*Pfunc) (lua_State *L, void *ud);
 
+LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop);
 LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name,
                                                   const char *mode);
 LUAI_FUNC void luaD_hook (lua_State *L, int event, int line,

src/ldump.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldump.c,v 2.41 2018/02/26 14:16:05 roberto Exp $
+** $Id: ldump.c $
 ** save precompiled Lua chunks
 ** See Copyright Notice in lua.h
 */

@@ -198,11 +198,9 @@
 
 static void DumpHeader (DumpState *D) {
   DumpLiteral(LUA_SIGNATURE, D);
-  DumpByte(LUAC_VERSION, D);
+  DumpInt(LUAC_VERSION, D);
   DumpByte(LUAC_FORMAT, D);
   DumpLiteral(LUAC_DATA, D);
-  DumpByte(sizeof(int), D);
-  DumpByte(sizeof(size_t), D);
   DumpByte(sizeof(Instruction), D);
   DumpByte(sizeof(lua_Integer), D);
   DumpByte(sizeof(lua_Number), D);

src/lfunc.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lfunc.c,v 2.51 2017/06/29 15:06:44 roberto Exp $
+** $Id: lfunc.c $
 ** Auxiliary functions to manipulate prototypes and closures
 ** See Copyright Notice in lua.h
 */

@@ -14,6 +14,8 @@
 
 #include "lua.h"
 
+#include "ldebug.h"
+#include "ldo.h"
 #include "lfunc.h"
 #include "lgc.h"
 #include "lmem.h"

@@ -39,6 +41,7 @@
   return c;
 }
 
+
 /*
 ** fill a closure with new closed upvalues
 */

@@ -55,31 +58,131 @@
 }
 
 
+/*
+** Create a new upvalue with the given tag at the given level,
+** and link it to the list of open upvalues of 'L' after entry 'prev'.
+**/
+static UpVal *newupval (lua_State *L, int tag, StkId level, UpVal **prev) {
+  GCObject *o = luaC_newobj(L, tag, sizeof(UpVal));
+  UpVal *uv = gco2upv(o);
+  UpVal *next = *prev;
+  uv->v = s2v(level);  /* current value lives in the stack */
+  uv->u.open.next = next;  /* link it to list of open upvalues */
+  uv->u.open.previous = prev;
+  if (next)
+    next->u.open.previous = &uv->u.open.next;
+  *prev = uv;
+  if (!isintwups(L)) {  /* thread not in list of threads with upvalues? */
+    L->twups = G(L)->twups;  /* link it to the list */
+    G(L)->twups = L;
+  }
+  return uv;
+}
+
+
+/*
+** Find and reuse, or create if it does not exist, a regular upvalue
+** at the given level.
+*/
 UpVal *luaF_findupval (lua_State *L, StkId level) {
   UpVal **pp = &L->openupval;
-  GCObject *o;
   UpVal *p;
-  UpVal *uv;
   lua_assert(isintwups(L) || L->openupval == NULL);
-  while ((p = *pp) != NULL && uplevel(p) >= level) {
+  while ((p = *pp) != NULL && uplevel(p) >= level) {  /* search for it */
     if (uplevel(p) == level && !isdead(G(L), p))  /* corresponding upvalue? */
       return p;  /* return it */
     pp = &p->u.open.next;
   }
-  /* not found: create a new upvalue between 'pp' and 'p' */
-  o = luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal));
-  uv = gco2upv(o);
-  uv->u.open.next = p;  /* link it to list of open upvalues */
-  uv->u.open.previous = pp;
-  if (p)
-    p->u.open.previous = &uv->u.open.next;
-  *pp = uv;
-  uv->v = s2v(level);  /* current value lives in the stack */
-  if (!isintwups(L)) {  /* thread not in list of threads with upvalues? */
-    L->twups = G(L)->twups;  /* link it to the list */
-    G(L)->twups = L;
+  /* not found: create a new upvalue after 'pp' */
+  return newupval(L, LUA_TUPVAL, level, pp);
+}
+
+
+static void callclose (lua_State *L, void *ud) {
+  UNUSED(ud);
+  luaD_callnoyield(L, L->top - 3, 0);
+}
+
+
+/*
+** Prepare closing method plus its arguments for object 'obj' with
+** error message 'err'. (This function assumes EXTRA_STACK.)
+*/
+static int prepclosingmethod (lua_State *L, TValue *obj, TValue *err) {
+  StkId top = L->top;
+  const TValue *tm = luaT_gettmbyobj(L, obj, TM_CLOSE);
+  if (ttisnil(tm))  /* no metamethod? */
+    return 0;  /* nothing to call */
+  setobj2s(L, top, tm);  /* will call metamethod... */
+  setobj2s(L, top + 1, obj);  /* with 'self' as the 1st argument */
+  setobj2s(L, top + 2, err);  /* and error msg. as 2nd argument */
+  L->top = top + 3;  /* add function and arguments */
+  return 1;
+}
+
+
+/*
+** Prepare and call a closing method. If status is OK, code is still
+** inside the original protected call, and so any error will be handled
+** there. Otherwise, a previous error already activated original
+** protected call, and so the call to the closing method must be
+** protected here. (A status = CLOSEPROTECT behaves like a previous
+** error, to also run the closing method in protected mode).
+** If status is OK, the call to the closing method will be pushed
+** at the top of the stack. Otherwise, values are pushed after
+** the 'level' of the upvalue being closed, as everything after
+** that won't be used again.
+*/
+static int callclosemth (lua_State *L, TValue *uv, StkId level, int status) {
+  if (likely(status == LUA_OK)) {
+    if (prepclosingmethod(L, uv, &G(L)->nilvalue))  /* something to call? */
+      callclose(L, NULL);  /* call closing method */
+    else if (!ttisnil(uv)) {  /* non-closable non-nil value? */
+      int idx = cast_int(level - L->ci->func);
+      const char *vname = luaG_findlocal(L, L->ci, idx, NULL);
+      if (vname == NULL) vname = "?";
+      luaG_runerror(L, "attempt to close non-closable variable '%s'", vname);
+    }
+  }
+  else {  /* there was an error */
+    /* save error message and set stack top to 'level + 1' */
+    luaD_seterrorobj(L, status, level);
+    if (prepclosingmethod(L, uv, s2v(level))) {  /* something to call? */
+      int newstatus = luaD_pcall(L, callclose, NULL, savestack(L, level), 0);
+      if (newstatus != LUA_OK)  /* another error when closing? */
+        status = newstatus;  /* this will be the new error */
+    }
+    /* else no metamethod; ignore this case and keep original error */
+  }
+  return status;
+}
+
+
+/*
+** Try to create a to-be-closed upvalue
+** (can raise a memory-allocation error)
+*/
+static void trynewtbcupval (lua_State *L, void *ud) {
+  StkId level = cast(StkId, ud);
+  lua_assert(L->openupval == NULL || uplevel(L->openupval) < level);
+  newupval(L, LUA_TUPVALTBC, level, &L->openupval);
+}
+
+
+/*
+** Create a to-be-closed upvalue. If there is a memory error
+** when creating the upvalue, the closing method must be called here,
+** as there is no upvalue to call it later.
+*/
+void luaF_newtbcupval (lua_State *L, StkId level) {
+  int status = luaD_rawrunprotected(L, trynewtbcupval, level);
+  if (unlikely(status != LUA_OK)) {  /* memory error creating upvalue? */
+    lua_assert(status == LUA_ERRMEM);
+    luaD_seterrorobj(L, LUA_ERRMEM, level + 1);  /* save error message */
+    if (prepclosingmethod(L, s2v(level), s2v(level + 1)))
+      callclose(L, NULL);  /* call closing method */
+    luaD_throw(L, LUA_ERRMEM);  /* throw memory error */
   }
-  return uv;
 }
 
 

@@ -91,10 +194,10 @@
 }
 
 
-void luaF_close (lua_State *L, StkId level) {
+int luaF_close (lua_State *L, StkId level, int status) {
   UpVal *uv;
-  while (L->openupval != NULL &&
-        (uv = L->openupval, uplevel(uv) >= level)) {
+  while ((uv = L->openupval) != NULL && uplevel(uv) >= level) {
+    StkId upl = uplevel(uv);
     TValue *slot = &uv->u.value;  /* new position for value */
     luaF_unlinkupval(uv);
     setobj(L, slot, uv->v);  /* move value to upvalue slot */

@@ -102,7 +205,14 @@
     if (!iswhite(uv))
       gray2black(uv);  /* closed upvalues cannot be gray */
     luaC_barrier(L, uv, slot);
+    if (uv->tt == LUA_TUPVALTBC && status != NOCLOSINGMETH) {
+      /* must run closing method */
+      ptrdiff_t levelrel = savestack(L, level);
+      status = callclosemth(L, uv->v, upl, status);  /* may change the stack */
+      level = restorestack(L, levelrel);
+    }
   }
+  return status;
 }
 
 

@@ -114,8 +224,6 @@
   f->p = NULL;
   f->sizep = 0;
   f->code = NULL;
-  f->cache = NULL;
-  f->cachemiss = 0;
   f->sizecode = 0;
   f->lineinfo = NULL;
   f->sizelineinfo = 0;

src/lfunc.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lfunc.h,v 2.20 2018/02/25 13:40:00 roberto Exp $
+** $Id: lfunc.h $
 ** Auxiliary functions to manipulate prototypes and closures
 ** See Copyright Notice in lua.h
 */

@@ -42,12 +42,24 @@
 #define MAXMISS		10
 
 
+/*
+** Special "status" for 'luaF_close'
+*/
+
+/* close upvalues without running their closing methods */
+#define NOCLOSINGMETH	(-1)
+
+/* close upvalues running all closing methods in protected mode */
+#define CLOSEPROTECT	(-2)
+
+
 LUAI_FUNC Proto *luaF_newproto (lua_State *L);
 LUAI_FUNC CClosure *luaF_newCclosure (lua_State *L, int nelems);
 LUAI_FUNC LClosure *luaF_newLclosure (lua_State *L, int nelems);
 LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl);
 LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level);
-LUAI_FUNC void luaF_close (lua_State *L, StkId level);
+LUAI_FUNC void luaF_newtbcupval (lua_State *L, StkId level);
+LUAI_FUNC int luaF_close (lua_State *L, StkId level, int status);
 LUAI_FUNC void luaF_unlinkupval (UpVal *uv);
 LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f);
 LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number,

src/lgc.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.c,v 2.254 2018/06/15 14:14:20 roberto Exp $
+** $Id: lgc.c $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */

@@ -12,6 +12,7 @@
 #include <stdio.h>
 #include <string.h>
 
+
 #include "lua.h"
 
 #include "ldebug.h"

@@ -100,6 +101,7 @@
 
 static void reallymarkobject (global_State *g, GCObject *o);
 static lu_mem atomic (lua_State *L);
+static void entersweep (lua_State *L);
 
 
 /*

@@ -180,9 +182,13 @@
 
 /*
 ** barrier that moves collector forward, that is, mark the white object
-** being pointed by a black object. (If in sweep phase, clear the black
-** object to white [sweep it] to avoid other barrier calls for this
-** same object.)
+** 'v' being pointed by the black object 'o'. (If in sweep phase, clear
+** the black object to white [sweep it] to avoid other barrier calls for
+** this same object.) In the generational mode, 'v' must also become
+** old, if 'o' is old; however, it cannot be changed directly to OLD,
+** because it may still point to non-old objects. So, it is marked as
+** OLD0. In the next cycle it will become OLD1, and in the next it
+** will finally become OLD (regular old).
 */
 void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) {
   global_State *g = G(L);

@@ -211,31 +217,11 @@
   lua_assert(g->gckind != KGC_GEN || (isold(o) && getage(o) != G_TOUCHED1));
   if (getage(o) != G_TOUCHED2)  /* not already in gray list? */
     linkobjgclist(o, g->grayagain);  /* link it in 'grayagain' */
-  black2gray(o);  /* make table gray (again) */
+  black2gray(o);  /* make object gray (again) */
   setage(o, G_TOUCHED1);  /* touched in current cycle */
 }
 
 
-/*
-** Barrier for prototype's cache of closures.  For an 'old1'
-** object, making it gray stops it from being visited by 'markold',
-** so it is linked in the 'grayagain' list to ensure it will be
-** visited. Otherwise, it goes to 'protogray', as only its 'cache' field
-** needs to be revisited.  (A prototype to be in this barrier must be
-** already finished, so its other fields cannot change and do not need
-** to be revisited.)
-*/
-LUAI_FUNC void luaC_protobarrier_ (lua_State *L, Proto *p) {
-  global_State *g = G(L);
-  lua_assert(g->gckind != KGC_GEN || isold(p));
-  if (getage(p) == G_OLD1)  /* still need to be visited? */
-    linkgclist(p, g->grayagain);  /* link it in 'grayagain' */
-  else
-    linkgclist(p, g->protogray);  /* link it in 'protogray' */
-  black2gray(p);  /* make prototype gray (to avoid other barriers) */
-}
-
-
 void luaC_fix (lua_State *L, GCObject *o) {
   global_State *g = G(L);
   lua_assert(g->allgc == o);  /* object must be 1st in 'allgc' list! */

@@ -287,7 +273,8 @@
       gray2black(o);
       break;
     }
-    case LUA_TUPVAL: {
+    case LUA_TUPVAL:
+    case LUA_TUPVALTBC: {
       UpVal *uv = gco2upv(o);
       if (!upisopen(uv))  /* open upvalues are kept gray */
         gray2black(o);

@@ -372,7 +359,7 @@
 */
 static void restartcollection (global_State *g) {
   g->gray = g->grayagain = NULL;
-  g->weak = g->allweak = g->ephemeron = g->protogray = NULL;
+  g->weak = g->allweak = g->ephemeron = NULL;
   markobject(g, g->mainthread);
   markvalue(g, &g->l_registry);
   markmt(g);

@@ -514,29 +501,16 @@
 }
 
 
-/*
-** Check the cache of a prototype, to keep invariants. If the
-** cache is white, clear it. (A cache should not prevent the
-** collection of its reference.) Otherwise, if in generational
-** mode, check the generational invariant. If the cache is old,
-** everything is ok. If the prototype is 'old0', everything
-** is ok too. (It will naturally be visited again.) If the
-** prototype is older than 'old0', then its cache (which is new)
-** must be visited again in the next collection, so the prototype
-** goes to the 'protogray' list. (If the prototype has a cache,
-** it is already immutable and does not need other barriers;
-** then, it can become gray without problems for its other fields.)
-*/
-static void checkprotocache (global_State *g, Proto *p) {
-  if (p->cache) {
-    if (iswhite(p->cache))
-      p->cache = NULL;  /* allow cache to be collected */
-    else if (g->gckind == KGC_GEN && !isold(p->cache) && getage(p) >= G_OLD1) {
-      linkgclist(p, g->protogray);  /* link it in 'protogray' */
-      black2gray(p);  /* make prototype gray */
-    }
+static int traverseudata (global_State *g, Udata *u) {
+  int i;
+  markobjectN(g, u->metatable);  /* mark its metatable */
+  for (i = 0; i < u->nuvalue; i++)
+    markvalue(g, &u->uv[i].uv);
+  if (g->gckind == KGC_GEN) {
+    linkgclist(u, g->grayagain);  /* keep it in some gray list */
+    black2gray(u);
   }
-  p->cachemiss = 0;  /* restart counting */
+  return 1 + u->nuvalue;
 }
 
 

@@ -547,7 +521,6 @@
 */
 static int traverseproto (global_State *g, Proto *f) {
   int i;
-  checkprotocache(g, f);
   markobjectN(g, f->source);
   for (i = 0; i < f->sizek; i++)  /* mark literals */
     markvalue(g, &f->k[i]);

@@ -589,6 +562,7 @@
 ** That ensures that the entire stack have valid (non-dead) objects.
 */
 static int traversethread (global_State *g, lua_State *th) {
+  UpVal *uv;
   StkId o = th->stack;
   if (o == NULL)
     return 1;  /* stack not completely built yet */

@@ -596,6 +570,10 @@
              th->openupval == NULL || isintwups(th));
   for (; o < th->top; o++)  /* mark live elements in the stack */
     markvalue(g, s2v(o));
+  for (uv = th->openupval; uv != NULL; uv = uv->u.open.next) {
+    if (uv->tt == LUA_TUPVALTBC)  /* to be closed? */
+      markobject(g, uv);  /* cannot be collected */
+  }
   if (g->gcstate == GCSatomic) {  /* final traversal? */
     StkId lim = th->stack + th->stacksize;  /* real end of stack */
     for (; o < lim; o++)  /* clear not-marked stack slice */

@@ -612,15 +590,6 @@
 }
 
 
-static int traverseudata (global_State *g, Udata *u) {
-  int i;
-  markobjectN(g, u->metatable);  /* mark its metatable */
-  for (i = 0; i < u->nuvalue; i++)
-    markvalue(g, &u->uv[i].uv);
-  return 1 + u->nuvalue;
-}
-
-
 /*
 ** traverse one gray object, turning it to black (except for threads,
 ** which are always gray).

@@ -680,19 +649,6 @@
 ** =======================================================
 */
 
-static void clearprotolist (global_State *g) {
-  GCObject *p = g->protogray;
-  g->protogray = NULL;
-  while (p != NULL) {
-    Proto *pp = gco2p(p);
-    GCObject *next = pp->gclist;
-    lua_assert(isgray(pp) && (pp->cache != NULL || pp->cachemiss >= MAXMISS));
-    gray2black(pp);
-    checkprotocache(g, pp);
-    p = next;
-  }
-}
-
 
 /*
 ** clear entries with unmarked keys from all weaktables in list 'l'

@@ -750,6 +706,7 @@
       luaF_freeproto(L, gco2p(o));
       break;
     case LUA_TUPVAL:
+    case LUA_TUPVALTBC:
       freeupval(L, gco2upv(o));
       break;
     case LUA_TLCL:

@@ -868,14 +825,14 @@
 }
 
 
-static void GCTM (lua_State *L, int propagateerrors) {
+static void GCTM (lua_State *L) {
   global_State *g = G(L);
   const TValue *tm;
   TValue v;
   lua_assert(!g->gcemergency);
   setgcovalue(L, &v, udata2finalize(g));
   tm = luaT_gettmbyobj(L, &v, TM_GC);
-  if (tm != NULL && ttisfunction(tm)) {  /* is there a finalizer? */
+  if (!notm(tm)) {  /* is there a finalizer? */
     int status;
     lu_byte oldah = L->allowhook;
     int running  = g->gcrunning;

@@ -889,15 +846,13 @@
     L->ci->callstatus &= ~CIST_FIN;  /* not running a finalizer anymore */
     L->allowhook = oldah;  /* restore hooks */
     g->gcrunning = running;  /* restore state */
-    if (status != LUA_OK && propagateerrors) {  /* error while running __gc? */
-      if (status == LUA_ERRRUN) {  /* is there an error object? */
-        const char *msg = (ttisstring(s2v(L->top - 1)))
-                            ? svalue(s2v(L->top - 1))
-                            : "no message";
-        luaO_pushfstring(L, "error in __gc metamethod (%s)", msg);
-        status = LUA_ERRGCMM;  /* error in __gc metamethod */
-      }
-      luaD_throw(L, status);  /* re-throw error */
+    if (status != LUA_OK) {  /* error while running __gc? */
+      const char *msg = (ttisstring(s2v(L->top - 1)))
+                        ? svalue(s2v(L->top - 1))
+                        : "error object is not a string";
+      luaE_warning(L, "error in __gc metamethod (", 1);
+      luaE_warning(L, msg, 1);
+      luaE_warning(L, ")", 0);
     }
   }
 }

@@ -910,7 +865,7 @@
   global_State *g = G(L);
   int i;
   for (i = 0; i < n && g->tobefnz; i++)
-    GCTM(L, 1);  /* call one finalizer */
+    GCTM(L);  /* call one finalizer */
   return i;
 }
 

@@ -918,10 +873,10 @@
 /*
 ** call all pending finalizers
 */
-static void callallpendingfinalizers (lua_State *L, int propagateerrors) {
+static void callallpendingfinalizers (lua_State *L) {
   global_State *g = G(L);
   while (g->tobefnz)
-    GCTM(L, propagateerrors);
+    GCTM(L);
 }
 
 

@@ -1004,6 +959,8 @@
 ** =======================================================
 */
 
+static void setpause (global_State *g);
+
 
 /* mask to erase all color bits, not changing gen-related stuff */
 #define maskgencolors	(~(bitmask(BLACKBIT) | WHITEBITS))

@@ -1078,9 +1035,9 @@
 
 
 /*
-** Correct a list of gray objects. Because this correction is
-** done after sweeping, young objects can be white and still
-** be in the list. They are only removed.
+** Correct a list of gray objects.
+** Because this correction is done after sweeping, young objects might
+** be turned white and still be in the list. They are only removed.
 ** For tables and userdata, advance 'touched1' to 'touched2'; 'touched2'
 ** objects become regular old and are removed from the list.
 ** For threads, just remove white ones from the list.

@@ -1097,13 +1054,14 @@
           changeage(curr, G_TOUCHED1, G_TOUCHED2);
           p = next;  /* go to next element */
         }
-        else {
-          if (!iswhite(curr)) {
+        else {  /* not touched in this cycle */
+          if (!iswhite(curr)) {  /* not white? */
             lua_assert(isold(curr));
-            if (getage(curr) == G_TOUCHED2)
-              changeage(curr, G_TOUCHED2, G_OLD);
+            if (getage(curr) == G_TOUCHED2)  /* advance from G_TOUCHED2... */
+              changeage(curr, G_TOUCHED2, G_OLD);  /* ... to G_OLD */
             gray2black(curr);  /* make it black */
           }
+          /* else, object is white: just remove it from this list */
           *p = *next;  /* remove 'curr' from gray list */
         }
         break;

@@ -1139,7 +1097,7 @@
 
 
 /*
-** Mark 'old1' objects when starting a new young collection.
+** Mark 'OLD1' objects when starting a new young collection.
 ** Gray objects are already in some gray list, and so will be visited
 ** in the atomic step.
 */

@@ -1165,14 +1123,14 @@
   checkSizes(L, g);
   g->gcstate = GCSpropagate;  /* skip restart */
   if (!g->gcemergency)
-    callallpendingfinalizers(L, 1);
+    callallpendingfinalizers(L);
 }
 
 
 /*
-** Does a young collection. First, mark 'old1' objects.  (Only survival
-** and "recent old" lists can contain 'old1' objects. New lists cannot
-** contain 'old1' objects, at most 'old0' objects that were already
+** Does a young collection. First, mark 'OLD1' objects.  (Only survival
+** and "recent old" lists can contain 'OLD1' objects. New lists cannot
+** contain 'OLD1' objects, at most 'OLD0' objects that were already
 ** visited when marked old.) Then does the atomic step. Then,
 ** sweep all lists and advance pointers. Finally, finish the collection.
 */

@@ -1205,15 +1163,7 @@
 }
 
 
-/*
-** Enter generational mode. Must go until the end of an atomic cycle
-** to ensure that all threads are in the gray list. Then, turn all
-** objects into old and finishes the collection.
-*/
-static void entergen (lua_State *L, global_State *g) {
-  luaC_runtilstate(L, bitmask(GCSpause));  /* prepare to start a new cycle */
-  luaC_runtilstate(L, bitmask(GCSpropagate));  /* start new cycle */
-  atomic(L);
+static void atomic2gen (lua_State *L, global_State *g) {
   /* sweep all elements making them old */
   sweep2old(L, &g->allgc);
   /* everything alive now is old */

@@ -1226,15 +1176,31 @@
   sweep2old(L, &g->tobefnz);
 
   g->gckind = KGC_GEN;
+  g->lastatomic = 0;
   g->GCestimate = gettotalbytes(g);  /* base for memory control */
   finishgencycle(L, g);
 }
 
 
 /*
+** Enter generational mode. Must go until the end of an atomic cycle
+** to ensure that all threads and weak tables are in the gray lists.
+** Then, turn all objects into old and finishes the collection.
+*/
+static lu_mem entergen (lua_State *L, global_State *g) {
+  lu_mem numobjs;
+  luaC_runtilstate(L, bitmask(GCSpause));  /* prepare to start a new cycle */
+  luaC_runtilstate(L, bitmask(GCSpropagate));  /* start new cycle */
+  numobjs = atomic(L);  /* propagates all and then do the atomic stuff */
+  atomic2gen(L, g);
+  return numobjs;
+}
+
+
+/*
 ** Enter incremental mode. Turn all objects white, make all
 ** intermediate lists point to NULL (to avoid invalid pointers),
-** and go to pause state.
+** and go to the pause state.
 */
 static void enterinc (global_State *g) {
   whitelist(g, g->allgc);

@@ -1244,6 +1210,7 @@
   g->finobjrold = g->finobjold = g->finobjsur = NULL;
   g->gcstate = GCSpause;
   g->gckind = KGC_INC;
+  g->lastatomic = 0;
 }
 
 

@@ -1258,40 +1225,114 @@
     else
       enterinc(g);  /* entering incremental mode */
   }
+  g->lastatomic = 0;
 }
 
 
 /*
 ** Does a full collection in generational mode.
 */
-static void fullgen (lua_State *L, global_State *g) {
+static lu_mem fullgen (lua_State *L, global_State *g) {
   enterinc(g);
-  entergen(L, g);
+  return entergen(L, g);
+}
+
+
+/*
+** Set debt for the next minor collection, which will happen when
+** memory grows 'genminormul'%.
+*/
+static void setminordebt (global_State *g) {
+  luaE_setdebt(g, -(cast(l_mem, (gettotalbytes(g) / 100)) * g->genminormul));
 }
 
 
 /*
-** Does a generational "step". If memory grows 'genmajormul'% larger
-** than last major collection (kept in 'g->GCestimate'), does a major
-** collection. Otherwise, does a minor collection and set debt to make
-** another collection when memory grows 'genminormul'% larger.
+** Does a major collection after last collection was a "bad collection".
+**
+** When the program is building a big struture, it allocates lots of
+** memory but generates very little garbage. In those scenarios,
+** the generational mode just wastes time doing small collections, and
+** major collections are frequently what we call a "bad collection", a
+** collection that frees too few objects. To avoid the cost of switching
+** between generational mode and the incremental mode needed for full
+** (major) collections, the collector tries to stay in incremental mode
+** after a bad collection, and to switch back to generational mode only
+** after a "good" collection (one that traverses less than 9/8 objects
+** of the previous one).
+** The collector must choose whether to stay in incremental mode or to
+** switch back to generational mode before sweeping. At this point, it
+** does not know the real memory in use, so it cannot use memory to
+** decide whether to return to generational mode. Instead, it uses the
+** number of objects traversed (returned by 'atomic') as a proxy. The
+** field 'g->lastatomic' keeps this count from the last collection.
+** ('g->lastatomic != 0' also means that the last collection was bad.)
+*/
+static void stepgenfull (lua_State *L, global_State *g) {
+  lu_mem newatomic;  /* count of traversed objects */
+  lu_mem lastatomic = g->lastatomic;  /* count from last collection */
+  if (g->gckind == KGC_GEN)  /* still in generational mode? */
+    enterinc(g);  /* enter incremental mode */
+  luaC_runtilstate(L, bitmask(GCSpropagate));  /* start new cycle */
+  newatomic = atomic(L);  /* mark everybody */
+  if (newatomic < lastatomic + (lastatomic >> 3)) {  /* good collection? */
+    atomic2gen(L, g);  /* return to generational mode */
+    setminordebt(g);
+  }
+  else {  /* another bad collection; stay in incremental mode */
+    g->GCestimate = gettotalbytes(g);  /* first estimate */;
+    entersweep(L);
+    luaC_runtilstate(L, bitmask(GCSpause));  /* finish collection */
+    setpause(g);
+    g->lastatomic = newatomic;
+  }
+}
+
+
+/*
+** Does a generational "step".
+** Usually, this means doing a minor collection and setting the debt to
+** make another collection when memory grows 'genminormul'% larger.
+**
+** However, there are exceptions.  If memory grows 'genmajormul'%
+** larger than it was at the end of the last major collection (kept
+** in 'g->GCestimate'), the function does a major collection. At the
+** end, it checks whether the major collection was able to free a
+** decent amount of memory (at least half the growth in memory since
+** previous major collection). If so, the collector keeps its state,
+** and the next collection will probably be minor again. Otherwise,
+** we have what we call a "bad collection". In that case, set the field
+** 'g->lastatomic' to signal that fact, so that the next collection will
+** go to 'stepgenfull'.
+**
 ** 'GCdebt <= 0' means an explicit call to GC step with "size" zero;
-** in that case, always do a minor collection.
+** in that case, do a minor collection.
 */
 static void genstep (lua_State *L, global_State *g) {
-  lu_mem majorbase = g->GCestimate;
-  int majormul = getgcparam(g->genmajormul);
-  if (g->GCdebt > 0 &&
-      gettotalbytes(g) > (majorbase / 100) * (100 + majormul)) {
-    fullgen(L, g);
-  }
+  if (g->lastatomic != 0)  /* last collection was a bad one? */
+    stepgenfull(L, g);  /* do a full step */
   else {
-    lu_mem mem;
-    youngcollection(L, g);
-    mem = gettotalbytes(g);
-    luaE_setdebt(g, -(cast(l_mem, (mem / 100)) * g->genminormul));
-    g->GCestimate = majorbase;  /* preserve base value */
+    lu_mem majorbase = g->GCestimate;  /* memory after last major collection */
+    lu_mem majorinc = (majorbase / 100) * getgcparam(g->genmajormul);
+    if (g->GCdebt > 0 && gettotalbytes(g) > majorbase + majorinc) {
+      lu_mem numobjs = fullgen(L, g);  /* do a major collection */
+      if (gettotalbytes(g) < majorbase + (majorinc / 2)) {
+        /* collected at least half of memory growth since last major
+           collection; keep doing minor collections */
+        setminordebt(g);
+      }
+      else {  /* bad collection */
+        g->lastatomic = numobjs;  /* signal that last collection was bad */
+        setpause(g);  /* do a long wait for next (major) collection */
+      }
+    }
+    else {  /* regular case; do a minor collection */
+      youngcollection(L, g);
+      setminordebt(g);
+      g->GCestimate = majorbase;  /* preserve base value */
+    }
   }
+  lua_assert(isdecGCmodegen(g));
 }
 
 /* }====================================================== */

@@ -1361,7 +1402,7 @@
   luaC_changemode(L, KGC_INC);
   separatetobefnz(g, 1);  /* separate all objects with finalizers */
   lua_assert(g->finobj == NULL);
-  callallpendingfinalizers(L, 0);
+  callallpendingfinalizers(L);
   deletelist(L, g->allgc, obj2gco(g->mainthread));
   deletelist(L, g->finobj, NULL);
   deletelist(L, g->fixedgc, NULL);  /* collect fixed objects */

@@ -1382,6 +1423,7 @@
   /* registry and global metatables may be changed by API */
   markvalue(g, &g->l_registry);
   markmt(g);  /* mark global metatables */
+  work += propagateall(g);  /* empties 'gray' list */
   /* remark occasional upvalues of (maybe) dead threads */
   work += remarkupvals(g);
   work += propagateall(g);  /* propagate changes */

@@ -1405,7 +1447,6 @@
   clearbyvalues(g, g->weak, origweak);
   clearbyvalues(g, g->allweak, origall);
   luaS_clearcache(g);
-  clearprotolist(g);
   g->currentwhite = cast_byte(otherwhite(g));  /* flip current white */
   lua_assert(g->gray == NULL);
   return work;  /* estimate of slots marked by 'atomic' */

@@ -1446,8 +1487,7 @@
         return propagatemark(g);  /* traverse one gray object */
     }
     case GCSenteratomic: {
-      lu_mem work = propagateall(g);  /* make sure gray list is empty */
-      work += atomic(L);  /* work is what was traversed by 'atomic' */
+      lu_mem work = atomic(L);  /* work is what was traversed by 'atomic' */
       entersweep(L);
       g->GCestimate = gettotalbytes(g);  /* first estimate */;
       return work;

@@ -1523,10 +1563,10 @@
 void luaC_step (lua_State *L) {
   global_State *g = G(L);
   if (g->gcrunning) {  /* running? */
-    if (g->gckind == KGC_INC)
-      incstep(L, g);
-    else
+    if(isdecGCmodegen(g))
       genstep(L, g);
+    else
+      incstep(L, g);
   }
 }
 

src/lgc.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.h,v 2.103 2018/06/11 14:19:50 roberto Exp $
+** $Id: lgc.h $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */

@@ -123,11 +123,11 @@
 #define LUAI_GENMINORMUL         20
 
 /* wait memory to double before starting new cycle */
-#define LUAI_GCPAUSE    200     /* 200% */
+#define LUAI_GCPAUSE    200
 
 /*
 ** some gc parameters are stored divided by 4 to allow a maximum value
-** larger than 1000 in a 'lu_byte'.
+** up to 1023 in a 'lu_byte'.
 */
 #define getgcparam(p)	((p) * 4)
 #define setgcparam(p,v)	((p) = (v) / 4)

@@ -139,6 +139,13 @@
 
 
 /*
+** Check whether the declared GC mode is generational. While in
+** generational mode, the collector can go temporarily to incremental
+** mode to improve performance. This is signaled by 'g->lastatomic != 0'.
+*/
+#define isdecGCmodegen(g)	(g->gckind == KGC_GEN || g->lastatomic != 0)
+
+/*
 ** Does one step of collection when debt becomes positive. 'pre'/'pos'
 ** allows some adjustments to be done only when needed. macro
 ** 'condchangemem' is used only for heavy tests (forcing a full

@@ -164,9 +171,6 @@
 	(isblack(p) && iswhite(o)) ? \
 	luaC_barrier_(L,obj2gco(p),obj2gco(o)) : cast_void(0))
 
-#define luaC_protobarrier(L,p,o) \
-	(isblack(p) ? luaC_protobarrier_(L,p) : cast_void(0))
-
 LUAI_FUNC void luaC_fix (lua_State *L, GCObject *o);
 LUAI_FUNC void luaC_freeallobjects (lua_State *L);
 LUAI_FUNC void luaC_step (lua_State *L);

@@ -175,7 +179,6 @@
 LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz);
 LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v);
 LUAI_FUNC void luaC_barrierback_ (lua_State *L, GCObject *o);
-LUAI_FUNC void luaC_protobarrier_ (lua_State *L, Proto *p);
 LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt);
 LUAI_FUNC void luaC_changemode (lua_State *L, int newmode);
 

src/linit.c

@@ -1,5 +1,5 @@
 /*
-** $Id: linit.c,v 1.41 2018/02/27 18:47:32 roberto Exp $
+** $Id: linit.c $
 ** Initialization of libraries for lua.c and other clients
 ** See Copyright Notice in lua.h
 */

src/liolib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: liolib.c,v 2.156 2018/03/02 18:25:00 roberto Exp $
+** $Id: liolib.c $
 ** Standard I/O (and system) library
 ** See Copyright Notice in lua.h
 */

@@ -39,7 +39,7 @@
 /* Check whether 'mode' matches '[rwa]%+?[L_MODEEXT]*' */
 static int l_checkmode (const char *mode) {
   return (*mode != '\0' && strchr("rwa", *(mode++)) != NULL &&
-         (*mode != '+' || (++mode, 1)) &&  /* skip if char is '+' */
+         (*mode != '+' || ((void)(++mode), 1)) &&  /* skip if char is '+' */
          (strspn(mode, L_MODEEXT) == strlen(mode)));  /* check extensions */
 }
 

@@ -68,7 +68,7 @@
 
 /* ISO C definitions */
 #define l_popen(L,c,m)  \
-	  ((void)((void)c, m), \
+	  ((void)c, (void)m, \
 	  luaL_error(L, "'popen' not supported"), \
 	  (FILE*)0)
 #define l_pclose(L,file)		((void)L, (void)file, -1)

@@ -133,6 +133,7 @@
 /* }====================================================== */
 
 
+
 #define IO_PREFIX	"_IO_"
 #define IOPREF_LEN	(sizeof(IO_PREFIX)/sizeof(char) - 1)
 #define IO_INPUT	(IO_PREFIX "input")

@@ -336,12 +337,22 @@
 */
 #define MAXARGLINE	250
 
+/*
+** Auxiliar function to create the iteration function for 'lines'.
+** The iteration function is a closure over 'io_readline', with
+** the following upvalues:
+** 1) The file being read (first value in the stack)
+** 2) the number of arguments to read
+** 3) a boolean, true iff file has to be closed when finished ('toclose')
+** *) a variable number of format arguments (rest of the stack)
+*/
 static void aux_lines (lua_State *L, int toclose) {
   int n = lua_gettop(L) - 1;  /* number of arguments to read */
   luaL_argcheck(L, n <= MAXARGLINE, MAXARGLINE + 2, "too many arguments");
+  lua_pushvalue(L, 1);  /* file */
   lua_pushinteger(L, n);  /* number of arguments to read */
   lua_pushboolean(L, toclose);  /* close/not close file when finished */
-  lua_rotate(L, 2, 2);  /* move 'n' and 'toclose' to their positions */
+  lua_rotate(L, 2, 3);  /* move the three values to their positions */
   lua_pushcclosure(L, io_readline, 3 + n);
 }
 

@@ -353,6 +364,11 @@
 }
 
 
+/*
+** Return an iteration function for 'io.lines'. If file has to be
+** closed, also returns the file itself as a second result (to be
+** closed as the state at the exit of a generic for).
+*/
 static int io_lines (lua_State *L) {
   int toclose;
   if (lua_isnone(L, 1)) lua_pushnil(L);  /* at least one argument */

@@ -368,8 +384,15 @@
     lua_replace(L, 1);  /* put file at index 1 */
     toclose = 1;  /* close it after iteration */
   }
-  aux_lines(L, toclose);
-  return 1;
+  aux_lines(L, toclose);  /* push iteration function */
+  if (toclose) {
+    lua_pushnil(L);  /* state */
+    lua_pushnil(L);  /* control */
+    lua_pushvalue(L, 1);  /* file is the to-be-closed variable (4th result) */
+    return 4;
+  }
+  else
+    return 1;
 }
 
 

@@ -435,7 +458,7 @@
 /*
 ** Read a number: first reads a valid prefix of a numeral into a buffer.
 ** Then it calls 'lua_stringtonumber' to check whether the format is
-** correct and to convert it to a Lua number
+** correct and to convert it to a Lua number.
 */
 static int read_number (lua_State *L, FILE *f) {
   RN rn;

@@ -481,17 +504,17 @@
 
 static int read_line (lua_State *L, FILE *f, int chop) {
   luaL_Buffer b;
-  int c = '\0';
+  int c;
   luaL_buffinit(L, &b);
-  while (c != EOF && c != '\n') {  /* repeat until end of line */
-    char *buff = luaL_prepbuffer(&b);  /* preallocate buffer */
+  do {  /* may need to read several chunks to get whole line */
+    char *buff = luaL_prepbuffer(&b);  /* preallocate buffer space */
     int i = 0;
     l_lockfile(f);  /* no memory errors can happen inside the lock */
     while (i < LUAL_BUFFERSIZE && (c = l_getc(f)) != EOF && c != '\n')
-      buff[i++] = c;
+      buff[i++] = c;  /* read up to end of line or buffer limit */
     l_unlockfile(f);
     luaL_addsize(&b, i);
-  }
+  } while (c != EOF && c != '\n');  /* repeat until end of line */
   if (!chop && c == '\n')  /* want a newline and have one? */
     luaL_addchar(&b, c);  /* add ending newline to result */
   luaL_pushresult(&b);  /* close buffer */

@@ -586,6 +609,9 @@
 }
 
 
+/*
+** Iteration function for 'lines'.
+*/
 static int io_readline (lua_State *L) {
   LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1));
   int i;

@@ -606,8 +632,8 @@
       return luaL_error(L, "%s", lua_tostring(L, -n + 1));
     }
     if (lua_toboolean(L, lua_upvalueindex(3))) {  /* generator created file? */
-      lua_settop(L, 0);
-      lua_pushvalue(L, lua_upvalueindex(1));
+      lua_settop(L, 0);  /* clear stack */
+      lua_pushvalue(L, lua_upvalueindex(1));  /* push file at index 1 */
       aux_close(L);  /* close it */
     }
     return 0;

@@ -725,6 +751,7 @@
   {"setvbuf", f_setvbuf},
   {"write", f_write},
   {"__gc", f_gc},
+  {"__close", f_gc},
   {"__tostring", f_tostring},
   {NULL, NULL}
 };

src/ljumptab.h

@@ -1,3 +1,10 @@
+/*
+** $Id: ljumptab.h $
+** Jump Table for the Lua interpreter
+** See Copyright Notice in lua.h
+*/
+
+
 #undef vmdispatch
 #undef vmcase
 #undef vmbreak

@@ -9,7 +16,7 @@
 #define vmbreak		vmfetch(); vmdispatch(GET_OPCODE(i));
 
 
-static void *disptab[] = {
+static void *disptab[NUM_OPCODES] = {
 
 #if 0
 ** you can update the following list with this command:

@@ -44,6 +51,13 @@
 &&L_OP_POWI,
 &&L_OP_DIVI,
 &&L_OP_IDIVI,
+&&L_OP_ADDK,
+&&L_OP_SUBK,
+&&L_OP_MULK,
+&&L_OP_MODK,
+&&L_OP_POWK,
+&&L_OP_DIVK,
+&&L_OP_IDIVK,
 &&L_OP_BANDK,
 &&L_OP_BORK,
 &&L_OP_BXORK,

@@ -67,6 +81,7 @@
 &&L_OP_LEN,
 &&L_OP_CONCAT,
 &&L_OP_CLOSE,
+&&L_OP_TBC,
 &&L_OP_JMP,
 &&L_OP_EQ,
 &&L_OP_LT,

@@ -84,16 +99,15 @@
 &&L_OP_RETURN,
 &&L_OP_RETURN0,
 &&L_OP_RETURN1,
-&&L_OP_FORLOOP1,
-&&L_OP_FORPREP1,
 &&L_OP_FORLOOP,
 &&L_OP_FORPREP,
+&&L_OP_TFORPREP,
 &&L_OP_TFORCALL,
 &&L_OP_TFORLOOP,
 &&L_OP_SETLIST,
 &&L_OP_CLOSURE,
 &&L_OP_VARARG,
-&&L_OP_PREPVARARG,
+&&L_OP_VARARGPREP,
 &&L_OP_EXTRAARG
 
 };

src/llex.c

@@ -1,5 +1,5 @@
 /*
-** $Id: llex.c,v 2.102 2018/04/04 14:23:41 roberto Exp $
+** $Id: llex.c $
 ** Lexical Analyzer
 ** See Copyright Notice in lua.h
 */

@@ -82,7 +82,10 @@
 const char *luaX_token2str (LexState *ls, int token) {
   if (token < FIRST_RESERVED) {  /* single-byte symbols? */
     lua_assert(token == cast_uchar(token));
-    return luaO_pushfstring(ls->L, "'%c'", token);
+    if (lisprint(token))
+      return luaO_pushfstring(ls->L, "'%c'", token);
+    else  /* control character */
+      return luaO_pushfstring(ls->L, "'<\\%d>'", token);
   }
   else {
     const char *s = luaX_tokens[token - FIRST_RESERVED];

@@ -228,6 +231,8 @@
       save_and_next(ls);
     else break;
   }
+  if (lislalnum(ls->current))  /* is numeral touching an alpha num? */
+    save_and_next(ls);  /* force an error */
   save(ls, '\0');
   if (luaO_str2num(luaZ_buffer(ls->buff), &obj) == 0)  /* format error? */
     lexerror(ls, "malformed number", TK_FLT);

@@ -244,12 +249,12 @@
 
 
 /*
-** skip a sequence '[=*[' or ']=*]'; if sequence is well formed, return
-** its number of '='s; otherwise, return a negative number (-1 iff there
-** are no '='s after initial bracket)
+** reads a sequence '[=*[' or ']=*]', leaving the last bracket.
+** If sequence is well formed, return its number of '='s + 2; otherwise,
+** return 1 if there is no '='s or 0 otherwise (an unfinished '[==...').
 */
-static int skip_sep (LexState *ls) {
-  int count = 0;
+static size_t skip_sep (LexState *ls) {
+  size_t count = 0;
   int s = ls->current;
   lua_assert(s == '[' || s == ']');
   save_and_next(ls);

@@ -257,11 +262,13 @@
     save_and_next(ls);
     count++;
   }
-  return (ls->current == s) ? count : (-count) - 1;
+  return (ls->current == s) ? count + 2
+         : (count == 0) ? 1
+         : 0;
 }
 
 
-static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) {
+static void read_long_string (LexState *ls, SemInfo *seminfo, size_t sep) {
   int line = ls->linenumber;  /* initial line (for error message) */
   save_and_next(ls);  /* skip 2nd '[' */
   if (currIsNewline(ls))  /* string starts with a newline? */

@@ -295,8 +302,8 @@
     }
   } endloop:
   if (seminfo)
-    seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep),
-                                     luaZ_bufflen(ls->buff) - 2*(2 + sep));
+    seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + sep,
+                                     luaZ_bufflen(ls->buff) - 2 * sep);
 }
 
 

@@ -332,8 +339,8 @@
   r = gethexa(ls);  /* must have at least one digit */
   while ((save_and_next(ls), lisxdigit(ls->current))) {
     i++;
+    esccheck(ls, r <= (0x7FFFFFFFu >> 4), "UTF-8 value too large");
     r = (r << 4) + luaO_hexavalue(ls->current);
-    esccheck(ls, r <= 0x10FFFF, "UTF-8 value too large");
   }
   esccheck(ls, ls->current == '}', "missing '}'");
   next(ls);  /* skip '}' */

@@ -444,9 +451,9 @@
         /* else is a comment */
         next(ls);
         if (ls->current == '[') {  /* long comment? */
-          int sep = skip_sep(ls);
+          size_t sep = skip_sep(ls);
           luaZ_resetbuffer(ls->buff);  /* 'skip_sep' may dirty the buffer */
-          if (sep >= 0) {
+          if (sep >= 2) {
             read_long_string(ls, NULL, sep);  /* skip long comment */
             luaZ_resetbuffer(ls->buff);  /* previous call may dirty the buff. */
             break;

@@ -458,12 +465,12 @@
         break;
       }
       case '[': {  /* long string or simply '[' */
-        int sep = skip_sep(ls);
-        if (sep >= 0) {
+        size_t sep = skip_sep(ls);
+        if (sep >= 2) {
           read_long_string(ls, seminfo, sep);
           return TK_STRING;
         }
-        else if (sep != -1)  /* '[=...' missing second bracket */
+        else if (sep == 0)  /* '[=...' missing second bracket? */
           lexerror(ls, "invalid long string delimiter", TK_STRING);
         return '[';
       }

src/llex.h

@@ -1,5 +1,5 @@
 /*
-** $Id: llex.h,v 1.82 2018/04/04 14:23:41 roberto Exp $
+** $Id: llex.h $
 ** Lexical Analyzer
 ** See Copyright Notice in lua.h
 */

src/llimits.h

@@ -1,5 +1,5 @@
 /*
-** $Id: llimits.h,v 1.151 2018/06/15 14:13:45 roberto Exp $
+** $Id: llimits.h $
 ** Limits, basic types, and some other 'installation-dependent' definitions
 ** See Copyright Notice in lua.h
 */

@@ -14,6 +14,7 @@
 
 #include "lua.h"
 
+
 /*
 ** 'lu_mem' and 'l_mem' are unsigned/signed integers big enough to count
 ** the total memory used by Lua (in bytes). Usually, 'size_t' and

@@ -22,7 +23,7 @@
 #if defined(LUAI_MEM)		/* { external definitions? */
 typedef LUAI_UMEM lu_mem;
 typedef LUAI_MEM l_mem;
-#elif LUAI_BITSINT >= 32	/* }{ */
+#elif LUAI_IS32INT	/* }{ */
 typedef size_t lu_mem;
 typedef ptrdiff_t l_mem;
 #else  /* 16-bit ints */	/* }{ */

@@ -39,7 +40,7 @@
 /* maximum value for size_t */
 #define MAX_SIZET	((size_t)(~(size_t)0))
 
-/* maximum size visible for Lua (must be representable in a lua_Integer */
+/* maximum size visible for Lua (must be representable in a lua_Integer) */
 #define MAX_SIZE	(sizeof(size_t) < sizeof(lua_Integer) ? MAX_SIZET \
                           : (size_t)(LUA_MAXINTEGER))
 

@@ -65,6 +66,10 @@
 #define ispow2(x)	(((x) & ((x) - 1)) == 0)
 
 
+/* number of chars of a literal string without the ending \0 */
+#define LL(x)   (sizeof(x)/sizeof(char) - 1)
+
+
 /*
 ** conversion of pointer to unsigned integer:
 ** this is for hashing only; there is no problem if the integer

@@ -169,26 +174,17 @@
 
 
 /*
-** maximum depth for nested C calls and syntactical nested non-terminals
-** in a program. (Value must fit in an unsigned short int. It must also
-** be compatible with the size of the C stack.)
-*/
-#if !defined(LUAI_MAXCCALLS)
-#define LUAI_MAXCCALLS		2200
-#endif
-
-
-
-/*
 ** type for virtual-machine instructions;
 ** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h)
 */
-#if LUAI_BITSINT >= 32
-typedef unsigned int Instruction;
+#if LUAI_IS32INT
+typedef unsigned int l_uint32;
 #else
-typedef unsigned long Instruction;
+typedef unsigned long l_uint32;
 #endif
 
+typedef l_uint32 Instruction;
+
 
 
 /*

@@ -293,15 +289,20 @@
 #endif
 
 /*
-** modulo: defined as 'a - floor(a/b)*b'; this definition gives NaN when
-** 'b' is huge, but the result should be 'a'. 'fmod' gives the result of
-** 'a - trunc(a/b)*b', and therefore must be corrected when 'trunc(a/b)
-** ~= floor(a/b)'. That happens when the division has a non-integer
-** negative result, which is equivalent to the test below.
+** modulo: defined as 'a - floor(a/b)*b'; the direct computation
+** using this definition has several problems with rounding errors,
+** so it is better to use 'fmod'. 'fmod' gives the result of
+** 'a - trunc(a/b)*b', and therefore must be corrected when
+** 'trunc(a/b) ~= floor(a/b)'. That happens when the division has a
+** non-integer negative result: non-integer result is equivalent to
+** a non-zero remainder 'm'; negative result is equivalent to 'a' and
+** 'b' with different signs, or 'm' and 'b' with different signs
+** (as the result 'm' of 'fmod' has the same sign of 'a').
 */
 #if !defined(luai_nummod)
 #define luai_nummod(L,a,b,m)  \
-  { (m) = l_mathop(fmod)(a,b); if ((m)*(b) < 0) (m) += (b); }
+  { (void)L; (m) = l_mathop(fmod)(a,b); \
+    if (((m) > 0) ? (b) < 0 : ((m) < 0 && (b) > 0)) (m) += (b); }
 #endif
 
 /* exponentiation */

@@ -318,6 +319,8 @@
 #define luai_numeq(a,b)         ((a)==(b))
 #define luai_numlt(a,b)         ((a)<(b))
 #define luai_numle(a,b)         ((a)<=(b))
+#define luai_numgt(a,b)         ((a)>(b))
+#define luai_numge(a,b)         ((a)>=(b))
 #define luai_numisnan(a)        (!luai_numeq((a), (a)))
 #endif
 

src/lmathlib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lmathlib.c,v 1.135 2018/06/14 18:47:22 roberto Exp $
+** $Id: lmathlib.c $
 ** Standard mathematical library
 ** See Copyright Notice in lua.h
 */

@@ -266,7 +266,7 @@
 
 /* try to find an integer type with at least 64 bits */
 
-#if (LONG_MAX >> 31 >> 31) >= 1
+#if (ULONG_MAX >> 31 >> 31) >= 3
 
 /* 'long' has at least 64 bits */
 #define Rand64		unsigned long

@@ -276,7 +276,7 @@
 /* there is a 'long long' type (which must have at least 64 bits) */
 #define Rand64		unsigned long long
 
-#elif (LUA_MAXINTEGER >> 31 >> 31) >= 1
+#elif (LUA_MAXUNSIGNED >> 31 >> 31) >= 3
 
 /* 'lua_Integer' has at least 64 bits */
 #define Rand64		lua_Unsigned

@@ -301,7 +301,7 @@
 
 /* rotate left 'x' by 'n' bits */
 static Rand64 rotl (Rand64 x, int n) {
-  return (x << n) | (trim64(x) >> (64 - n)); 
+  return (x << n) | (trim64(x) >> (64 - n));
 }
 
 static Rand64 nextrand (Rand64 *state) {

@@ -323,14 +323,18 @@
 
 /*
 ** Convert bits from a random integer into a float in the
-** interval [0,1).
+** interval [0,1), getting the higher FIG bits from the
+** random unsigned integer and converting that to a float.
 */
-#define maskFIG		(~(~(Rand64)1 << (FIGS - 1)))  /* use FIGS bits */
-#define shiftFIG  \
-	(l_mathop(0.5) / ((Rand64)1 << (FIGS - 1)))  /* 2^(-FIGS) */
+
+/* must throw out the extra (64 - FIGS) bits */
+#define shift64_FIG  	(64 - FIGS)
+
+/* to scale to [0, 1), multiply by scaleFIG = 2^(-FIGS) */
+#define scaleFIG	(l_mathop(0.5) / ((Rand64)1 << (FIGS - 1)))
 
 static lua_Number I2d (Rand64 x) {
-  return (lua_Number)(x & maskFIG) * shiftFIG;
+  return (lua_Number)(trim64(x) >> shift64_FIG) * scaleFIG;
 }
 
 /* convert a 'Rand64' to a 'lua_Unsigned' */

@@ -343,7 +347,7 @@
 #else	/* no 'Rand64'   }{ */
 
 /* get an integer with at least 32 bits */
-#if (INT_MAX >> 30) >= 1
+#if LUAI_IS32INT
 typedef unsigned int lu_int32;
 #else
 typedef unsigned long lu_int32;

@@ -449,35 +453,49 @@
 /* an unsigned 1 with proper type */
 #define UONE		((lu_int32)1)
 
+
 #if FIGS <= 32
 
-#define maskHI		0  /* do not need bits from higher half */
-#define maskLOW		(~(~UONE << (FIGS - 1)))  /* use FIGS bits */
-#define shiftFIG	(l_mathop(0.5) / (UONE << (FIGS - 1)))  /* 2^(-FIGS) */
+/* 2^(-FIGS) */
+#define scaleFIG       (l_mathop(0.5) / (UONE << (FIGS - 1)))
+
+/*
+** get up to 32 bits from higher half, shifting right to
+** throw out the extra bits.
+*/
+static lua_Number I2d (Rand64 x) {
+  lua_Number h = (lua_Number)(trim32(x.h) >> (32 - FIGS));
+  return h * scaleFIG;
+}
 
 #else	/* 32 < FIGS <= 64 */
 
 /* must take care to not shift stuff by more than 31 slots */
 
-/* use FIGS - 32 bits from higher half */
-#define maskHI		(~(~UONE << (FIGS - 33)))
+/* 2^(-FIGS) = 1.0 / 2^30 / 2^3 / 2^(FIGS-33) */
+#define scaleFIG  \
+	((lua_Number)1.0 / (UONE << 30) / 8.0 / (UONE << (FIGS - 33)))
 
-/* use 32 bits from lower half */
-#define maskLOW		(~(~UONE << 31))
-
-/* 2^(-FIGS) == (1 / 2^33) / 2^(FIGS-33) */
-#define shiftFIG  ((lua_Number)(1.0 / 8589934592.0) / (UONE << (FIGS - 33)))
+/*
+** use FIGS - 32 bits from lower half, throwing out the other
+** (32 - (FIGS - 32)) = (64 - FIGS) bits
+*/
+#define shiftLOW	(64 - FIGS)
 
-#endif
+/*
+** higher 32 bits go after those (FIGS - 32) bits: shiftHI = 2^(FIGS - 32)
+*/
+#define shiftHI		((lua_Number)(UONE << (FIGS - 33)) * 2.0)
 
-#define twoto32		l_mathop(4294967296.0)  /* 2^32 */
 
 static lua_Number I2d (Rand64 x) {
-  lua_Number h = (lua_Number)(x.h & maskHI);
-  lua_Number l = (lua_Number)(x.l & maskLOW);
-  return (h * twoto32 + l) * shiftFIG;
+  lua_Number h = (lua_Number)trim32(x.h) * shiftHI;
+  lua_Number l = (lua_Number)(trim32(x.l) >> shiftLOW);
+  return (h + l) * scaleFIG;
 }
 
+#endif
+
 
 /* convert a 'Rand64' to a 'lua_Unsigned' */
 static lua_Unsigned I2UInt (Rand64 x) {

@@ -520,7 +538,7 @@
     lim |= (lim >> 4);
     lim |= (lim >> 8);
     lim |= (lim >> 16);
-#if (LUA_MAXINTEGER >> 30 >> 1) > 0
+#if (LUA_MAXUNSIGNED >> 31) >= 3
     lim |= (lim >> 32);  /* integer type has more than 32 bits */
 #endif
   }

@@ -579,11 +597,27 @@
 }
 
 
+/*
+** Set a "random" seed. To get some randomness, use the current time
+** and the address of 'L' (in case the machine does address space layout
+** randomization).
+*/
+static void randseed (lua_State *L, RanState *state) {
+  lua_Unsigned seed1 = (lua_Unsigned)time(NULL);
+  lua_Unsigned seed2 = (lua_Unsigned)(size_t)L;
+  setseed(state->s, seed1, seed2);
+}
+
+
 static int math_randomseed (lua_State *L) {
   RanState *state = (RanState *)lua_touserdata(L, lua_upvalueindex(1));
-  lua_Integer n1 = luaL_checkinteger(L, 1);
-  lua_Integer n2 = luaL_optinteger(L, 2, 0);
-  setseed(state->s, n1, n2);
+  if (lua_isnone(L, 1))
+    randseed(L, state);
+  else {
+    lua_Integer n1 = luaL_checkinteger(L, 1);
+    lua_Integer n2 = luaL_optinteger(L, 2, 0);
+    setseed(state->s, n1, n2);
+  }
   return 0;
 }
 

@@ -597,15 +631,10 @@
 
 /*
 ** Register the random functions and initialize their state.
-** To give some "randomness" to the initial seed, use the current time
-** and the address of 'L' (in case the machine does address space layout
-** randomization).
 */
 static void setrandfunc (lua_State *L) {
   RanState *state = (RanState *)lua_newuserdatauv(L, sizeof(RanState), 0);
-  lua_Unsigned seed1 = (lua_Unsigned)time(NULL); 
-  lua_Unsigned seed2 = (lua_Unsigned)(size_t)L; 
-  setseed(state->s, seed1, seed2);
+  randseed(L, state);  /* initialize with a "random" seed */
   luaL_setfuncs(L, randfuncs, 1);
 }
 

src/lmem.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lmem.c,v 1.98 2018/06/18 12:08:10 roberto Exp $
+** $Id: lmem.c $
 ** Interface to Memory Manager
 ** See Copyright Notice in lua.h
 */

@@ -108,7 +108,7 @@
 */
 void luaM_free_ (lua_State *L, void *block, size_t osize) {
   global_State *g = G(L);
-  lua_assert((block == 0) == (block == NULL));
+  lua_assert((osize == 0) == (block == NULL));
   (*g->frealloc)(g->ud, block, osize, 0);
   g->GCdebt -= osize;
 }

src/lmem.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lmem.h,v 1.47 2018/01/28 15:13:26 roberto Exp $
+** $Id: lmem.h $
 ** Interface to Memory Manager
 ** See Copyright Notice in lua.h
 */

src/loadlib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: loadlib.c,v 1.132 2018/02/27 18:47:32 roberto Exp $
+** $Id: loadlib.c $
 ** Dynamic library loader for Lua
 ** See Copyright Notice in lua.h
 **

@@ -290,22 +290,33 @@
 static void setpath (lua_State *L, const char *fieldname,
                                    const char *envname,
                                    const char *dft) {
+  const char *dftmark;
   const char *nver = lua_pushfstring(L, "%s%s", envname, LUA_VERSUFFIX);
-  const char *path = getenv(nver);  /* use versioned name */
-  if (path == NULL)  /* no environment variable? */
+  const char *path = getenv(nver);  /* try versioned name */
+  if (path == NULL)  /* no versioned environment variable? */
     path = getenv(envname);  /* try unversioned name */
   if (path == NULL || noenv(L))  /* no environment variable? */
     lua_pushstring(L, dft);  /* use default */
-  else {
-    /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */
-    path = luaL_gsub(L, path, LUA_PATH_SEP LUA_PATH_SEP,
-                              LUA_PATH_SEP AUXMARK LUA_PATH_SEP);
-    luaL_gsub(L, path, AUXMARK, dft);
-    lua_remove(L, -2); /* remove result from 1st 'gsub' */
+  else if ((dftmark = strstr(path, LUA_PATH_SEP LUA_PATH_SEP)) == NULL)
+    lua_pushstring(L, path);  /* nothing to change */
+  else {  /* path contains a ";;": insert default path in its place */
+    size_t len = strlen(path);
+    luaL_Buffer b;
+    luaL_buffinit(L, &b);
+    if (path < dftmark) {  /* is there a prefix before ';;'? */
+      luaL_addlstring(&b, path, dftmark - path);  /* add it */
+      luaL_addchar(&b, *LUA_PATH_SEP);
+    }
+    luaL_addstring(&b, dft);  /* add default */
+    if (dftmark < path + len - 2) {  /* is there a sufix after ';;'? */
+      luaL_addchar(&b, *LUA_PATH_SEP);
+      luaL_addlstring(&b, dftmark + 2, (path + len - 2) - dftmark);
+    }
+    luaL_pushresult(&b);
   }
   setprogdir(L);
   lua_setfield(L, -3, fieldname);  /* package[fieldname] = path value */
-  lua_pop(L, 1);  /* pop versioned variable name */
+  lua_pop(L, 1);  /* pop versioned variable name ('nver') */
 }
 
 /* }================================================================== */

@@ -421,14 +432,42 @@
 }
 
 
-static const char *pushnexttemplate (lua_State *L, const char *path) {
-  const char *l;
-  while (*path == *LUA_PATH_SEP) path++;  /* skip separators */
-  if (*path == '\0') return NULL;  /* no more templates */
-  l = strchr(path, *LUA_PATH_SEP);  /* find next separator */
-  if (l == NULL) l = path + strlen(path);
-  lua_pushlstring(L, path, l - path);  /* template */
-  return l;
+/*
+** Get the next name in '*path' = 'name1;name2;name3;...', changing
+** the ending ';' to '\0' to create a zero-terminated string. Return
+** NULL when list ends.
+*/
+static const char *getnextfilename (char **path, char *end) {
+  char *sep;
+  char *name = *path;
+  if (name == end)
+    return NULL;  /* no more names */
+  else if (*name == '\0') {  /* from previous iteration? */
+    *name = *LUA_PATH_SEP;  /* restore separator */
+    name++;  /* skip it */
+  }
+  sep = strchr(name, *LUA_PATH_SEP);  /* find next separator */
+  if (sep == NULL)  /* separator not found? */
+    sep = end;  /* name goes until the end */
+  *sep = '\0';  /* finish file name */
+  *path = sep;  /* will start next search from here */
+  return name;
+}
+
+
+/*
+** Given a path such as ";blabla.so;blublu.so", pushes the string
+**
+** 	no file 'blabla.so'
+**	no file 'blublu.so'
+*/
+static void pusherrornotfound (lua_State *L, const char *path) {
+  luaL_Buffer b;
+  luaL_buffinit(L, &b);
+  luaL_addstring(&b, "\n\tno file '");
+  luaL_addgsub(&b, path, LUA_PATH_SEP, "'\n\tno file '");
+  luaL_addstring(&b, "'");
+  luaL_pushresult(&b);
 }
 
 

@@ -436,21 +475,25 @@
                                              const char *path,
                                              const char *sep,
                                              const char *dirsep) {
-  luaL_Buffer msg;  /* to build error message */
-  if (*sep != '\0')  /* non-empty separator? */
+  luaL_Buffer buff;
+  char *pathname;  /* path with name inserted */
+  char *endpathname;  /* its end */
+  const char *filename;
+  /* separator is non-empty and appears in 'name'? */
+  if (*sep != '\0' && strchr(name, *sep) != NULL)
     name = luaL_gsub(L, name, sep, dirsep);  /* replace it by 'dirsep' */
-  luaL_buffinit(L, &msg);
-  while ((path = pushnexttemplate(L, path)) != NULL) {
-    const char *filename = luaL_gsub(L, lua_tostring(L, -1),
-                                     LUA_PATH_MARK, name);
-    lua_remove(L, -2);  /* remove path template */
+  luaL_buffinit(L, &buff);
+  /* add path to the buffer, replacing marks ('?') with the file name */
+  luaL_addgsub(&buff, path, LUA_PATH_MARK, name);
+  luaL_addchar(&buff, '\0');
+  pathname = luaL_buffaddr(&buff);  /* writable list of file names */
+  endpathname = pathname + luaL_bufflen(&buff) - 1;
+  while ((filename = getnextfilename(&pathname, endpathname)) != NULL) {
     if (readable(filename))  /* does file exist and is readable? */
-      return filename;  /* return that file name */
-    lua_pushfstring(L, "\n\tno file '%s'", filename);
-    lua_remove(L, -2);  /* remove file name */
-    luaL_addvalue(&msg);  /* concatenate error msg. entry */
+      return lua_pushstring(L, filename);  /* save and return name */
   }
-  luaL_pushresult(&msg);  /* create error message */
+  luaL_pushresult(&buff);  /* push path to create error message */
+  pusherrornotfound(L, lua_tostring(L, -1));  /* create error message */
   return NULL;  /* not found */
 }
 

@@ -560,9 +603,14 @@
 static int searcher_preload (lua_State *L) {
   const char *name = luaL_checkstring(L, 1);
   lua_getfield(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE);
-  if (lua_getfield(L, -1, name) == LUA_TNIL)  /* not found? */
+  if (lua_getfield(L, -1, name) == LUA_TNIL) {  /* not found? */
     lua_pushfstring(L, "\n\tno field package.preload['%s']", name);
-  return 1;
+    return 1;
+  }
+  else {
+    lua_pushliteral(L, ":preload:");
+    return 2;
+  }
 }
 
 

@@ -604,17 +652,23 @@
   /* else must load package */
   lua_pop(L, 1);  /* remove 'getfield' result */
   findloader(L, name);
-  lua_pushstring(L, name);  /* pass name as argument to module loader */
-  lua_insert(L, -2);  /* name is 1st argument (before search data) */
+  lua_rotate(L, -2, 1);  /* function <-> loader data */
+  lua_pushvalue(L, 1);  /* name is 1st argument to module loader */
+  lua_pushvalue(L, -3);  /* loader data is 2nd argument */
+  /* stack: ...; loader data; loader function; mod. name; loader data */
   lua_call(L, 2, 1);  /* run loader to load module */
+  /* stack: ...; loader data; result from loader */
   if (!lua_isnil(L, -1))  /* non-nil return? */
     lua_setfield(L, 2, name);  /* LOADED[name] = returned value */
+  else
+    lua_pop(L, 1);  /* pop nil */
   if (lua_getfield(L, 2, name) == LUA_TNIL) {   /* module set no value? */
     lua_pushboolean(L, 1);  /* use true as result */
-    lua_pushvalue(L, -1);  /* extra copy to be returned */
+    lua_copy(L, -1, -2);  /* replace loader result */
     lua_setfield(L, 2, name);  /* LOADED[name] = true */
   }
-  return 1;
+  lua_rotate(L, -2, 1);  /* loader data <-> module result  */
+  return 2;  /* return module result and loader data */
 }
 
 /* }====================================================== */

src/lobject.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lobject.c,v 2.126 2018/06/01 17:40:38 roberto Exp $
+** $Id: lobject.c $
 ** Some generic functions over Lua objects
 ** See Copyright Notice in lua.h
 */

@@ -83,7 +83,7 @@
     case LUA_OPSUB:return intop(-, v1, v2);
     case LUA_OPMUL:return intop(*, v1, v2);
     case LUA_OPMOD: return luaV_mod(L, v1, v2);
-    case LUA_OPIDIV: return luaV_div(L, v1, v2);
+    case LUA_OPIDIV: return luaV_idiv(L, v1, v2);
     case LUA_OPBAND: return intop(&, v1, v2);
     case LUA_OPBOR: return intop(|, v1, v2);
     case LUA_OPBXOR: return intop(^, v1, v2);

@@ -106,11 +106,7 @@
     case LUA_OPPOW: return luai_numpow(L, v1, v2);
     case LUA_OPIDIV: return luai_numidiv(L, v1, v2);
     case LUA_OPUNM: return luai_numunm(L, v1);
-    case LUA_OPMOD: {
-      lua_Number m;
-      luai_nummod(L, v1, v2, m);
-      return m;
-    }
+    case LUA_OPMOD: return luaV_modf(L, v1, v2);
     default: lua_assert(0); return 0;
   }
 }

@@ -347,7 +343,7 @@
 
 int luaO_utf8esc (char *buff, unsigned long x) {
   int n = 1;  /* number of bytes put in buffer (backwards) */
-  lua_assert(x <= 0x10FFFF);
+  lua_assert(x <= 0x7FFFFFFFu);
   if (x < 0x80)  /* ascii? */
     buff[UTF8BUFFSZ - 1] = cast_char(x);
   else {  /* need continuation bytes */

@@ -368,85 +364,178 @@
 
 
 /*
-** Convert a number object to a string
+** Convert a number object to a string, adding it to a buffer
 */
-void luaO_tostring (lua_State *L, TValue *obj) {
-  char buff[MAXNUMBER2STR];
+static size_t tostringbuff (TValue *obj, char *buff) {
   size_t len;
   lua_assert(ttisnumber(obj));
   if (ttisinteger(obj))
-    len = lua_integer2str(buff, sizeof(buff), ivalue(obj));
+    len = lua_integer2str(buff, MAXNUMBER2STR, ivalue(obj));
   else {
-    len = lua_number2str(buff, sizeof(buff), fltvalue(obj));
+    len = lua_number2str(buff, MAXNUMBER2STR, fltvalue(obj));
     if (buff[strspn(buff, "-0123456789")] == '\0') {  /* looks like an int? */
       buff[len++] = lua_getlocaledecpoint();
       buff[len++] = '0';  /* adds '.0' to result */
     }
   }
+  return len;
+}
+
+
+/*
+** Convert a number object to a Lua string, replacing the value at 'obj'
+*/
+void luaO_tostring (lua_State *L, TValue *obj) {
+  char buff[MAXNUMBER2STR];
+  size_t len = tostringbuff(obj, buff);
   setsvalue(L, obj, luaS_newlstr(L, buff, len));
 }
 
 
-static void pushstr (lua_State *L, const char *str, size_t l) {
+
+
+/*
+** {==================================================================
+** 'luaO_pushvfstring'
+** ===================================================================
+*/
+
+/* size for buffer space used by 'luaO_pushvfstring' */
+#define BUFVFS		400
+
+/* buffer used by 'luaO_pushvfstring' */
+typedef struct BuffFS {
+  lua_State *L;
+  int pushed;  /* number of string pieces already on the stack */
+  int blen;  /* length of partial string in 'space' */
+  char space[BUFVFS];  /* holds last part of the result */
+} BuffFS;
+
+
+/*
+** Push given string to the stack, as part of the buffer. If the stack
+** is almost full, join all partial strings in the stack into one.
+*/
+static void pushstr (BuffFS *buff, const char *str, size_t l) {
+  lua_State *L = buff->L;
   setsvalue2s(L, L->top, luaS_newlstr(L, str, l));
-  L->top++;
+  L->top++;  /* may use one extra slot */
+  buff->pushed++;
+  if (buff->pushed > 1 && L->top + 1 >= L->stack_last) {
+    luaV_concat(L, buff->pushed);  /* join all partial results into one */
+    buff->pushed = 1;
+  }
 }
 
 
 /*
-** this function handles only '%d', '%c', '%f', '%p', and '%s'
+** empty the buffer space into the stack
+*/
+static void clearbuff (BuffFS *buff) {
+  pushstr(buff, buff->space, buff->blen);  /* push buffer contents */
+  buff->blen = 0;  /* space now is empty */
+}
+
+
+/*
+** Get a space of size 'sz' in the buffer. If buffer has not enough
+** space, empty it. 'sz' must fit in an empty space.
+*/
+static char *getbuff (BuffFS *buff, size_t sz) {
+  lua_assert(buff->blen <= BUFVFS); lua_assert(sz <= BUFVFS);
+  if (sz > BUFVFS - cast_sizet(buff->blen))  /* string does not fit? */
+    clearbuff(buff);
+  return buff->space + buff->blen;
+}
+
+
+#define addsize(b,sz)	((b)->blen += (sz))
+
+
+/*
+** Add 'str' to the buffer. If string is larger than the buffer space,
+** push the string directly to the stack.
+*/
+static void addstr2buff (BuffFS *buff, const char *str, size_t slen) {
+  if (slen <= BUFVFS) {  /* does string fit into buffer? */
+    char *bf = getbuff(buff, slen);
+    memcpy(bf, str, slen);  /* add string to buffer */
+    addsize(buff, slen);
+  }
+  else {  /* string larger than buffer */
+    clearbuff(buff);  /* string comes after buffer's content */
+    pushstr(buff, str, slen);  /* push string */
+  }
+}
+
+
+/*
+** Add a number to the buffer.
+*/
+static void addnum2buff (BuffFS *buff, TValue *num) {
+  char *numbuff = getbuff(buff, MAXNUMBER2STR);
+  size_t len = tostringbuff(num, numbuff);  /* format number into 'numbuff' */
+  addsize(buff, len);
+}
+
+
+/*
+** this function handles only '%d', '%c', '%f', '%p', '%s', and '%%'
    conventional formats, plus Lua-specific '%I' and '%U'
 */
 const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
-  int n = 0;  /* number of strings in the stack to concatenate */
-  const char *e;  /* points to next conversion specifier */
+  BuffFS buff;  /* holds last part of the result */
+  const char *e;  /* points to next '%' */
+  buff.pushed = buff.blen = 0;
+  buff.L = L;
   while ((e = strchr(fmt, '%')) != NULL) {
-    pushstr(L, fmt, e - fmt);  /* string up to conversion specifier */
-    switch (*(e+1)) {
+    addstr2buff(&buff, fmt, e - fmt);  /* add 'fmt' up to '%' */
+    switch (*(e + 1)) {  /* conversion specifier */
       case 's': {  /* zero-terminated string */
         const char *s = va_arg(argp, char *);
         if (s == NULL) s = "(null)";
-        pushstr(L, s, strlen(s));
+        addstr2buff(&buff, s, strlen(s));
         break;
       }
       case 'c': {  /* an 'int' as a character */
-        char buff = cast_char(va_arg(argp, int));
-        if (lisprint(cast_uchar(buff)))
-          pushstr(L, &buff, 1);
-        else  /* non-printable character; print its code */
-          luaO_pushfstring(L, "<\\%d>", cast_uchar(buff));
+        char c = cast_uchar(va_arg(argp, int));
+        addstr2buff(&buff, &c, sizeof(char));
         break;
       }
       case 'd': {  /* an 'int' */
-        setivalue(s2v(L->top), va_arg(argp, int));
-        goto top2str;
+        TValue num;
+        setivalue(&num, va_arg(argp, int));
+        addnum2buff(&buff, &num);
+        break;
       }
       case 'I': {  /* a 'lua_Integer' */
-        setivalue(s2v(L->top), cast(lua_Integer, va_arg(argp, l_uacInt)));
-        goto top2str;
+        TValue num;
+        setivalue(&num, cast(lua_Integer, va_arg(argp, l_uacInt)));
+        addnum2buff(&buff, &num);
+        break;
       }
       case 'f': {  /* a 'lua_Number' */
-        setfltvalue(s2v(L->top), cast_num(va_arg(argp, l_uacNumber)));
-      top2str:  /* convert the top element to a string */
-        L->top++;
-        luaO_tostring(L, s2v(L->top - 1));
+        TValue num;
+        setfltvalue(&num, cast_num(va_arg(argp, l_uacNumber)));
+        addnum2buff(&buff, &num);
         break;
       }
       case 'p': {  /* a pointer */
-        char buff[4*sizeof(void *) + 8]; /* should be enough space for a '%p' */
+        const int sz = 3 * sizeof(void*) + 8; /* enough space for '%p' */
+        char *bf = getbuff(&buff, sz);
         void *p = va_arg(argp, void *);
-        int l = lua_pointer2str(buff, sizeof(buff), p);
-        pushstr(L, buff, l);
+        int len = lua_pointer2str(bf, sz, p);
+        addsize(&buff, len);
         break;
       }
-      case 'U': {  /* an 'int' as a UTF-8 sequence */
-        char buff[UTF8BUFFSZ];
-        int l = luaO_utf8esc(buff, cast(long, va_arg(argp, long)));
-        pushstr(L, buff + UTF8BUFFSZ - l, l);
+      case 'U': {  /* a 'long' as a UTF-8 sequence */
+        char bf[UTF8BUFFSZ];
+        int len = luaO_utf8esc(bf, va_arg(argp, long));
+        addstr2buff(&buff, bf + UTF8BUFFSZ - len, len);
         break;
       }
       case '%': {
-        pushstr(L, "%", 1);
+        addstr2buff(&buff, "%", 1);
         break;
       }
       default: {

@@ -454,15 +543,12 @@
                          *(e + 1));
       }
     }
-    n += 2;
-    if (L->top + 2 > L->stack_last) {  /* no free stack space? */
-      luaV_concat(L, n);
-      n = 1;
-    }
-    fmt = e + 2;
+    fmt = e + 2;  /* skip '%' and the specifier */
   }
-  pushstr(L, fmt, strlen(fmt));
-  if (n > 0) luaV_concat(L, n + 1);
+  addstr2buff(&buff, fmt, strlen(fmt));  /* rest of 'fmt' */
+  clearbuff(&buff);  /* empty buffer into the stack */
+  if (buff.pushed > 1)
+    luaV_concat(L, buff.pushed);  /* join all partial results */
   return svalue(s2v(L->top - 1));
 }
 

@@ -476,9 +562,8 @@
   return msg;
 }
 
+/* }================================================================== */
 
-/* number of chars of a literal string without the ending \0 */
-#define LL(x)	(sizeof(x)/sizeof(char) - 1)
 
 #define RETS	"..."
 #define PRE	"[string \""

@@ -486,36 +571,36 @@
 
 #define addstr(a,b,l)	( memcpy(a,b,(l) * sizeof(char)), a += (l) )
 
-void luaO_chunkid (char *out, const char *source, size_t bufflen) {
-  size_t l = strlen(source);
+void luaO_chunkid (char *out, const char *source, size_t srclen) {
+  size_t bufflen = LUA_IDSIZE;  /* free space in buffer */
   if (*source == '=') {  /* 'literal' source */
-    if (l <= bufflen)  /* small enough? */
-      memcpy(out, source + 1, l * sizeof(char));
+    if (srclen <= bufflen)  /* small enough? */
+      memcpy(out, source + 1, srclen * sizeof(char));
     else {  /* truncate it */
       addstr(out, source + 1, bufflen - 1);
       *out = '\0';
     }
   }
   else if (*source == '@') {  /* file name */
-    if (l <= bufflen)  /* small enough? */
-      memcpy(out, source + 1, l * sizeof(char));
+    if (srclen <= bufflen)  /* small enough? */
+      memcpy(out, source + 1, srclen * sizeof(char));
     else {  /* add '...' before rest of name */
       addstr(out, RETS, LL(RETS));
       bufflen -= LL(RETS);
-      memcpy(out, source + 1 + l - bufflen, bufflen * sizeof(char));
+      memcpy(out, source + 1 + srclen - bufflen, bufflen * sizeof(char));
     }
   }
   else {  /* string; format as [string "source"] */
     const char *nl = strchr(source, '\n');  /* find first new line (if any) */
     addstr(out, PRE, LL(PRE));  /* add prefix */
     bufflen -= LL(PRE RETS POS) + 1;  /* save space for prefix+suffix+'\0' */
-    if (l < bufflen && nl == NULL) {  /* small one-line source? */
-      addstr(out, source, l);  /* keep it */
+    if (srclen < bufflen && nl == NULL) {  /* small one-line source? */
+      addstr(out, source, srclen);  /* keep it */
     }
     else {
-      if (nl != NULL) l = nl - source;  /* stop at first newline */
-      if (l > bufflen) l = bufflen;
-      addstr(out, source, l);
+      if (nl != NULL) srclen = nl - source;  /* stop at first newline */
+      if (srclen > bufflen) srclen = bufflen;
+      addstr(out, source, srclen);
       addstr(out, RETS, LL(RETS));
     }
     memcpy(out, POS, (LL(POS) + 1) * sizeof(char));

src/lobject.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lobject.h,v 2.146 2018/06/15 19:31:22 roberto Exp $
+** $Id: lobject.h $
 ** Type definitions for Lua objects
 ** See Copyright Notice in lua.h
 */

@@ -350,21 +350,13 @@
 } TString;
 
 
-/*
-** Ensures that address after this type is always fully aligned.
-*/
-typedef union UTString {
-  LUAI_MAXALIGN;  /* ensures maximum alignment for strings */
-  TString tsv;
-} UTString;
-
 
 /*
 ** Get the actual string (array of bytes) from a 'TString'.
 ** (Access to 'extra' ensures that value is really a 'TString'.)
 */
 #define getstr(ts)  \
-  check_exp(sizeof((ts)->extra), cast_charp((ts)) + sizeof(UTString))
+  check_exp(sizeof((ts)->extra), cast_charp((ts)) + sizeof(TString))
 
 
 /* get the actual string (array of bytes) from a Lua value */

@@ -505,7 +497,6 @@
   lu_byte numparams;  /* number of fixed (named) parameters */
   lu_byte is_vararg;
   lu_byte maxstacksize;  /* number of registers needed by this function */
-  lu_byte cachemiss;  /* count for successive misses for 'cache' field */
   int sizeupvalues;  /* size of 'upvalues' */
   int sizek;  /* size of 'k' */
   int sizecode;

@@ -516,7 +507,6 @@
   int linedefined;  /* debug information  */
   int lastlinedefined;  /* debug information  */
   TValue *k;  /* constants used by the function */
-  struct LClosure *cache;  /* last-created closure with this prototype */
   Instruction *code;  /* opcodes */
   struct Proto **p;  /* functions defined inside the function */
   Upvaldesc *upvalues;  /* upvalue information */

@@ -588,6 +578,10 @@
 } UpVal;
 
 
+/* variant for "To Be Closed" upvalues */
+#define LUA_TUPVALTBC	(LUA_TUPVAL | (1 << 4))
+
+
 #define ClosureHeader \
 	CommonHeader; lu_byte nupvalues; GCObject *gclist
 

@@ -753,7 +747,7 @@
 LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt,
                                                        va_list argp);
 LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);
-LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len);
+LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t srclen);
 
 
 #endif

src/lopcodes.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lopcodes.c,v 1.82 2018/04/19 15:42:41 roberto Exp $
+** $Id: lopcodes.c $
 ** Opcodes for Lua virtual machine
 ** See Copyright Notice in lua.h
 */

@@ -17,92 +17,6 @@
 
 /* ORDER OP */
 
-#if defined(LUAI_DEFOPNAMES)
-
-LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = {
-  "MOVE",
-  "LOADI",
-  "LOADF",
-  "LOADK",
-  "LOADKX",
-  "LOADBOOL",
-  "LOADNIL",
-  "GETUPVAL",
-  "SETUPVAL",
-  "GETTABUP",
-  "GETTABLE",
-  "GETI",
-  "GETFIELD",
-  "SETTABUP",
-  "SETTABLE",
-  "SETI",
-  "SETFIELD",
-  "NEWTABLE",
-  "SELF",
-  "ADDI",
-  "SUBI",
-  "MULI",
-  "MODI",
-  "POWI",
-  "DIVI",
-  "IDIVI",
-  "BANDK",
-  "BORK",
-  "BXORK",
-  "SHRI",
-  "SHLI",
-  "ADD",
-  "SUB",
-  "MUL",
-  "MOD",
-  "POW",
-  "DIV",
-  "IDIV",
-  "BAND",
-  "BOR",
-  "BXOR",
-  "SHL",
-  "SHR",
-  "UNM",
-  "BNOT",
-  "NOT",
-  "LEN",
-  "CONCAT",
-  "CLOSE",
-  "JMP",
-  "EQ",
-  "LT",
-  "LE",
-  "EQK",
-  "EQI",
-  "LTI",
-  "LEI",
-  "GTI",
-  "GEI",
-  "TEST",
-  "TESTSET",
-  "CALL",
-  "TAILCALL",
-  "RETURN",
-  "RETURN0",
-  "RETURN1",
-  "FORLOOP1",
-  "FORPREP1",
-  "FORLOOP",
-  "FORPREP",
-  "TFORCALL",
-  "TFORLOOP",
-  "SETLIST",
-  "CLOSURE",
-  "VARARG",
-  "PREPVARARG",
-  "EXTRAARG",
-  NULL
-};
-
-#endif
-
-
 LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
 /*       OT IT T  A  mode		   opcode  */
   opmode(0, 0, 0, 1, iABC)		/* OP_MOVE */

@@ -131,6 +45,13 @@
  ,opmode(0, 0, 0, 1, iABC)		/* OP_POWI */
  ,opmode(0, 0, 0, 1, iABC)		/* OP_DIVI */
  ,opmode(0, 0, 0, 1, iABC)		/* OP_IDIVI */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_ADDK */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_SUBK */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_MULK */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_MODK */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_POWK */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_DIVK */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_IDIVK */
  ,opmode(0, 0, 0, 1, iABC)		/* OP_BANDK */
  ,opmode(0, 0, 0, 1, iABC)		/* OP_BORK */
  ,opmode(0, 0, 0, 1, iABC)		/* OP_BXORK */

@@ -154,6 +75,7 @@
  ,opmode(0, 0, 0, 1, iABC)		/* OP_LEN */
  ,opmode(0, 0, 0, 1, iABC)		/* OP_CONCAT */
  ,opmode(0, 0, 0, 0, iABC)		/* OP_CLOSE */
+ ,opmode(0, 0, 0, 0, iABC)		/* OP_TBC */
  ,opmode(0, 0, 0, 0, isJ)		/* OP_JMP */
  ,opmode(0, 0, 1, 0, iABC)		/* OP_EQ */
  ,opmode(0, 0, 1, 0, iABC)		/* OP_LT */

@@ -171,16 +93,15 @@
  ,opmode(0, 1, 0, 0, iABC)		/* OP_RETURN */
  ,opmode(0, 0, 0, 0, iABC)		/* OP_RETURN0 */
  ,opmode(0, 0, 0, 0, iABC)		/* OP_RETURN1 */
- ,opmode(0, 0, 0, 1, iABx)		/* OP_FORLOOP1 */
- ,opmode(0, 0, 0, 1, iABx)		/* OP_FORPREP1 */
  ,opmode(0, 0, 0, 1, iABx)		/* OP_FORLOOP */
  ,opmode(0, 0, 0, 1, iABx)		/* OP_FORPREP */
+ ,opmode(0, 0, 0, 0, iABx)		/* OP_TFORPREP */
  ,opmode(0, 0, 0, 0, iABC)		/* OP_TFORCALL */
  ,opmode(0, 0, 0, 1, iABx)		/* OP_TFORLOOP */
  ,opmode(0, 1, 0, 0, iABC)		/* OP_SETLIST */
  ,opmode(0, 0, 0, 1, iABx)		/* OP_CLOSURE */
  ,opmode(1, 0, 0, 1, iABC)		/* OP_VARARG */
- ,opmode(0, 0, 0, 1, iABC)		/* OP_PREPVARARG */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_VARARGPREP */
  ,opmode(0, 0, 0, 0, iAx)		/* OP_EXTRAARG */
 };
 

src/lopcodes.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lopcodes.h,v 1.193 2018/06/18 12:51:05 roberto Exp $
+** $Id: lopcodes.h $
 ** Opcodes for Lua virtual machine
 ** See Copyright Notice in lua.h
 */

@@ -21,7 +21,7 @@
 iABx               Bx(17)               |     A(8)      |   Op(7)     |
 iAsB              sBx (signed)(17)      |     A(8)      |   Op(7)     |
 iAx                           Ax(25)                    |   Op(7)     |
-isJ                          sJ(24)                   |m|   Op(7)     |
+isJ                          sJ(25)                     |   Op(7)     |
 
   A signed argument is represented in excess K: the represented value is
   the written unsigned value minus K, where K is half the maximum for the

@@ -40,7 +40,7 @@
 #define SIZE_Bx		(SIZE_C + SIZE_B + 1)
 #define SIZE_A		8
 #define SIZE_Ax		(SIZE_Bx + SIZE_A)
-#define SIZE_sJ		(SIZE_Bx + SIZE_A - 1)
+#define SIZE_sJ		(SIZE_Bx + SIZE_A)
 
 #define SIZE_OP		7
 

@@ -55,15 +55,20 @@
 
 #define POS_Ax		POS_A
 
-#define POS_m		POS_A
-#define POS_sJ		(POS_A + 1)
+#define POS_sJ		POS_A
+
 
 /*
 ** limits for opcode arguments.
-** we use (signed) int to manipulate most arguments,
-** so they must fit in LUAI_BITSINT-1 bits (-1 for sign)
+** we use (signed) 'int' to manipulate most arguments,
+** so they must fit in ints.
 */
-#if SIZE_Bx < LUAI_BITSINT-1
+
+/* Check whether type 'int' has at least 'b' bits ('b' < 32) */
+#define L_INTHASBITS(b)		((UINT_MAX >> ((b) - 1)) >= 1)
+
+
+#if L_INTHASBITS(SIZE_Bx)
 #define MAXARG_Bx	((1<<SIZE_Bx)-1)
 #else
 #define MAXARG_Bx	MAX_INT

@@ -72,13 +77,13 @@
 #define OFFSET_sBx	(MAXARG_Bx>>1)         /* 'sBx' is signed */
 
 
-#if SIZE_Ax < LUAI_BITSINT-1
+#if L_INTHASBITS(SIZE_Ax)
 #define MAXARG_Ax	((1<<SIZE_Ax)-1)
 #else
 #define MAXARG_Ax	MAX_INT
 #endif
 
-#if SIZE_sJ < LUAI_BITSINT-1
+#if L_INTHASBITS(SIZE_sJ)
 #define MAXARG_sJ	((1 << SIZE_sJ) - 1)
 #else
 #define MAXARG_sJ	MAX_INT

@@ -91,7 +96,6 @@
 #define MAXARG_B	((1<<SIZE_B)-1)
 #define MAXARG_C	((1<<SIZE_C)-1)
 #define OFFSET_sC	(MAXARG_C >> 1)
-#define MAXARG_Cx	((1<<(SIZE_C + 1))-1)
 
 
 /* creates a mask with 'n' 1 bits at position 'p' */

@@ -144,8 +148,6 @@
 	check_exp(checkopm(i, isJ), getarg(i, POS_sJ, SIZE_sJ) - OFFSET_sJ)
 #define SETARG_sJ(i,j) \
 	setarg(i, cast_uint((j)+OFFSET_sJ), POS_sJ, SIZE_sJ)
-#define GETARG_m(i)	check_exp(checkopm(i, isJ), getarg(i, POS_m, 1))
-#define SETARG_m(i,m)	setarg(i, m, POS_m, 1)
 
 
 #define CREATE_ABCk(o,a,b,c,k)	((cast(Instruction, o)<<POS_OP) \

@@ -224,12 +226,20 @@
 OP_DIVI,/*	A B sC	R(A) := R(B) / C				*/
 OP_IDIVI,/*	A B sC	R(A) := R(B) // C				*/
 
+OP_ADDK,/*	A B C	R(A) := R(B) + K(C)				*/
+OP_SUBK,/*	A B C	R(A) := R(B) - K(C)				*/
+OP_MULK,/*	A B C	R(A) := R(B) * K(C)				*/
+OP_MODK,/*	A B C	R(A) := R(B) % K(C)				*/
+OP_POWK,/*	A B C	R(A) := R(B) ^ K(C)				*/
+OP_DIVK,/*	A B C	R(A) := R(B) / K(C)				*/
+OP_IDIVK,/*	A B C	R(A) := R(B) // K(C)				*/
+
 OP_BANDK,/*	A B C	R(A) := R(B) & K(C):integer			*/
 OP_BORK,/*	A B C	R(A) := R(B) | K(C):integer			*/
 OP_BXORK,/*	A B C	R(A) := R(B) ~ K(C):integer			*/
 
-OP_SHRI,/*	A B C	R(A) := R(B) >> C				*/
-OP_SHLI,/*	A B C	R(A) := C << R(B)				*/
+OP_SHRI,/*	A B sC	R(A) := R(B) >> C				*/
+OP_SHLI,/*	A B sC	R(A) := C << R(B)				*/
 
 OP_ADD,/*	A B C	R(A) := R(B) + R(C)				*/
 OP_SUB,/*	A B C	R(A) := R(B) - R(C)				*/

@@ -238,11 +248,13 @@
 OP_POW,/*	A B C	R(A) := R(B) ^ R(C)				*/
 OP_DIV,/*	A B C	R(A) := R(B) / R(C)				*/
 OP_IDIV,/*	A B C	R(A) := R(B) // R(C)				*/
+
 OP_BAND,/*	A B C	R(A) := R(B) & R(C)				*/
 OP_BOR,/*	A B C	R(A) := R(B) | R(C)				*/
 OP_BXOR,/*	A B C	R(A) := R(B) ~ R(C)				*/
 OP_SHL,/*	A B C	R(A) := R(B) << R(C)				*/
 OP_SHR,/*	A B C	R(A) := R(B) >> R(C)				*/
+
 OP_UNM,/*	A B	R(A) := -R(B)					*/
 OP_BNOT,/*	A B	R(A) := ~R(B)					*/
 OP_NOT,/*	A B	R(A) := not R(B)				*/

@@ -251,6 +263,7 @@
 OP_CONCAT,/*	A B  	R(A) := R(A).. ... ..R(A + B - 1)		*/
 
 OP_CLOSE,/*	A	close all upvalues >= R(A)			*/
+OP_TBC,/*	A	mark variable A "to be closed"			*/
 OP_JMP,/*	k sJ	pc += sJ  (k is used in code generation)	*/
 OP_EQ,/*	A B	if ((R(A) == R(B)) ~= k) then pc++		*/
 OP_LT,/*	A B	if ((R(A) <  R(B)) ~= k) then pc++		*/

@@ -264,7 +277,7 @@
 OP_GEI,/*	A sB	if ((R(A) >= sB) ~= k) then pc++		*/
 
 OP_TEST,/*	A 	if (not R(A) == k) then pc++			*/
-OP_TESTSET,/*	A B	if (not R(B) == k) then R(A) := R(B) else pc++	*/
+OP_TESTSET,/*	A B	if (not R(B) == k) then pc++ else R(A) := R(B)	*/
 
 OP_CALL,/*	A B C	R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
 OP_TAILCALL,/*	A B C	return R(A)(R(A+1), ... ,R(A+B-1))		*/

@@ -273,16 +286,13 @@
 OP_RETURN0,/*	  	return 						*/
 OP_RETURN1,/*	A 	return R(A)					*/
 
-OP_FORLOOP1,/*	A Bx	R(A)++;
-			if R(A) <= R(A+1) then { pc-=Bx; R(A+3)=R(A) }	*/
-OP_FORPREP1,/*	A Bx	R(A)--; pc+=Bx					*/
-
 OP_FORLOOP,/*	A Bx	R(A)+=R(A+2);
 			if R(A) <?= R(A+1) then { pc-=Bx; R(A+3)=R(A) }	*/
 OP_FORPREP,/*	A Bx	R(A)-=R(A+2); pc+=Bx				*/
 
-OP_TFORCALL,/*	A C	R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2));	*/
-OP_TFORLOOP,/*	A Bx	if R(A+1) ~= nil then { R(A)=R(A+1); pc -= Bx }	*/
+OP_TFORPREP,/*	A Bx	create upvalue for R(A + 3); pc+=Bx		*/
+OP_TFORCALL,/*	A C	R(A+4), ... ,R(A+3+C) := R(A)(R(A+1), R(A+2));	*/
+OP_TFORLOOP,/*	A Bx	if R(A+2) ~= nil then { R(A)=R(A+2); pc -= Bx }	*/
 
 OP_SETLIST,/*	A B C	R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B	*/
 

@@ -290,21 +300,21 @@
 
 OP_VARARG,/*	A C  	R(A), R(A+1), ..., R(A+C-2) = vararg		*/
 
-OP_PREPVARARG,/*A 	(adjust vararg parameters)			*/
+OP_VARARGPREP,/*A 	(adjust vararg parameters)			*/
 
 OP_EXTRAARG/*	Ax	extra (larger) argument for previous opcode	*/
 } OpCode;
 
 
-#define NUM_OPCODES	(cast_int(OP_EXTRAARG) + 1)
+#define NUM_OPCODES	((int)(OP_EXTRAARG) + 1)
 
 
 
 /*===========================================================================
   Notes:
-  (*) In OP_CALL, if (B == 0) then B = top. If (C == 0), then 'top' is
-  set to last_result+1, so next open instruction (OP_CALL, OP_RETURN*,
-  OP_SETLIST) may use 'top'.
+  (*) In OP_CALL, if (B == 0) then B = top - A. If (C == 0), then
+  'top' is set to last_result+1, so next open instruction (OP_CALL,
+  OP_RETURN*, OP_SETLIST) may use 'top'.
 
   (*) In OP_VARARG, if (C == 0) then use actual number of varargs and
   set top (like in OP_CALL with C == 0).

@@ -327,6 +337,9 @@
   C > 0 means the function is vararg and (C - 1) is its number of
   fixed parameters.
 
+  (*) In comparisons with an immediate operand, C signals whether the
+  original operand was a float.
+
 ===========================================================================*/
 
 

@@ -358,9 +371,6 @@
 #define opmode(ot,it,t,a,m) (((ot)<<6) | ((it)<<5) | ((t)<<4) | ((a)<<3) | (m))
 
 
-LUAI_DDEC(const char *const luaP_opnames[NUM_OPCODES+1];)  /* opcode names */
-
-
 /* number of list items to accumulate before a SETLIST instruction */
 #define LFIELDS_PER_FLUSH	50
 

src/lopnames.h

@@ -0,0 +1,101 @@
+/*
+** $Id: lopnames.h $
+** Opcode names
+** See Copyright Notice in lua.h
+*/
+
+#if !defined(lopnames_h)
+#define lopnames_h
+
+/* ORDER OP */
+
+static const char *const opnames[] = {
+  "MOVE",
+  "LOADI",
+  "LOADF",
+  "LOADK",
+  "LOADKX",
+  "LOADBOOL",
+  "LOADNIL",
+  "GETUPVAL",
+  "SETUPVAL",
+  "GETTABUP",
+  "GETTABLE",
+  "GETI",
+  "GETFIELD",
+  "SETTABUP",
+  "SETTABLE",
+  "SETI",
+  "SETFIELD",
+  "NEWTABLE",
+  "SELF",
+  "ADDI",
+  "SUBI",
+  "MULI",
+  "MODI",
+  "POWI",
+  "DIVI",
+  "IDIVI",
+  "ADDK",
+  "SUBK",
+  "MULK",
+  "MODK",
+  "POWK",
+  "DIVK",
+  "IDIVK",
+  "BANDK",
+  "BORK",
+  "BXORK",
+  "SHRI",
+  "SHLI",
+  "ADD",
+  "SUB",
+  "MUL",
+  "MOD",
+  "POW",
+  "DIV",
+  "IDIV",
+  "BAND",
+  "BOR",
+  "BXOR",
+  "SHL",
+  "SHR",
+  "UNM",
+  "BNOT",
+  "NOT",
+  "LEN",
+  "CONCAT",
+  "CLOSE",
+  "TBC",
+  "JMP",
+  "EQ",
+  "LT",
+  "LE",
+  "EQK",
+  "EQI",
+  "LTI",
+  "LEI",
+  "GTI",
+  "GEI",
+  "TEST",
+  "TESTSET",
+  "CALL",
+  "TAILCALL",
+  "RETURN",
+  "RETURN0",
+  "RETURN1",
+  "FORLOOP",
+  "FORPREP",
+  "TFORPREP",
+  "TFORCALL",
+  "TFORLOOP",
+  "SETLIST",
+  "CLOSURE",
+  "VARARG",
+  "VARARGPREP",
+  "EXTRAARG",
+  NULL
+};
+
+#endif
+

src/loslib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: loslib.c,v 1.66 2017/03/14 12:40:44 roberto Exp $
+** $Id: loslib.c $
 ** Standard Operating System library
 ** See Copyright Notice in lua.h
 */

@@ -10,7 +10,6 @@
 #include "lprefix.h"
 
 
-#include <errno.h>
 #include <locale.h>
 #include <stdlib.h>
 #include <string.h>

src/lparser.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.c,v 2.181 2018/06/18 17:57:20 roberto Exp $
+** $Id: lparser.c $
 ** Lua Parser
 ** See Copyright Notice in lua.h
 */

@@ -10,6 +10,7 @@
 #include "lprefix.h"
 
 
+#include <limits.h>
 #include <string.h>
 
 #include "lua.h"

@@ -49,11 +50,10 @@
   struct BlockCnt *previous;  /* chain */
   int firstlabel;  /* index of first label in this block */
   int firstgoto;  /* index of first pending goto in this block */
-  int brks;  /* list of break jumps in this block */
-  lu_byte brkcls;  /* true if some 'break' needs to close upvalues */
   lu_byte nactvar;  /* # active locals outside the block */
   lu_byte upval;  /* true if some variable in the block is an upvalue */
   lu_byte isloop;  /* true if 'block' is a loop */
+  lu_byte insidetbc;  /* true if inside the scope of a to-be-closed var. */
 } BlockCnt;
 
 

@@ -89,6 +89,9 @@
 }
 
 
+/*
+** Test whether next token is 'c'; if so, skip it.
+*/
 static int testnext (LexState *ls, int c) {
   if (ls->t.token == c) {
     luaX_next(ls);

@@ -98,12 +101,18 @@
 }
 
 
+/*
+** Check that next token is 'c'.
+*/
 static void check (LexState *ls, int c) {
   if (ls->t.token != c)
     error_expected(ls, c);
 }
 
 
+/*
+** Check that next token is 'c' and skip it.
+*/
 static void checknext (LexState *ls, int c) {
   check(ls, c);
   luaX_next(ls);

@@ -113,11 +122,15 @@
 #define check_condition(ls,c,msg)	{ if (!(c)) luaX_syntaxerror(ls, msg); }
 
 
-
+/*
+** Check that next token is 'what' and skip it. In case of error,
+** raise an error that the expected 'what' should match a 'who'
+** in line 'where' (if that is not the current line).
+*/
 static void check_match (LexState *ls, int what, int who, int where) {
-  if (!testnext(ls, what)) {
-    if (where == ls->linenumber)
-      error_expected(ls, what);
+  if (unlikely(!testnext(ls, what))) {
+    if (where == ls->linenumber)  /* all in the same line? */
+      error_expected(ls, what);  /* do not need a complex message */
     else {
       luaX_syntaxerror(ls, luaO_pushfstring(ls->L,
              "%s expected (to close %s at line %d)",

@@ -143,16 +156,27 @@
 }
 
 
+static void init_var (expdesc *e, expkind k, int i) {
+  e->f = e->t = NO_JUMP;
+  e->k = k;
+  e->u.var.idx = i;
+}
+
+
 static void codestring (LexState *ls, expdesc *e, TString *s) {
   init_exp(e, VK, luaK_stringK(ls->fs, s));
 }
 
 
-static void checkname (LexState *ls, expdesc *e) {
+static void codename (LexState *ls, expdesc *e) {
   codestring(ls, e, str_checkname(ls));
 }
 
 
+/*
+** Register a new local variable in the active 'Proto' (for debug
+** information).
+*/
 static int registerlocalvar (LexState *ls, TString *varname) {
   FuncState *fs = ls->fs;
   Proto *f = fs->f;

@@ -167,33 +191,89 @@
 }
 
 
-static void new_localvar (LexState *ls, TString *name) {
+/*
+** Create a new local variable with the given 'name'.
+*/
+static Vardesc *new_localvar (LexState *ls, TString *name) {
   FuncState *fs = ls->fs;
   Dyndata *dyd = ls->dyd;
+  Vardesc *var;
   int reg = registerlocalvar(ls, name);
   checklimit(fs, dyd->actvar.n + 1 - fs->firstlocal,
                   MAXVARS, "local variables");
   luaM_growvector(ls->L, dyd->actvar.arr, dyd->actvar.n + 1,
                   dyd->actvar.size, Vardesc, MAX_INT, "local variables");
-  dyd->actvar.arr[dyd->actvar.n++].idx = cast(short, reg);
+  var = &dyd->actvar.arr[dyd->actvar.n++];
+  var->idx = cast(short, reg);
+  var->name = name;
+  var->ro = 0;
+  return var;
 }
 
+#define new_localvarliteral(ls,v) \
+    new_localvar(ls, luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char)) - 1));
 
-static void new_localvarliteral_ (LexState *ls, const char *name, size_t sz) {
-  new_localvar(ls, luaX_newstring(ls, name, sz));
-}
 
-#define new_localvarliteral(ls,v) \
-	new_localvarliteral_(ls, "" v, (sizeof(v)/sizeof(char))-1)
 
+/*
+** Return the "variable description" (Vardesc) of a given
+** variable
+*/
+static Vardesc *getlocalvardesc (FuncState *fs, int i) {
+  return &fs->ls->dyd->actvar.arr[fs->firstlocal + i];
+}
 
+/*
+** Get the debug-information entry for current variable 'i'.
+*/
 static LocVar *getlocvar (FuncState *fs, int i) {
-  int idx = fs->ls->dyd->actvar.arr[fs->firstlocal + i].idx;
+  int idx = getlocalvardesc(fs, i)->idx;
   lua_assert(idx < fs->nlocvars);
   return &fs->f->locvars[idx];
 }
 
 
+/*
+** Return the "variable description" (Vardesc) of a given
+** variable or upvalue
+*/
+static Vardesc *getvardesc (FuncState *fs, expdesc *e) {
+  if (e->k == VLOCAL)
+    return getlocalvardesc(fs, e->u.var.idx);
+  else if (e->k != VUPVAL)
+    return NULL;  /* not a local variable */
+  else {  /* upvalue: must go up all levels up to the original local */
+    int idx = e->u.var.idx;
+    for (;;) {
+      Upvaldesc *up = &fs->f->upvalues[idx];
+      fs = fs->prev;  /* must look at the previous level */
+      idx = up->idx;  /* at this index */
+      if (fs == NULL) {  /* no more levels? (can happen only with _ENV) */
+        lua_assert(strcmp(getstr(up->name), LUA_ENV) == 0);
+        return NULL;
+      }
+      else if (up->instack)  /* got to the original level? */
+        return getlocalvardesc(fs, idx);
+      /* else repeat for previous level */
+    }
+  }
+}
+
+
+static void check_readonly (LexState *ls, expdesc *e) {
+  Vardesc *vardesc = getvardesc(ls->fs, e);
+  if (vardesc && vardesc->ro) {  /* is variable local and const? */
+    const char *msg = luaO_pushfstring(ls->L,
+       "attempt to assign to const variable '%s'", getstr(vardesc->name));
+    luaK_semerror(ls, msg);  /* error */
+  }
+}
+
+
+/*
+** Start the scope for the last 'nvars' created variables.
+** (debug info.)
+*/
 static void adjustlocalvars (LexState *ls, int nvars) {
   FuncState *fs = ls->fs;
   fs->nactvar = cast_byte(fs->nactvar + nvars);

@@ -203,6 +283,10 @@
 }
 
 
+/*
+** Close the scope for all variables up to level 'tolevel'.
+** (debug info.)
+*/
 static void removevars (FuncState *fs, int tolevel) {
   fs->ls->dyd->actvar.n -= (fs->nactvar - tolevel);
   while (fs->nactvar > tolevel)

@@ -210,6 +294,10 @@
 }
 
 
+/*
+** Search the upvalues of the function 'fs' for one
+** with the given 'name'.
+*/
 static int searchupvalue (FuncState *fs, TString *name) {
   int i;
   Upvaldesc *up = fs->f->upvalues;

@@ -229,13 +317,17 @@
   while (oldsize < f->sizeupvalues)
     f->upvalues[oldsize++].name = NULL;
   f->upvalues[fs->nups].instack = (v->k == VLOCAL);
-  f->upvalues[fs->nups].idx = cast_byte(v->u.info);
+  f->upvalues[fs->nups].idx = cast_byte(v->u.var.idx);
   f->upvalues[fs->nups].name = name;
   luaC_objbarrier(fs->ls->L, f, name);
   return fs->nups++;
 }
 
 
+/*
+** Look for an active local variable with the name 'n' in the
+** function 'fs'.
+*/
 static int searchvar (FuncState *fs, TString *n) {
   int i;
   for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) {

@@ -247,20 +339,22 @@
 
 
 /*
-  Mark block where variable at given level was defined
-  (to emit close instructions later).
+** Mark block where variable at given level was defined
+** (to emit close instructions later).
 */
 static void markupval (FuncState *fs, int level) {
   BlockCnt *bl = fs->bl;
   while (bl->nactvar > level)
     bl = bl->previous;
   bl->upval = 1;
+  fs->needclose = 1;
 }
 
 
 /*
-  Find variable with given name 'n'. If it is an upvalue, add this
-  upvalue into all intermediate functions.
+** Find a variable with the given name 'n'. If it is an upvalue, add
+** this upvalue into all intermediate functions. If it is a global, set
+** 'var' as 'void' as a flag.
 */
 static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
   if (fs == NULL)  /* no more levels? */

@@ -268,7 +362,7 @@
   else {
     int v = searchvar(fs, n);  /* look up locals at current level */
     if (v >= 0) {  /* found? */
-      init_exp(var, VLOCAL, v);  /* variable is local */
+      init_var(var, VLOCAL, v);  /* variable is local */
       if (!base)
         markupval(fs, v);  /* local will be used as an upval */
     }

@@ -281,12 +375,16 @@
         /* else was LOCAL or UPVAL */
         idx  = newupvalue(fs, n, var);  /* will be a new upvalue */
       }
-      init_exp(var, VUPVAL, idx);  /* new or old upvalue */
+      init_var(var, VUPVAL, idx);  /* new or old upvalue */
     }
   }
 }
 
 
+/*
+** Find a variable with the given name 'n', handling global variables
+** too.
+*/
 static void singlevar (LexState *ls, expdesc *var) {
   TString *varname = str_checkname(ls);
   FuncState *fs = ls->fs;

@@ -301,78 +399,90 @@
 }
 
 
+/*
+** Adjust the number of results from an expression list 'e' with 'nexps'
+** expressions to 'nvars' values.
+*/
 static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) {
   FuncState *fs = ls->fs;
-  int extra = nvars - nexps;
-  if (hasmultret(e->k)) {
-    extra++;  /* includes call itself */
-    if (extra < 0) extra = 0;
+  int needed = nvars - nexps;  /* extra values needed */
+  if (hasmultret(e->k)) {  /* last expression has multiple returns? */
+    int extra = needed + 1;  /* discount last expression itself */
+    if (extra < 0)
+      extra = 0;
     luaK_setreturns(fs, e, extra);  /* last exp. provides the difference */
-    if (extra > 1) luaK_reserveregs(fs, extra-1);
   }
   else {
-    if (e->k != VVOID) luaK_exp2nextreg(fs, e);  /* close last expression */
-    if (extra > 0) {
-      int reg = fs->freereg;
-      luaK_reserveregs(fs, extra);
-      luaK_nil(fs, reg, extra);
-    }
+    if (e->k != VVOID)  /* at least one expression? */
+      luaK_exp2nextreg(fs, e);  /* close last expression */
+    if (needed > 0)  /* missing values? */
+      luaK_nil(fs, fs->freereg, needed);  /* complete with nils */
   }
-  if (nexps > nvars)
-    ls->fs->freereg -= nexps - nvars;  /* remove extra values */
+  if (needed > 0)
+    luaK_reserveregs(fs, needed);  /* registers for extra values */
+  else  /* adding 'needed' is actually a subtraction */
+    fs->freereg += needed;  /* remove extra values */
 }
 
 
-#define enterlevel(ls)	luaE_incCcalls((ls)->L)
+/*
+** Macros to limit the maximum recursion depth while parsing
+*/
+#define enterlevel(ls)	luaE_enterCcall((ls)->L)
+
+#define leavelevel(ls)	luaE_exitCcall((ls)->L)
 
 
-#define leavelevel(ls)	((ls)->L->nCcalls--)
+/*
+** Generates an error that a goto jumps into the scope of some
+** local variable.
+*/
+static l_noret jumpscopeerror (LexState *ls, Labeldesc *gt) {
+  const char *varname = getstr(getlocvar(ls->fs, gt->nactvar)->varname);
+  const char *msg = "<goto %s> at line %d jumps into the scope of local '%s'";
+  msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line, varname);
+  luaK_semerror(ls, msg);  /* raise the error */
+}
 
 
-static void closegoto (LexState *ls, int g, Labeldesc *label) {
+/*
+** Solves the goto at index 'g' to given 'label' and removes it
+** from the list of pending goto's.
+** If it jumps into the scope of some variable, raises an error.
+*/
+static void solvegoto (LexState *ls, int g, Labeldesc *label) {
   int i;
-  FuncState *fs = ls->fs;
-  Labellist *gl = &ls->dyd->gt;
-  Labeldesc *gt = &gl->arr[g];
+  Labellist *gl = &ls->dyd->gt;  /* list of goto's */
+  Labeldesc *gt = &gl->arr[g];  /* goto to be resolved */
   lua_assert(eqstr(gt->name, label->name));
-  if (gt->nactvar < label->nactvar) {
-    TString *vname = getlocvar(fs, gt->nactvar)->varname;
-    const char *msg = luaO_pushfstring(ls->L,
-      "<goto %s> at line %d jumps into the scope of local '%s'",
-      getstr(gt->name), gt->line, getstr(vname));
-    luaK_semerror(ls, msg);
-  }
-  luaK_patchgoto(fs, gt->pc, label->pc, 1);
-  /* remove goto from pending list */
-  for (i = g; i < gl->n - 1; i++)
+  if (unlikely(gt->nactvar < label->nactvar))  /* enter some scope? */
+    jumpscopeerror(ls, gt);
+  luaK_patchlist(ls->fs, gt->pc, label->pc);
+  for (i = g; i < gl->n - 1; i++)  /* remove goto from pending list */
     gl->arr[i] = gl->arr[i + 1];
   gl->n--;
 }
 
 
 /*
-** try to close a goto with existing labels; this solves backward jumps
+** Search for an active label with the given name.
 */
-static int solvelabel (LexState *ls, int g) {
+static Labeldesc *findlabel (LexState *ls, TString *name) {
   int i;
-  BlockCnt *bl = ls->fs->bl;
   Dyndata *dyd = ls->dyd;
-  Labeldesc *gt = &dyd->gt.arr[g];
-  /* check labels in current block for a match */
-  for (i = bl->firstlabel; i < dyd->label.n; i++) {
+  /* check labels in current function for a match */
+  for (i = ls->fs->firstlabel; i < dyd->label.n; i++) {
     Labeldesc *lb = &dyd->label.arr[i];
-    if (eqstr(lb->name, gt->name)) {  /* correct label? */
-      if (gt->nactvar > lb->nactvar &&
-          (bl->upval || dyd->label.n > bl->firstlabel))
-        luaK_patchclose(ls->fs, gt->pc);
-      closegoto(ls, g, lb);  /* close it */
-      return 1;
-    }
+    if (eqstr(lb->name, name))  /* correct label? */
+      return lb;
   }
-  return 0;  /* label not found; cannot close goto */
+  return NULL;  /* label not found */
 }
 
 
+/*
+** Adds a new label/goto in the corresponding list.
+*/
 static int newlabelentry (LexState *ls, Labellist *l, TString *name,
                           int line, int pc) {
   int n = l->n;

@@ -381,58 +491,77 @@
   l->arr[n].name = name;
   l->arr[n].line = line;
   l->arr[n].nactvar = ls->fs->nactvar;
+  l->arr[n].close = 0;
   l->arr[n].pc = pc;
   l->n = n + 1;
   return n;
 }
 
 
+static int newgotoentry (LexState *ls, TString *name, int line, int pc) {
+  return newlabelentry(ls, &ls->dyd->gt, name, line, pc);
+}
+
+
 /*
-** check whether new label 'lb' matches any pending gotos in current
-** block; solves forward jumps
+** Solves forward jumps. Check whether new label 'lb' matches any
+** pending gotos in current block and solves them. Return true
+** if any of the goto's need to close upvalues.
 */
-static void solvegotos (LexState *ls, Labeldesc *lb) {
+static int solvegotos (LexState *ls, Labeldesc *lb) {
   Labellist *gl = &ls->dyd->gt;
   int i = ls->fs->bl->firstgoto;
+  int needsclose = 0;
   while (i < gl->n) {
-    if (eqstr(gl->arr[i].name, lb->name))
-      closegoto(ls, i, lb);  /* will remove 'i' from the list */
+    if (eqstr(gl->arr[i].name, lb->name)) {
+      needsclose |= gl->arr[i].close;
+      solvegoto(ls, i, lb);  /* will remove 'i' from the list */
+    }
     else
       i++;
   }
+  return needsclose;
+}
+
+
+/*
+** Create a new label with the given 'name' at the given 'line'.
+** 'last' tells whether label is the last non-op statement in its
+** block. Solves all pending goto's to this new label and adds
+** a close instruction if necessary.
+** Returns true iff it added a close instruction.
+*/
+static int createlabel (LexState *ls, TString *name, int line,
+                        int last) {
+  FuncState *fs = ls->fs;
+  Labellist *ll = &ls->dyd->label;
+  int l = newlabelentry(ls, ll, name, line, luaK_getlabel(fs));
+  if (last) {  /* label is last no-op statement in the block? */
+    /* assume that locals are already out of scope */
+    ll->arr[l].nactvar = fs->bl->nactvar;
+  }
+  if (solvegotos(ls, &ll->arr[l])) {  /* need close? */
+    luaK_codeABC(fs, OP_CLOSE, fs->nactvar, 0, 0);
+    return 1;
+  }
+  return 0;
 }
 
 
 /*
-** export pending gotos to outer level, to check them against
-** outer labels; if the block being exited has upvalues, and
-** the goto exits the scope of any variable (which can be the
-** upvalue), close those variables being exited. Also export
-** break list.
+** Adjust pending gotos to outer level of a block.
 */
 static void movegotosout (FuncState *fs, BlockCnt *bl) {
-  int i = bl->firstgoto;
+  int i;
   Labellist *gl = &fs->ls->dyd->gt;
-  /* correct pending gotos to current block and try to close it
-     with visible labels */
-  while (i < gl->n) {  /* for each pending goto */
+  /* correct pending gotos to current block */
+  for (i = bl->firstgoto; i < gl->n; i++) {  /* for each pending goto */
     Labeldesc *gt = &gl->arr[i];
     if (gt->nactvar > bl->nactvar) {  /* leaving a variable scope? */
-      if (bl->upval)  /* variable may be an upvalue? */
-        luaK_patchclose(fs, gt->pc);  /* jump will need a close */
       gt->nactvar = bl->nactvar;  /* update goto level */
+      gt->close |= bl->upval;  /* jump may need a close */
     }
-    if (!solvelabel(fs->ls, i))
-      i++;  /* move to next one */
-    /* else, 'solvelabel' removed current goto from the list
-       and 'i' now points to next one */
-  }
-  /* handles break list */
-  if (bl->upval)  /* exiting the scope of an upvalue? */
-    luaK_patchclose(fs, bl->brks);  /* breaks will need OP_CLOSE */
-  /* move breaks to outer block */
-  luaK_concat(fs, &bl->previous->brks, bl->brks);
-  bl->previous->brkcls |= bl->brkcls;
+  }
 }
 
 

@@ -441,9 +570,8 @@
   bl->nactvar = fs->nactvar;
   bl->firstlabel = fs->ls->dyd->label.n;
   bl->firstgoto = fs->ls->dyd->gt.n;
-  bl->brks = NO_JUMP;
-  bl->brkcls = 0;
   bl->upval = 0;
+  bl->insidetbc = (fs->bl != NULL && fs->bl->insidetbc);
   bl->previous = fs->bl;
   fs->bl = bl;
   lua_assert(fs->freereg == fs->nactvar);

@@ -451,25 +579,18 @@
 
 
 /*
-** Fix all breaks in block 'bl' to jump to the end of the block.
-*/
-static void fixbreaks (FuncState *fs, BlockCnt *bl) {
-  int target = fs->pc;
-  if (bl->brkcls)  /* does the block need to close upvalues? */
-    luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);
-  luaK_patchgoto(fs, bl->brks, target, bl->brkcls);
-  bl->brks = NO_JUMP;  /* no more breaks to fix */
-  bl->brkcls = 0;  /* no more need to close upvalues */
-  lua_assert(!bl->upval);  /* loop body cannot have local variables */
-}
-
-
-/*
 ** generates an error for an undefined 'goto'.
 */
 static l_noret undefgoto (LexState *ls, Labeldesc *gt) {
-  const char *msg = "no visible label '%s' for <goto> at line %d";
-  msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line);
+  const char *msg;
+  if (eqstr(gt->name, luaS_newliteral(ls->L, "break"))) {
+    msg = "break outside loop at line %d";
+    msg = luaO_pushfstring(ls->L, msg, gt->line);
+  }
+  else {
+    msg = "no visible label '%s' for <goto> at line %d";
+    msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line);
+  }
   luaK_semerror(ls, msg);
 }
 

@@ -477,11 +598,10 @@
 static void leaveblock (FuncState *fs) {
   BlockCnt *bl = fs->bl;
   LexState *ls = fs->ls;
-  if (bl->upval && bl->brks != NO_JUMP)  /* breaks in upvalue scopes? */
-    bl->brkcls = 1;  /* these breaks must close the upvalues */
-  if (bl->isloop)
-    fixbreaks(fs, bl);  /* fix pending breaks */
-  if (bl->previous && bl->upval)
+  int hasclose = 0;
+  if (bl->isloop)  /* fix pending breaks? */
+    hasclose = createlabel(ls, luaS_newliteral(ls->L, "break"), 0, 0);
+  if (!hasclose && bl->previous && bl->upval)
     luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);
   fs->bl = bl->previous;
   removevars(fs, bl->nactvar);

@@ -491,7 +611,6 @@
   if (bl->previous)  /* inner block? */
     movegotosout(fs, bl);  /* update pending gotos to outer block */
   else {
-    lua_assert(bl->brks == NO_JUMP);  /* no pending breaks */
     if (bl->firstgoto < ls->dyd->gt.n)  /* pending gotos in outer block? */
       undefgoto(ls, &ls->dyd->gt.arr[bl->firstgoto]);  /* error */
   }

@@ -547,7 +666,9 @@
   fs->nups = 0;
   fs->nlocvars = 0;
   fs->nactvar = 0;
+  fs->needclose = 0;
   fs->firstlocal = ls->dyd->actvar.n;
+  fs->firstlabel = ls->dyd->label.n;
   fs->bl = NULL;
   f->source = ls->source;
   f->maxstacksize = 2;  /* registers 0/1 are always valid */

@@ -559,7 +680,7 @@
   lua_State *L = ls->L;
   FuncState *fs = ls->fs;
   Proto *f = fs->f;
-  luaK_ret(fs, 0, 0);  /* final return */
+  luaK_ret(fs, fs->nactvar, 0);  /* final return */
   leaveblock(fs);
   lua_assert(fs->bl == NULL);
   luaK_finish(fs);

@@ -616,7 +737,7 @@
   expdesc key;
   luaK_exp2anyregup(fs, v);
   luaX_next(ls);  /* skip the dot or colon */
-  checkname(ls, &key);
+  codename(ls, &key);
   luaK_indexed(fs, v, &key);
 }
 

@@ -653,7 +774,7 @@
   expdesc tab, key, val;
   if (ls->t.token == TK_NAME) {
     checklimit(fs, cc->nh, MAX_INT, "items in a constructor");
-    checkname(ls, &key);
+    codename(ls, &key);
   }
   else  /* ls->t.token == '[' */
     yindex(ls, &key);

@@ -754,7 +875,7 @@
 
 static void setvararg (FuncState *fs, int nparams) {
   fs->f->is_vararg = 1;
-  luaK_codeABC(fs, OP_PREPVARARG, nparams, 0, 0);
+  luaK_codeABC(fs, OP_VARARGPREP, nparams, 0, 0);
 }
 
 

@@ -922,7 +1043,7 @@
       case ':': {  /* ':' NAME funcargs */
         expdesc key;
         luaX_next(ls);
-        checkname(ls, &key);
+        codename(ls, &key);
         luaK_self(fs, v, &key);
         funcargs(ls, v, line);
         break;

@@ -1032,6 +1153,9 @@
 }
 
 
+/*
+** Priority table for binary operators.
+*/
 static const struct {
   lu_byte left;  /* left priority for each binary operator */
   lu_byte right; /* right priority */

@@ -1060,9 +1184,9 @@
   UnOpr uop;
   enterlevel(ls);
   uop = getunopr(ls->t.token);
-  if (uop != OPR_NOUNOPR) {
+  if (uop != OPR_NOUNOPR) {  /* prefix (unary) operator? */
     int line = ls->linenumber;
-    luaX_next(ls);
+    luaX_next(ls);  /* skip operator */
     subexpr(ls, v, UNARY_PRIORITY);
     luaK_prefix(ls->fs, uop, v, line);
   }

@@ -1073,7 +1197,7 @@
     expdesc v2;
     BinOpr nextop;
     int line = ls->linenumber;
-    luaX_next(ls);
+    luaX_next(ls);  /* skip operator */
     luaK_infix(ls->fs, op, v);
     /* read sub-expression with higher priority */
     nextop = subexpr(ls, &v2, priority[op].right);

@@ -1133,20 +1257,20 @@
   for (; lh; lh = lh->prev) {  /* check all previous assignments */
     if (vkisindexed(lh->v.k)) {  /* assignment to table field? */
       if (lh->v.k == VINDEXUP) {  /* is table an upvalue? */
-        if (v->k == VUPVAL && lh->v.u.ind.t == v->u.info) {
+        if (v->k == VUPVAL && lh->v.u.ind.t == v->u.var.idx) {
           conflict = 1;  /* table is the upvalue being assigned now */
           lh->v.k = VINDEXSTR;
           lh->v.u.ind.t = extra;  /* assignment will use safe copy */
         }
       }
       else {  /* table is a register */
-        if (v->k == VLOCAL && lh->v.u.ind.t == v->u.info) {
+        if (v->k == VLOCAL && lh->v.u.ind.t == v->u.var.idx) {
           conflict = 1;  /* table is the local being assigned now */
           lh->v.u.ind.t = extra;  /* assignment will use safe copy */
         }
         /* is index the local being assigned? */
         if (lh->v.k == VINDEXED && v->k == VLOCAL &&
-            lh->v.u.ind.idx == v->u.info) {
+            lh->v.u.ind.idx == v->u.var.idx) {
           conflict = 1;
           lh->v.u.ind.idx = extra;  /* previous assignment will use safe copy */
         }

@@ -1156,26 +1280,33 @@
   if (conflict) {
     /* copy upvalue/local value to a temporary (in position 'extra') */
     OpCode op = (v->k == VLOCAL) ? OP_MOVE : OP_GETUPVAL;
-    luaK_codeABC(fs, op, extra, v->u.info, 0);
+    luaK_codeABC(fs, op, extra, v->u.var.idx, 0);
     luaK_reserveregs(fs, 1);
   }
 }
 
-
-static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {
+/*
+** Parse and compile a mulitple assignment. The first "variable"
+** (a 'suffixedexp') was already read by the caller.
+**
+** assignment -> suffixedexp restassign
+** restassign -> ',' suffixedexp restassign | '=' explist
+*/
+static void restassign (LexState *ls, struct LHS_assign *lh, int nvars) {
   expdesc e;
   check_condition(ls, vkisvar(lh->v.k), "syntax error");
-  if (testnext(ls, ',')) {  /* assignment -> ',' suffixedexp assignment */
+  check_readonly(ls, &lh->v);
+  if (testnext(ls, ',')) {  /* restassign -> ',' suffixedexp restassign */
     struct LHS_assign nv;
     nv.prev = lh;
     suffixedexp(ls, &nv.v);
     if (!vkisindexed(nv.v.k))
       check_conflict(ls, lh, &nv.v);
-    luaE_incCcalls(ls->L);  /* control recursion depth */
-    assignment(ls, &nv, nvars+1);
-    ls->L->nCcalls--;
+    enterlevel(ls);  /* control recursion depth */
+    restassign(ls, &nv, nvars+1);
+    leavelevel(ls);
   }
-  else {  /* assignment -> '=' explist */
+  else {  /* restassign -> '=' explist */
     int nexps;
     checknext(ls, '=');
     nexps = explist(ls, &e);

@@ -1202,63 +1333,54 @@
 }
 
 
-static void gotostat (LexState *ls, int pc) {
+static void gotostat (LexState *ls) {
+  FuncState *fs = ls->fs;
   int line = ls->linenumber;
-  int g;
-  luaX_next(ls);  /* skip 'goto' */
-  g = newlabelentry(ls, &ls->dyd->gt, str_checkname(ls), line, pc);
-  solvelabel(ls, g);  /* close it if label already defined */
+  TString *name = str_checkname(ls);  /* label's name */
+  Labeldesc *lb = findlabel(ls, name);
+  if (lb == NULL)  /* no label? */
+    /* forward jump; will be resolved when the label is declared */
+    newgotoentry(ls, name, line, luaK_jump(fs));
+  else {  /* found a label */
+    /* backward jump; will be resolved here */
+    if (fs->nactvar > lb->nactvar)  /* leaving the scope of some variable? */
+      luaK_codeABC(fs, OP_CLOSE, lb->nactvar, 0, 0);
+    /* create jump and link it to the label */
+    luaK_patchlist(fs, luaK_jump(fs), lb->pc);
+  }
 }
 
 
-static void breakstat (LexState *ls, int pc) {
-  FuncState *fs = ls->fs;
-  BlockCnt *bl = fs->bl;
+/*
+** Break statement. Semantically equivalent to "goto break".
+*/
+static void breakstat (LexState *ls) {
+  int line = ls->linenumber;
   luaX_next(ls);  /* skip break */
-  while (bl && !bl->isloop) { bl = bl->previous; }
-  if (!bl)
-    luaX_syntaxerror(ls, "no loop to break");
-  luaK_concat(fs, &fs->bl->brks, pc);
+  newgotoentry(ls, luaS_newliteral(ls->L, "break"), line, luaK_jump(ls->fs));
 }
 
 
-/* check for repeated labels on the same block */
-static void checkrepeated (FuncState *fs, Labellist *ll, TString *label) {
-  int i;
-  for (i = fs->bl->firstlabel; i < ll->n; i++) {
-    if (eqstr(label, ll->arr[i].name)) {
-      const char *msg = luaO_pushfstring(fs->ls->L,
-                          "label '%s' already defined on line %d",
-                          getstr(label), ll->arr[i].line);
-      luaK_semerror(fs->ls, msg);
-    }
+/*
+** Check whether there is already a label with the given 'name'.
+*/
+static void checkrepeated (LexState *ls, TString *name) {
+  Labeldesc *lb = findlabel(ls, name);
+  if (unlikely(lb != NULL)) {  /* already defined? */
+    const char *msg = "label '%s' already defined on line %d";
+    msg = luaO_pushfstring(ls->L, msg, getstr(name), lb->line);
+    luaK_semerror(ls, msg);  /* error */
   }
 }
 
 
-/* skip no-op statements */
-static void skipnoopstat (LexState *ls) {
-  while (ls->t.token == ';' || ls->t.token == TK_DBCOLON)
-    statement(ls);
-}
-
-
-static void labelstat (LexState *ls, TString *label, int line) {
+static void labelstat (LexState *ls, TString *name, int line) {
   /* label -> '::' NAME '::' */
-  FuncState *fs = ls->fs;
-  Labellist *ll = &ls->dyd->label;
-  int l;  /* index of new label being created */
-  checkrepeated(fs, ll, label);  /* check for repeated labels */
   checknext(ls, TK_DBCOLON);  /* skip double colon */
-  /* create new entry for this label */
-  l = newlabelentry(ls, ll, label, line, luaK_getlabel(fs));
-  luaK_codeABC(fs, OP_CLOSE, fs->nactvar, 0, 0);
-  skipnoopstat(ls);  /* skip other no-op statements */
-  if (block_follow(ls, 0)) {  /* label is last no-op statement in the block? */
-    /* assume that locals are already out of scope */
-    ll->arr[l].nactvar = fs->bl->nactvar;
-  }
-  solvegotos(ls, &ll->arr[l]);
+  while (ls->t.token == ';' || ls->t.token == TK_DBCOLON)
+    statement(ls);  /* skip other no-op statements */
+  checkrepeated(ls, name);  /* check for repeated labels */
+  createlabel(ls, name, line, block_follow(ls, 0));
 }
 
 

@@ -1293,8 +1415,6 @@
   statlist(ls);
   check_match(ls, TK_UNTIL, TK_REPEAT, line);
   condexit = cond(ls);  /* read condition (inside scope block) */
-  if (bl2.upval)  /* upvalues? */
-    luaK_patchclose(fs, condexit);
   leaveblock(fs);  /* finish scope */
   if (bl2.upval) {  /* upvalues? */
     int exit = luaK_jump(fs);  /* normal exit must jump over fix */

@@ -1310,18 +1430,14 @@
 
 /*
 ** Read an expression and generate code to put its results in next
-** stack slot. Return true if expression is a constant integer and,
-** if 'i' is not-zero, its value is equal to 'i'.
+** stack slot.
 **
 */
-static int exp1 (LexState *ls, int i) {
+static void exp1 (LexState *ls) {
   expdesc e;
-  int res;
   expr(ls, &e);
-  res = luaK_isKint(&e) && (i == 0 || i == e.u.ival);
   luaK_exp2nextreg(ls->fs, &e);
   lua_assert(e.k == VNONRELOC);
-  return res;
 }
 
 

@@ -1335,43 +1451,36 @@
   int offset = dest - (pc + 1);
   if (back)
     offset = -offset;
-  if (offset > MAXARG_Bx)
+  if (unlikely(offset > MAXARG_Bx))
     luaX_syntaxerror(fs->ls, "control structure too long");
   SETARG_Bx(*jmp, offset);
 }
 
 
 /*
-** Generate code for a 'for' loop. 'kind' can be zero (a common for
-** loop), one (a basic for loop, with integer values and increment of
-** 1), or two (a generic for loop).
+** Generate code for a 'for' loop.
 */
-static void forbody (LexState *ls, int base, int line, int nvars, int kind) {
+static void forbody (LexState *ls, int base, int line, int nvars, int isgen) {
   /* forbody -> DO block */
+  static OpCode forprep[2] = {OP_FORPREP, OP_TFORPREP};
+  static OpCode forloop[2] = {OP_FORLOOP, OP_TFORLOOP};
   BlockCnt bl;
   FuncState *fs = ls->fs;
   int prep, endfor;
-  adjustlocalvars(ls, 3);  /* control variables */
   checknext(ls, TK_DO);
-  prep = (kind == 0) ? luaK_codeABx(fs, OP_FORPREP, base, 0)
-       : (kind == 1) ? luaK_codeABx(fs, OP_FORPREP1, base, 0)
-       : luaK_jump(fs);
+  prep = luaK_codeABx(fs, forprep[isgen], base, 0);
   enterblock(fs, &bl, 0);  /* scope for declared variables */
   adjustlocalvars(ls, nvars);
   luaK_reserveregs(fs, nvars);
   block(ls);
   leaveblock(fs);  /* end of scope for declared variables */
-  if (kind == 2) {  /* generic for? */
-    luaK_patchtohere(fs, prep);
+  fixforjump(fs, prep, luaK_getlabel(fs), 0);
+  if (isgen) {  /* generic for? */
     luaK_codeABC(fs, OP_TFORCALL, base, 0, nvars);
     luaK_fixline(fs, line);
-    endfor = luaK_codeABx(fs, OP_TFORLOOP, base + 2, 0);
-  }
-  else {
-    fixforjump(fs, prep, luaK_getlabel(fs), 0);
-    endfor = (kind == 0) ? luaK_codeABx(fs, OP_FORLOOP, base, 0)
-                         : luaK_codeABx(fs, OP_FORLOOP1, base, 0);
+    base += 2;  /* base for 'OP_TFORLOOP' (skips function and state) */
   }
+  endfor = luaK_codeABx(fs, forloop[isgen], base, 0);
   fixforjump(fs, endfor, prep + 1, 1);
   luaK_fixline(fs, line);
 }

@@ -1381,25 +1490,22 @@
   /* fornum -> NAME = exp,exp[,exp] forbody */
   FuncState *fs = ls->fs;
   int base = fs->freereg;
-  int basicfor = 1;  /* true if it is a "basic" 'for' (integer + 1) */
   new_localvarliteral(ls, "(for index)");
   new_localvarliteral(ls, "(for limit)");
   new_localvarliteral(ls, "(for step)");
   new_localvar(ls, varname);
   checknext(ls, '=');
-  if (!exp1(ls, 0))  /* initial value not an integer? */
-    basicfor = 0;  /* not a basic 'for' */
+  exp1(ls);  /* initial value */
   checknext(ls, ',');
-  exp1(ls, 0);  /* limit */
-  if (testnext(ls, ',')) {
-    if (!exp1(ls, 1))  /* optional step not 1? */
-      basicfor = 0;  /* not a basic 'for' */
-  }
+  exp1(ls);  /* limit */
+  if (testnext(ls, ','))
+    exp1(ls);  /* optional step */
   else {  /* default step = 1 */
     luaK_int(fs, fs->freereg, 1);
     luaK_reserveregs(fs, 1);
   }
-  forbody(ls, base, line, 1, basicfor);
+  adjustlocalvars(ls, 3);  /* control variables */
+  forbody(ls, base, line, 1, 0);
 }
 
 

@@ -1407,13 +1513,15 @@
   /* forlist -> NAME {,NAME} IN explist forbody */
   FuncState *fs = ls->fs;
   expdesc e;
-  int nvars = 4;  /* gen, state, control, plus at least one declared var */
+  int nvars = 5;  /* gen, state, control, toclose, 'indexname' */
   int line;
   int base = fs->freereg;
   /* create control variables */
   new_localvarliteral(ls, "(for generator)");
   new_localvarliteral(ls, "(for state)");
+  markupval(fs, fs->nactvar);  /* state may create an upvalue */
   new_localvarliteral(ls, "(for control)");
+  new_localvarliteral(ls, "(for toclose)");
   /* create declared variables */
   new_localvar(ls, indexname);
   while (testnext(ls, ',')) {

@@ -1422,9 +1530,10 @@
   }
   checknext(ls, TK_IN);
   line = ls->linenumber;
-  adjust_assign(ls, 3, explist(ls, &e), &e);
+  adjust_assign(ls, 4, explist(ls, &e), &e);
+  adjustlocalvars(ls, 4);  /* control variables */
   luaK_checkstack(fs, 3);  /* extra space to call generator */
-  forbody(ls, base, line, nvars - 3, 2);
+  forbody(ls, base, line, nvars - 4, 1);
 }
 
 

@@ -1446,31 +1555,67 @@
 }
 
 
+/*
+** Check whether next instruction is a single jump (a 'break', a 'goto'
+** to a forward label, or a 'goto' to a backward label with no variable
+** to close). If so, set the name of the 'label' it is jumping to
+** ("break" for a 'break') or to where it is jumping to ('target') and
+** return true. If not a single jump, leave input unchanged, to be
+** handled as a regular statement.
+*/
+static int issinglejump (LexState *ls, TString **label, int *target) {
+  if (testnext(ls, TK_BREAK)) {  /* a break? */
+    *label = luaS_newliteral(ls->L, "break");
+    return 1;
+  }
+  else if (ls->t.token != TK_GOTO || luaX_lookahead(ls) != TK_NAME)
+    return 0;  /* not a valid goto */
+  else {
+    TString *lname = ls->lookahead.seminfo.ts;  /* label's id */
+    Labeldesc *lb = findlabel(ls, lname);
+    if (lb) {  /* a backward jump? */
+      if (ls->fs->nactvar > lb->nactvar)  /* needs to close variables? */
+        return 0;  /* not a single jump; cannot optimize */
+      *target = lb->pc;
+    }
+    else  /* jump forward */
+      *label = lname;
+    luaX_next(ls);  /* skip goto */
+    luaX_next(ls);  /* skip name */
+    return 1;
+  }
+}
+
+
 static void test_then_block (LexState *ls, int *escapelist) {
   /* test_then_block -> [IF | ELSEIF] cond THEN block */
   BlockCnt bl;
+  int line;
   FuncState *fs = ls->fs;
+  TString *jlb = NULL;
+  int target = NO_JUMP;
   expdesc v;
   int jf;  /* instruction to skip 'then' code (if condition is false) */
   luaX_next(ls);  /* skip IF or ELSEIF */
   expr(ls, &v);  /* read condition */
   checknext(ls, TK_THEN);
-  if (ls->t.token == TK_GOTO || ls->t.token == TK_BREAK) {
+  line = ls->linenumber;
+  if (issinglejump(ls, &jlb, &target)) {  /* 'if x then goto' ? */
     luaK_goiffalse(ls->fs, &v);  /* will jump to label if condition is true */
     enterblock(fs, &bl, 0);  /* must enter block before 'goto' */
-    if (ls->t.token == TK_GOTO)
-      gotostat(ls, v.t);  /* handle goto */
-    else
-      breakstat(ls, v.t);  /* handle break */
+    if (jlb != NULL)  /* forward jump? */
+      newgotoentry(ls, jlb, line, v.t);  /* will be resolved later */
+    else  /* backward jump */
+      luaK_patchlist(fs, v.t, target);  /* jump directly to 'target' */
     while (testnext(ls, ';')) {}  /* skip semicolons */
-    if (block_follow(ls, 0)) {  /* 'goto'/'break' is the entire block? */
+    if (block_follow(ls, 0)) {  /* jump is the entire block? */
       leaveblock(fs);
       return;  /* and that is it */
     }
     else  /* must skip over 'then' part if condition is false */
       jf = luaK_jump(fs);
   }
-  else {  /* regular case (not goto/break) */
+  else {  /* regular case (not a jump) */
     luaK_goiftrue(ls->fs, &v);  /* skip over block if condition is false */
     enterblock(fs, &bl, 0);
     jf = v.f;

@@ -1509,7 +1654,7 @@
 }
 
 
-static void localstat (LexState *ls) {
+static void commonlocalstat (LexState *ls) {
   /* stat -> LOCAL NAME {',' NAME} ['=' explist] */
   int nvars = 0;
   int nexps;

@@ -1529,6 +1674,43 @@
 }
 
 
+static void tocloselocalstat (LexState *ls, Vardesc *var) {
+  FuncState *fs = ls->fs;
+  var->ro = 1;  /* to-be-closed variables are always read-only */
+  markupval(fs, fs->nactvar);
+  fs->bl->insidetbc = 1;  /* in the scope of a to-be-closed variable */
+  luaK_codeABC(fs, OP_TBC, fs->nactvar - 1, 0, 0);
+}
+
+
+static void attriblocalstat (LexState *ls) {
+  Vardesc *var;
+  TString *attr = str_checkname(ls);
+  testnext(ls, '>');
+  var = new_localvar(ls, str_checkname(ls));
+  checknext(ls, '=');
+  exp1(ls);
+  adjustlocalvars(ls, 1);
+  if (strcmp(getstr(attr), "const") == 0)
+    var->ro = 1;  /* set variable as read-only */
+  else if (strcmp(getstr(attr), "toclose") == 0)
+    tocloselocalstat(ls, var);
+  else
+    luaK_semerror(ls,
+      luaO_pushfstring(ls->L, "unknown attribute '%s'", getstr(attr)));
+}
+
+
+static void localstat (LexState *ls) {
+  /* stat -> LOCAL NAME {',' NAME} ['=' explist]
+           | LOCAL *toclose NAME '=' exp */
+  if (testnext(ls, '<'))
+    attriblocalstat(ls);
+  else
+    commonlocalstat(ls);
+}
+
+
 static int funcname (LexState *ls, expdesc *v) {
   /* funcname -> NAME {fieldsel} [':' NAME] */
   int ismethod = 0;

@@ -1562,7 +1744,7 @@
   suffixedexp(ls, &v.v);
   if (ls->t.token == '=' || ls->t.token == ',') { /* stat -> assignment ? */
     v.prev = NULL;
-    assignment(ls, &v, 1);
+    restassign(ls, &v, 1);
   }
   else {  /* stat -> func */
     Instruction *inst = &getinstruction(fs, &v.v);

@@ -1576,26 +1758,25 @@
   /* stat -> RETURN [explist] [';'] */
   FuncState *fs = ls->fs;
   expdesc e;
-  int first, nret;  /* registers with returned values */
+  int nret;  /* number of values being returned */
+  int first = fs->nactvar;  /* first slot to be returned */
   if (block_follow(ls, 1) || ls->t.token == ';')
-    first = nret = 0;  /* return no values */
+    nret = 0;  /* return no values */
   else {
     nret = explist(ls, &e);  /* optional return values */
     if (hasmultret(e.k)) {
       luaK_setmultret(fs, &e);
-      if (e.k == VCALL && nret == 1) {  /* tail call? */
+      if (e.k == VCALL && nret == 1 && !fs->bl->insidetbc) {  /* tail call? */
         SET_OPCODE(getinstruction(fs,&e), OP_TAILCALL);
         lua_assert(GETARG_A(getinstruction(fs,&e)) == fs->nactvar);
       }
-      first = fs->nactvar;
       nret = LUA_MULTRET;  /* return all values */
     }
     else {
       if (nret == 1)  /* only one single value? */
-        first = luaK_exp2anyreg(fs, &e);
-      else {
-        luaK_exp2nextreg(fs, &e);  /* values must go to the stack */
-        first = fs->nactvar;  /* return all active values */
+        first = luaK_exp2anyreg(fs, &e);  /* can use original slot */
+      else {  /* values must go to the top of the stack */
+        luaK_exp2nextreg(fs, &e);
         lua_assert(nret == fs->freereg - first);
       }
     }

@@ -1658,11 +1839,12 @@
       break;
     }
     case TK_BREAK: {  /* stat -> breakstat */
-      breakstat(ls, luaK_jump(ls->fs));
+      breakstat(ls);
       break;
     }
     case TK_GOTO: {  /* stat -> 'goto' NAME */
-      gotostat(ls, luaK_jump(ls->fs));
+      luaX_next(ls);  /* skip 'goto' */
+      gotostat(ls);
       break;
     }
     default: {  /* stat -> func | assignment */

@@ -1688,7 +1870,7 @@
   expdesc v;
   open_func(ls, fs, &bl);
   setvararg(fs, 0);  /* main function is always declared vararg */
-  init_exp(&v, VLOCAL, 0);  /* create and... */
+  init_var(&v, VLOCAL, 0);  /* create and... */
   newupvalue(fs, ls->envn, &v);  /* ...set environment upvalue */
   luaX_next(ls);  /* read first token */
   statlist(ls);  /* parse main body */

src/lparser.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.h,v 1.82 2018/04/04 14:23:41 roberto Exp $
+** $Id: lparser.h $
 ** Lua Parser
 ** See Copyright Notice in lua.h
 */

@@ -33,8 +33,8 @@
   VKINT,  /* integer constant; nval = numerical integer value */
   VNONRELOC,  /* expression has its value in a fixed register;
                  info = result register */
-  VLOCAL,  /* local variable; info = local register */
-  VUPVAL,  /* upvalue variable; info = index of upvalue in 'upvalues' */
+  VLOCAL,  /* local variable; var.idx = local register */
+  VUPVAL,  /* upvalue variable; var.idx = index of upvalue in 'upvalues' */
   VINDEXED,  /* indexed variable;
                 ind.t = table register;
                 ind.idx = key's R index */

@@ -58,7 +58,7 @@
 
 #define vkisvar(k)	(VLOCAL <= (k) && (k) <= VINDEXSTR)
 #define vkisindexed(k)	(VINDEXED <= (k) && (k) <= VINDEXSTR)
-#define vkisinreg(k)	((k) == VNONRELOC || (k) == VLOCAL)
+
 
 typedef struct expdesc {
   expkind k;

@@ -70,15 +70,20 @@
       short idx;  /* index (R or "long" K) */
       lu_byte t;  /* table (register or upvalue) */
     } ind;
+    struct {  /* for local variables and upvalues */
+      lu_byte idx;  /* index of the variable */
+    } var;
   } u;
   int t;  /* patch list of 'exit when true' */
   int f;  /* patch list of 'exit when false' */
 } expdesc;
 
 
-/* description of active local variable */
+/* description of an active local variable */
 typedef struct Vardesc {
-  short idx;  /* variable index in stack */
+  TString *name;
+  short idx;  /* index of the variable in the Proto's 'locvars' array */
+  lu_byte ro;  /* true if variable is 'const' */
 } Vardesc;
 
 

@@ -88,6 +93,7 @@
   int pc;  /* position in code */
   int line;  /* line where it appeared */
   lu_byte nactvar;  /* local level where it appears in current block */
+  lu_byte close;  /* goto that escapes upvalues */
 } Labeldesc;
 
 

@@ -128,11 +134,13 @@
   int np;  /* number of elements in 'p' */
   int nabslineinfo;  /* number of elements in 'abslineinfo' */
   int firstlocal;  /* index of first local var (in Dyndata array) */
+  int firstlabel;  /* index of first label (in 'dyd->label->arr') */
   short nlocvars;  /* number of elements in 'f->locvars' */
   lu_byte nactvar;  /* number of active local variables */
   lu_byte nups;  /* number of upvalues */
   lu_byte freereg;  /* first free register */
   lu_byte iwthabs;  /* instructions issued since last absolute line info */
+  lu_byte needclose;  /* function needs to close upvalues when returning */
 } FuncState;
 
 

src/lprefix.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lprefix.h,v 1.2 2014/12/29 16:54:13 roberto Exp $
+** $Id: lprefix.h $
 ** Definitions for Lua code that must come before any other header file
 ** See Copyright Notice in lua.h
 */

src/lstate.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.c,v 2.155 2018/06/18 12:08:10 roberto Exp $
+** $Id: lstate.c $
 ** Global State
 ** See Copyright Notice in lua.h
 */

@@ -99,24 +99,42 @@
 /*
 ** Increment count of "C calls" and check for overflows. In case of
 ** a stack overflow, check appropriate error ("regular" overflow or
-** overflow while handling stack overflow). If 'nCalls' is larger than
-** LUAI_MAXCCALLS (which means it is handling a "regular" overflow) but
-** smaller than 9/8 of LUAI_MAXCCALLS, does not report an error (to
-** allow overflow handling to work)
-*/
-void luaE_incCcalls (lua_State *L) {
-  if (++L->nCcalls >= LUAI_MAXCCALLS) {
-    if (L->nCcalls == LUAI_MAXCCALLS)
-      luaG_runerror(L, "C stack overflow");
-    else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3)))
-      luaD_throw(L, LUA_ERRERR);  /* error while handing stack error */
+** overflow while handling stack overflow).
+** If 'nCcalls' is larger than LUAI_MAXCSTACK but smaller than
+** LUAI_MAXCSTACK + CSTACKCF (plus 2 to avoid by-one errors), it means
+** it has just entered the "overflow zone", so the function raises an
+** overflow error.
+** If 'nCcalls' is larger than LUAI_MAXCSTACK + CSTACKCF + 2
+** (which means it is already handling an overflow) but smaller than
+** 9/8 of LUAI_MAXCSTACK, does not report an error (to allow message
+** handling to work).
+** Otherwise, report a stack overflow while handling a stack overflow
+** (probably caused by a repeating error in the message handling
+** function).
+*/
+void luaE_enterCcall (lua_State *L) {
+  int ncalls = getCcalls(L);
+  L->nCcalls++;
+  if (ncalls >= LUAI_MAXCSTACK) {  /* possible overflow? */
+    luaE_freeCI(L);  /* release unused CIs */
+    ncalls = getCcalls(L);  /* update call count */
+    if (ncalls >= LUAI_MAXCSTACK) {  /* still overflow? */
+      if (ncalls <= LUAI_MAXCSTACK + CSTACKCF + 2) {
+        /* no error before increments; raise the error now */
+        L->nCcalls += (CSTACKCF + 4);  /* avoid raising it again */
+        luaG_runerror(L, "C stack overflow");
+      }
+      else if (ncalls >= (LUAI_MAXCSTACK + (LUAI_MAXCSTACK >> 3)))
+        luaD_throw(L, LUA_ERRERR);  /* error while handling stack error */
+    }
   }
 }
 
 
 CallInfo *luaE_extendCI (lua_State *L) {
   CallInfo *ci;
-  luaE_incCcalls(L);
+  lua_assert(L->ci->next == NULL);
+  luaE_enterCcall(L);
   ci = luaM_new(L, CallInfo);
   lua_assert(L->ci->next == NULL);
   L->ci->next = ci;

@@ -135,13 +153,13 @@
   CallInfo *ci = L->ci;
   CallInfo *next = ci->next;
   ci->next = NULL;
-  L->nCcalls -= L->nci;  /* to subtract removed elements from 'nCcalls' */
+  L->nCcalls -= L->nci;  /* subtract removed elements from 'nCcalls' */
   while ((ci = next) != NULL) {
     next = ci->next;
     luaM_free(L, ci);
     L->nci--;
   }
-  L->nCcalls += L->nci;  /* to subtract removed elements from 'nCcalls' */
+  L->nCcalls += L->nci;  /* adjust result */
 }
 
 

@@ -151,7 +169,7 @@
 void luaE_shrinkCI (lua_State *L) {
   CallInfo *ci = L->ci;
   CallInfo *next2;  /* next's next */
-  L->nCcalls -= L->nci;  /* to subtract removed elements from 'nCcalls' */
+  L->nCcalls -= L->nci;  /* subtract removed elements from 'nCcalls' */
   /* while there are two nexts */
   while (ci->next != NULL && (next2 = ci->next->next) != NULL) {
     luaM_free(L, ci->next);  /* free next */

@@ -160,7 +178,7 @@
     next2->previous = ci;
     ci = next2;  /* keep next's next */
   }
-  L->nCcalls += L->nci;  /* to subtract removed elements from 'nCcalls' */
+  L->nCcalls += L->nci;  /* adjust result */
 }
 
 

@@ -178,6 +196,8 @@
   ci->next = ci->previous = NULL;
   ci->callstatus = CIST_C;
   ci->func = L1->top;
+  ci->u.c.k = NULL;
+  ci->nresults = 0;
   setnilvalue(s2v(L1->top));  /* 'function' entry for this 'ci' */
   L1->top++;
   ci->top = L1->top + LUA_MINSTACK;

@@ -215,7 +235,8 @@
 
 /*
 ** open parts of the state that may cause memory-allocation errors.
-** ('ttisnil(&g->nilvalue)'' flags that the state was completely build)
+** ('g->nilvalue' being a nil value flags that the state was completely
+** build.)
 */
 static void f_luaopen (lua_State *L, void *ud) {
   global_State *g = G(L);

@@ -250,7 +271,6 @@
   L->allowhook = 1;
   resethookcount(L);
   L->openupval = NULL;
-  L->nny = 1;
   L->status = LUA_OK;
   L->errfunc = 0;
 }

@@ -258,7 +278,7 @@
 
 static void close_state (lua_State *L) {
   global_State *g = G(L);
-  luaF_close(L, L->stack);  /* close all upvalues for this thread */
+  luaF_close(L, L->stack, CLOSEPROTECT);  /* close all upvalues */
   luaC_freeallobjects(L);  /* collect all objects */
   if (ttisnil(&g->nilvalue))  /* closing a fully built state? */
     luai_userstateclose(L);

@@ -301,7 +321,7 @@
 
 void luaE_freethread (lua_State *L, lua_State *L1) {
   LX *l = fromstate(L1);
-  luaF_close(L1, L1->stack);  /* close all upvalues for this thread */
+  luaF_close(L1, L1->stack, NOCLOSINGMETH);  /* close all upvalues */
   lua_assert(L1->openupval == NULL);
   luai_userstatefree(L, L1);
   freestack(L1);

@@ -309,6 +329,29 @@
 }
 
 
+int lua_resetthread (lua_State *L) {
+  CallInfo *ci;
+  int status;
+  lua_lock(L);
+  ci = &L->base_ci;
+  status = luaF_close(L, L->stack, CLOSEPROTECT);
+  setnilvalue(s2v(L->stack));  /* 'function' entry for basic 'ci' */
+  if (status != CLOSEPROTECT)  /* real errors? */
+    luaD_seterrorobj(L, status, L->stack + 1);
+  else {
+    status = LUA_OK;
+    L->top = L->stack + 1;
+  }
+  ci->callstatus = CIST_C;
+  ci->func = L->stack;
+  ci->top = L->top + LUA_MINSTACK;
+  L->ci = ci;
+  L->status = status;
+  lua_unlock(L);
+  return status;
+}
+
+
 LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
   int i;
   lua_State *L;

@@ -325,6 +368,8 @@
   L->next = NULL;
   g->frealloc = f;
   g->ud = ud;
+  g->warnf = NULL;
+  g->ud_warn = NULL;
   g->mainthread = L;
   g->seed = luai_makeseed(L);
   g->gcrunning = 0;  /* no GC while building state */

@@ -340,10 +385,11 @@
   g->finobjsur = g->finobjold = g->finobjrold = NULL;
   g->sweepgc = NULL;
   g->gray = g->grayagain = NULL;
-  g->weak = g->ephemeron = g->allweak = g->protogray = NULL;
+  g->weak = g->ephemeron = g->allweak = NULL;
   g->twups = NULL;
   g->totalbytes = sizeof(LG);
   g->GCdebt = 0;
+  g->lastatomic = 0;
   setivalue(&g->nilvalue, 0);  /* to signal that state is not yet built */
   setgcparam(g->gcpause, LUAI_GCPAUSE);
   setgcparam(g->gcstepmul, LUAI_GCMUL);

@@ -367,3 +413,10 @@
 }
 
 
+void luaE_warning (lua_State *L, const char *msg, int tocont) {
+  lua_WarnFunction wf = G(L)->warnf;
+  if (wf != NULL)
+    wf(G(L)->ud_warn, msg, tocont);
+}
+
+

src/lstate.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.h,v 2.160 2018/06/18 12:08:10 roberto Exp $
+** $Id: lstate.h $
 ** Global State
 ** See Copyright Notice in lua.h
 */

@@ -15,7 +15,6 @@
 
 
 /*
-
 ** Some notes about garbage-collected objects: All objects in Lua must
 ** be kept somehow accessible until being freed, so all objects always
 ** belong to one (and only one) of these lists, using field 'next' of

@@ -27,6 +26,22 @@
 ** 'fixedgc': all objects that are not to be collected (currently
 ** only small strings, such as reserved words).
 **
+** For the generational collector, some of these lists have marks for
+** generations. Each mark points to the first element in the list for
+** that particular generation; that generation goes until the next mark.
+**
+** 'allgc' -> 'survival': new objects;
+** 'survival' -> 'old': objects that survived one collection;
+** 'old' -> 'reallyold': objects that became old in last collection;
+** 'reallyold' -> NULL: objects old for more than one cycle.
+**
+** 'finobj' -> 'finobjsur': new objects marked for finalization;
+** 'finobjsur' -> 'finobjold': survived   """";
+** 'finobjold' -> 'finobjrold': just old  """";
+** 'finobjrold' -> NULL: really old       """".
+*/
+
+/*
 ** Moreover, there is another set of lists that control gray objects.
 ** These lists are linked by fields 'gclist'. (All objects that
 ** can become gray have such a field. The field is not the same

@@ -43,11 +58,57 @@
 ** 'weak': tables with weak values to be cleared;
 ** 'ephemeron': ephemeron tables with white->white entries;
 ** 'allweak': tables with weak keys and/or weak values to be cleared.
-** There is also a list 'protogray' for prototypes that need to have
-** their caches cleared.
+*/
+
 
+
+/*
+** About 'nCcalls': each thread in Lua (a lua_State) keeps a count of
+** how many "C calls" it can do in the C stack, to avoid C-stack overflow.
+** This count is very rough approximation; it considers only recursive
+** functions inside the interpreter, as non-recursive calls can be
+** considered using a fixed (although unknown) amount of stack space.
+**
+** The count itself has two parts: the lower part is the count itself;
+** the higher part counts the number of non-yieldable calls in the stack.
+**
+** Because calls to external C functions can use of unkown amount
+** of space (e.g., functions using an auxiliary buffer), calls
+** to these functions add more than one to the count.
+**
+** The proper count also includes the number of CallInfo structures
+** allocated by Lua, as a kind of "potential" calls. So, when Lua
+** calls a function (and "consumes" one CallInfo), it needs neither to
+** increment nor to check 'nCcalls', as its use of C stack is already
+** accounted for.
 */
 
+/* number of "C stack slots" used by an external C function */
+#define CSTACKCF	10
+
+/* true if this thread does not have non-yieldable calls in the stack */
+#define yieldable(L)		(((L)->nCcalls & 0xffff0000) == 0)
+
+/* real number of C calls */
+#define getCcalls(L)	((L)->nCcalls & 0xffff)
+
+
+/* Increment the number of non-yieldable calls */
+#define incnny(L)	((L)->nCcalls += 0x10000)
+
+/* Decrement the number of non-yieldable calls */
+#define decnny(L)	((L)->nCcalls -= 0x10000)
+
+/* Increment the number of non-yieldable calls and nCcalls */
+#define incXCcalls(L)	((L)->nCcalls += 0x10000 + CSTACKCF)
+
+/* Decrement the number of non-yieldable calls and nCcalls */
+#define decXCcalls(L)	((L)->nCcalls -= 0x10000 + CSTACKCF)
+
+
+
+
+
 
 struct lua_longjmp;  /* defined in ldo.c */
 

@@ -122,9 +183,11 @@
 #define CIST_YPCALL	(1<<3)	/* call is a yieldable protected call */
 #define CIST_TAIL	(1<<4)	/* call was tail called */
 #define CIST_HOOKYIELD	(1<<5)	/* last hook called yielded */
-#define CIST_LEQ	(1<<6)  /* using __lt for __le */
-#define CIST_FIN	(1<<7)  /* call is running a finalizer */
-#define CIST_TRAN	(1<<8)	/* 'ci' has transfer information */
+#define CIST_FIN	(1<<6)  /* call is running a finalizer */
+#define CIST_TRAN	(1<<7)	/* 'ci' has transfer information */
+#if defined(LUA_COMPAT_LT_LE)
+#define CIST_LEQ	(1<<8)  /* using __lt for __le */
+#endif
 
 /* active function is a Lua function */
 #define isLua(ci)	(!((ci)->callstatus & CIST_C))

@@ -146,6 +209,7 @@
   l_mem totalbytes;  /* number of bytes currently allocated - GCdebt */
   l_mem GCdebt;  /* bytes allocated not yet compensated by the collector */
   lu_mem GCestimate;  /* an estimate of the non-garbage memory in use */
+  lu_mem lastatomic;  /* see function 'genstep' in file 'lgc.c' */
   stringtable strt;  /* hash table for strings */
   TValue l_registry;
   TValue nilvalue;  /* a nil value */

@@ -168,7 +232,6 @@
   GCObject *weak;  /* list of tables with weak values */
   GCObject *ephemeron;  /* list of ephemeron tables (weak keys) */
   GCObject *allweak;  /* list of all-weak tables */
-  GCObject *protogray;  /* list of prototypes with "new" caches */
   GCObject *tobefnz;  /* list of userdata to be GC */
   GCObject *fixedgc;  /* list of objects not to be collected */
   /* fields for generational collector */

@@ -185,6 +248,8 @@
   TString *tmname[TM_N];  /* array with tag-method names */
   struct Table *mt[LUA_NUMTAGS];  /* metatables for basic types */
   TString *strcache[STRCACHE_N][STRCACHE_M];  /* cache for strings in API */
+  lua_WarnFunction warnf;  /* warning function */
+  void *ud_warn;         /* auxiliary data to 'warnf' */
 } global_State;
 
 

@@ -193,8 +258,9 @@
 */
 struct lua_State {
   CommonHeader;
-  unsigned short nci;  /* number of items in 'ci' list */
   lu_byte status;
+  lu_byte allowhook;
+  unsigned short nci;  /* number of items in 'ci' list */
   StkId top;  /* first free slot in the stack */
   global_State *l_G;
   CallInfo *ci;  /* call info for current function */

@@ -208,13 +274,11 @@
   CallInfo base_ci;  /* CallInfo for first level (C calling Lua) */
   volatile lua_Hook hook;
   ptrdiff_t errfunc;  /* current error handling function (stack index) */
+  l_uint32 nCcalls;  /* number of allowed nested C calls - 'nci' */
   int stacksize;
   int basehookcount;
   int hookcount;
-  unsigned short nny;  /* number of non-yieldable calls in stack */
-  unsigned short nCcalls;  /* number of nested C calls */
   l_signalT hookmask;
-  lu_byte allowhook;
 };
 
 

@@ -249,7 +313,8 @@
 #define gco2t(o)  check_exp((o)->tt == LUA_TTABLE, &((cast_u(o))->h))
 #define gco2p(o)  check_exp((o)->tt == LUA_TPROTO, &((cast_u(o))->p))
 #define gco2th(o)  check_exp((o)->tt == LUA_TTHREAD, &((cast_u(o))->th))
-#define gco2upv(o)  check_exp((o)->tt == LUA_TUPVAL, &((cast_u(o))->upv))
+#define gco2upv(o)  \
+	check_exp(novariant((o)->tt) == LUA_TUPVAL, &((cast_u(o))->upv))
 
 
 /*

@@ -267,8 +332,11 @@
 LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L);
 LUAI_FUNC void luaE_freeCI (lua_State *L);
 LUAI_FUNC void luaE_shrinkCI (lua_State *L);
-LUAI_FUNC void luaE_incCcalls (lua_State *L);
+LUAI_FUNC void luaE_enterCcall (lua_State *L);
+LUAI_FUNC void luaE_warning (lua_State *L, const char *msg, int tocont);
+
 
+#define luaE_exitCcall(L)	((L)->nCcalls--)
 
 #endif
 

src/lstring.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lstring.c,v 2.66 2018/05/30 14:25:52 roberto Exp $
+** $Id: lstring.c $
 ** String table (keeps all strings handled by Lua)
 ** See Copyright Notice in lua.h
 */

src/lstring.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lstring.h,v 1.64 2018/02/20 16:52:50 roberto Exp $
+** $Id: lstring.h $
 ** String table (keep all strings handled by Lua)
 ** See Copyright Notice in lua.h
 */

@@ -19,7 +19,7 @@
 #define MEMERRMSG       "not enough memory"
 
 
-#define sizelstring(l)  (sizeof(union UTString) + ((l) + 1) * sizeof(char))
+#define sizelstring(l)  (sizeof(TString) + ((l) + 1) * sizeof(char))
 
 #define luaS_newliteral(L, s)	(luaS_newlstr(L, "" s, \
                                  (sizeof(s)/sizeof(char))-1))

src/lstrlib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lstrlib.c,v 1.263 2018/05/25 13:39:32 roberto Exp $
+** $Id: lstrlib.c $
 ** Standard library for string operations and pattern-matching
 ** See Copyright Notice in lua.h
 */

@@ -60,23 +60,50 @@
 }
 
 
-/* translate a relative string position: negative means back from end */
-static lua_Integer posrelat (lua_Integer pos, size_t len) {
-  if (pos >= 0) return pos;
-  else if (0u - (size_t)pos > len) return 0;
-  else return (lua_Integer)len + pos + 1;
+/*
+** translate a relative initial string position
+** (negative means back from end): clip result to [1, inf).
+** The length of any string in Lua must fit in a lua_Integer,
+** so there are no overflows in the casts.
+** The inverted comparison avoids a possible overflow
+** computing '-pos'.
+*/
+static size_t posrelatI (lua_Integer pos, size_t len) {
+  if (pos > 0)
+    return (size_t)pos;
+  else if (pos == 0)
+    return 1;
+  else if (pos < -(lua_Integer)len)  /* inverted comparison */
+    return 1;  /* clip to 1 */
+  else return len + (size_t)pos + 1;
+}
+
+
+/*
+** Gets an optional ending string position from argument 'arg',
+** with default value 'def'.
+** Negative means back from end: clip result to [0, len]
+*/
+static size_t getendpos (lua_State *L, int arg, lua_Integer def,
+                         size_t len) {
+  lua_Integer pos = luaL_optinteger(L, arg, def);
+  if (pos > (lua_Integer)len)
+    return len;
+  else if (pos >= 0)
+    return (size_t)pos;
+  else if (pos < -(lua_Integer)len)
+    return 0;
+  else return len + (size_t)pos + 1;
 }
 
 
 static int str_sub (lua_State *L) {
   size_t l;
   const char *s = luaL_checklstring(L, 1, &l);
-  lua_Integer start = posrelat(luaL_checkinteger(L, 2), l);
-  lua_Integer end = posrelat(luaL_optinteger(L, 3, -1), l);
-  if (start < 1) start = 1;
-  if (end > (lua_Integer)l) end = l;
+  size_t start = posrelatI(luaL_checkinteger(L, 2), l);
+  size_t end = getendpos(L, 3, -1, l);
   if (start <= end)
-    lua_pushlstring(L, s + start - 1, (size_t)(end - start) + 1);
+    lua_pushlstring(L, s + start - 1, (end - start) + 1);
   else lua_pushliteral(L, "");
   return 1;
 }

@@ -149,13 +176,12 @@
 static int str_byte (lua_State *L) {
   size_t l;
   const char *s = luaL_checklstring(L, 1, &l);
-  lua_Integer posi = posrelat(luaL_optinteger(L, 2, 1), l);
-  lua_Integer pose = posrelat(luaL_optinteger(L, 3, posi), l);
+  lua_Integer pi = luaL_optinteger(L, 2, 1);
+  size_t posi = posrelatI(pi, l);
+  size_t pose = getendpos(L, 3, pi, l);
   int n, i;
-  if (posi < 1) posi = 1;
-  if (pose > (lua_Integer)l) pose = l;
   if (posi > pose) return 0;  /* empty interval; return no values */
-  if (pose - posi >= INT_MAX)  /* arithmetic overflow? */
+  if (pose - posi >= (size_t)INT_MAX)  /* arithmetic overflow? */
     return luaL_error(L, "string slice too long");
   n = (int)(pose -  posi) + 1;
   luaL_checkstack(L, n, "string slice too long");

@@ -171,8 +197,8 @@
   luaL_Buffer b;
   char *p = luaL_buffinitsize(L, &b, n);
   for (i=1; i<=n; i++) {
-    lua_Integer c = luaL_checkinteger(L, i);
-    luaL_argcheck(L, uchar(c) == c, i, "value out of range");
+    lua_Unsigned c = (lua_Unsigned)luaL_checkinteger(L, i);
+    luaL_argcheck(L, c <= (lua_Unsigned)UCHAR_MAX, i, "value out of range");
     p[i - 1] = uchar(c);
   }
   luaL_pushresultsize(&b, n);

@@ -634,25 +660,46 @@
 }
 
 
-static void push_onecapture (MatchState *ms, int i, const char *s,
-                                                    const char *e) {
+/*
+** get information about the i-th capture. If there are no captures
+** and 'i==0', return information about the whole match, which
+** is the range 's'..'e'. If the capture is a string, return
+** its length and put its address in '*cap'. If it is an integer
+** (a position), push it on the stack and return CAP_POSITION.
+*/
+static size_t get_onecapture (MatchState *ms, int i, const char *s,
+                              const char *e, const char **cap) {
   if (i >= ms->level) {
-    if (i == 0)  /* ms->level == 0, too */
-      lua_pushlstring(ms->L, s, e - s);  /* add whole match */
-    else
+    if (i != 0)
       luaL_error(ms->L, "invalid capture index %%%d", i + 1);
+    *cap = s;
+    return e - s;
   }
   else {
-    ptrdiff_t l = ms->capture[i].len;
-    if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture");
-    if (l == CAP_POSITION)
+    ptrdiff_t capl = ms->capture[i].len;
+    *cap = ms->capture[i].init;
+    if (capl == CAP_UNFINISHED)
+      luaL_error(ms->L, "unfinished capture");
+    else if (capl == CAP_POSITION)
       lua_pushinteger(ms->L, (ms->capture[i].init - ms->src_init) + 1);
-    else
-      lua_pushlstring(ms->L, ms->capture[i].init, l);
+    return capl;
   }
 }
 
 
+/*
+** Push the i-th capture on the stack.
+*/
+static void push_onecapture (MatchState *ms, int i, const char *s,
+                                                    const char *e) {
+  const char *cap;
+  ptrdiff_t l = get_onecapture(ms, i, s, e, &cap);
+  if (l != CAP_POSITION)
+    lua_pushlstring(ms->L, cap, l);
+  /* else position was already pushed */
+}
+
+
 static int push_captures (MatchState *ms, const char *s, const char *e) {
   int i;
   int nlevels = (ms->level == 0 && s) ? 1 : ms->level;

@@ -695,16 +742,15 @@
   size_t ls, lp;
   const char *s = luaL_checklstring(L, 1, &ls);
   const char *p = luaL_checklstring(L, 2, &lp);
-  lua_Integer init = posrelat(luaL_optinteger(L, 3, 1), ls);
-  if (init < 1) init = 1;
-  else if (init > (lua_Integer)ls + 1) {  /* start after string's end? */
+  size_t init = posrelatI(luaL_optinteger(L, 3, 1), ls) - 1;
+  if (init > ls) {  /* start after string's end? */
     lua_pushnil(L);  /* cannot find anything */
     return 1;
   }
   /* explicit request or no special characters? */
   if (find && (lua_toboolean(L, 4) || nospecials(p, lp))) {
     /* do a plain search */
-    const char *s2 = lmemfind(s + init - 1, ls - (size_t)init + 1, p, lp);
+    const char *s2 = lmemfind(s + init, ls - init, p, lp);
     if (s2) {
       lua_pushinteger(L, (s2 - s) + 1);
       lua_pushinteger(L, (s2 - s) + lp);

@@ -713,7 +759,7 @@
   }
   else {
     MatchState ms;
-    const char *s1 = s + init - 1;
+    const char *s1 = s + init;
     int anchor = (*p == '^');
     if (anchor) {
       p++; lp--;  /* skip anchor character */

@@ -777,11 +823,14 @@
   size_t ls, lp;
   const char *s = luaL_checklstring(L, 1, &ls);
   const char *p = luaL_checklstring(L, 2, &lp);
+  size_t init = posrelatI(luaL_optinteger(L, 3, 1), ls) - 1;
   GMatchState *gm;
-  lua_settop(L, 2);  /* keep them on closure to avoid being collected */
+  lua_settop(L, 2);  /* keep strings on closure to avoid being collected */
   gm = (GMatchState *)lua_newuserdatauv(L, sizeof(GMatchState), 0);
+  if (init > ls)  /* start after string's end? */
+    init = ls + 1;  /* avoid overflows in 's + init' */
   prepstate(&gm->ms, L, s, ls, p, lp);
-  gm->src = s; gm->p = p; gm->lastmatch = NULL;
+  gm->src = s + init; gm->p = p; gm->lastmatch = NULL;
   lua_pushcclosure(L, gmatch_aux, 3);
   return 1;
 }

@@ -789,60 +838,72 @@
 
 static void add_s (MatchState *ms, luaL_Buffer *b, const char *s,
                                                    const char *e) {
-  size_t l, i;
+  size_t l;
   lua_State *L = ms->L;
   const char *news = lua_tolstring(L, 3, &l);
-  for (i = 0; i < l; i++) {
-    if (news[i] != L_ESC)
-      luaL_addchar(b, news[i]);
-    else {
-      i++;  /* skip ESC */
-      if (!isdigit(uchar(news[i]))) {
-        if (news[i] != L_ESC)
-          luaL_error(L, "invalid use of '%c' in replacement string", L_ESC);
-        luaL_addchar(b, news[i]);
-      }
-      else if (news[i] == '0')
-          luaL_addlstring(b, s, e - s);
-      else {
-        push_onecapture(ms, news[i] - '1', s, e);
-        luaL_tolstring(L, -1, NULL);  /* if number, convert it to string */
-        lua_remove(L, -2);  /* remove original value */
-        luaL_addvalue(b);  /* add capture to accumulated result */
-      }
+  const char *p;
+  while ((p = (char *)memchr(news, L_ESC, l)) != NULL) {
+    luaL_addlstring(b, news, p - news);
+    p++;  /* skip ESC */
+    if (*p == L_ESC)  /* '%%' */
+      luaL_addchar(b, *p);
+    else if (*p == '0')  /* '%0' */
+        luaL_addlstring(b, s, e - s);
+    else if (isdigit(uchar(*p))) {  /* '%n' */
+      const char *cap;
+      ptrdiff_t resl = get_onecapture(ms, *p - '1', s, e, &cap);
+      if (resl == CAP_POSITION)
+        luaL_addvalue(b);  /* add position to accumulated result */
+      else
+        luaL_addlstring(b, cap, resl);
     }
+    else
+      luaL_error(L, "invalid use of '%c' in replacement string", L_ESC);
+    l -= p + 1 - news;
+    news = p + 1;
   }
+  luaL_addlstring(b, news, l);
 }
 
 
-static void add_value (MatchState *ms, luaL_Buffer *b, const char *s,
-                                       const char *e, int tr) {
+/*
+** Add the replacement value to the string buffer 'b'.
+** Return true if the original string was changed. (Function calls and
+** table indexing resulting in nil or false do not change the subject.)
+*/
+static int add_value (MatchState *ms, luaL_Buffer *b, const char *s,
+                                      const char *e, int tr) {
   lua_State *L = ms->L;
   switch (tr) {
-    case LUA_TFUNCTION: {
+    case LUA_TFUNCTION: {  /* call the function */
       int n;
-      lua_pushvalue(L, 3);
-      n = push_captures(ms, s, e);
-      lua_call(L, n, 1);
+      lua_pushvalue(L, 3);  /* push the function */
+      n = push_captures(ms, s, e);  /* all captures as arguments */
+      lua_call(L, n, 1);  /* call it */
       break;
     }
-    case LUA_TTABLE: {
-      push_onecapture(ms, 0, s, e);
+    case LUA_TTABLE: {  /* index the table */
+      push_onecapture(ms, 0, s, e);  /* first capture is the index */
       lua_gettable(L, 3);
       break;
     }
     default: {  /* LUA_TNUMBER or LUA_TSTRING */
-      add_s(ms, b, s, e);
-      return;
+      add_s(ms, b, s, e);  /* add value to the buffer */
+      return 1;  /* something changed */
     }
   }
   if (!lua_toboolean(L, -1)) {  /* nil or false? */
-    lua_pop(L, 1);
-    lua_pushlstring(L, s, e - s);  /* keep original text */
+    lua_pop(L, 1);  /* remove value */
+    luaL_addlstring(b, s, e - s);  /* keep original text */
+    return 0;  /* no changes */
   }
   else if (!lua_isstring(L, -1))
-    luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1));
-  luaL_addvalue(b);  /* add result to accumulator */
+    return luaL_error(L, "invalid replacement value (a %s)",
+                         luaL_typename(L, -1));
+  else {
+    luaL_addvalue(b);  /* add result to accumulator */
+    return 1;  /* something changed */
+  }
 }
 
 

@@ -855,11 +916,12 @@
   lua_Integer max_s = luaL_optinteger(L, 4, srcl + 1);  /* max replacements */
   int anchor = (*p == '^');
   lua_Integer n = 0;  /* replacement count */
+  int changed = 0;  /* change flag */
   MatchState ms;
   luaL_Buffer b;
-  luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING ||
+  luaL_argexpected(L, tr == LUA_TNUMBER || tr == LUA_TSTRING ||
                    tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3,
-                      "string/function/table expected");
+                      "string/function/table");
   luaL_buffinit(L, &b);
   if (anchor) {
     p++; lp--;  /* skip anchor character */

@@ -870,7 +932,7 @@
     reprepstate(&ms);  /* (re)prepare state for new match */
     if ((e = match(&ms, src, p)) != NULL && e != lastmatch) {  /* match? */
       n++;
-      add_value(&ms, &b, src, e, tr);  /* add replacement to buffer */
+      changed = add_value(&ms, &b, src, e, tr) | changed;
       src = lastmatch = e;
     }
     else if (src < ms.src_end)  /* otherwise, skip one character */

@@ -878,8 +940,12 @@
     else break;  /* end of subject */
     if (anchor) break;
   }
-  luaL_addlstring(&b, src, ms.src_end-src);
-  luaL_pushresult(&b);
+  if (!changed)  /* no changes? */
+    lua_pushvalue(L, 1);  /* return original string */
+  else {  /* something changed */
+    luaL_addlstring(&b, src, ms.src_end-src);
+    luaL_pushresult(&b);  /* create and return new string */
+  }
   lua_pushinteger(L, n);  /* number of substitutions */
   return 2;
 }

@@ -972,13 +1038,23 @@
 
 
 /*
-** Maximum size of each formatted item. This maximum size is produced
+** Maximum size for items formatted with '%f'. This size is produced
 ** by format('%.99f', -maxfloat), and is equal to 99 + 3 ('-', '.',
 ** and '\0') + number of decimal digits to represent maxfloat (which
-** is maximum exponent + 1). (99+3+1 then rounded to 120 for "extra
-** expenses", such as locale-dependent stuff)
+** is maximum exponent + 1). (99+3+1, adding some extra, 110)
+*/
+#define MAX_ITEMF	(110 + l_mathlim(MAX_10_EXP))
+
+
+/*
+** All formats except '%f' do not need that large limit.  The other
+** float formats use exponents, so that they fit in the 99 limit for
+** significant digits; 's' for large strings and 'q' add items directly
+** to the buffer; all integer formats also fit in the 99 limit.  The
+** worst case are floats: they may need 99 significant digits, plus
+** '0x', '-', '.', 'e+XXXX', and '\0'. Adding some extra, 120.
 */
-#define MAX_ITEM        (120 + l_mathlim(MAX_10_EXP))
+#define MAX_ITEM	120
 
 
 /* valid flags in a format specification */

@@ -1128,36 +1204,49 @@
       luaL_addchar(&b, *strfrmt++);  /* %% */
     else { /* format item */
       char form[MAX_FORMAT];  /* to store the format ('%...') */
-      char *buff = luaL_prepbuffsize(&b, MAX_ITEM);  /* to put formatted item */
+      int maxitem = MAX_ITEM;
+      char *buff = luaL_prepbuffsize(&b, maxitem);  /* to put formatted item */
       int nb = 0;  /* number of bytes in added item */
       if (++arg > top)
-        luaL_argerror(L, arg, "no value");
+        return luaL_argerror(L, arg, "no value");
       strfrmt = scanformat(L, strfrmt, form);
       switch (*strfrmt++) {
         case 'c': {
-          nb = l_sprintf(buff, MAX_ITEM, form, (int)luaL_checkinteger(L, arg));
+          nb = l_sprintf(buff, maxitem, form, (int)luaL_checkinteger(L, arg));
           break;
         }
         case 'd': case 'i':
         case 'o': case 'u': case 'x': case 'X': {
           lua_Integer n = luaL_checkinteger(L, arg);
           addlenmod(form, LUA_INTEGER_FRMLEN);
-          nb = l_sprintf(buff, MAX_ITEM, form, (LUAI_UACINT)n);
+          nb = l_sprintf(buff, maxitem, form, (LUAI_UACINT)n);
           break;
         }
         case 'a': case 'A':
           addlenmod(form, LUA_NUMBER_FRMLEN);
-          nb = lua_number2strx(L, buff, MAX_ITEM, form,
+          nb = lua_number2strx(L, buff, maxitem, form,
                                   luaL_checknumber(L, arg));
           break;
         case 'e': case 'E': case 'f':
         case 'g': case 'G': {
           lua_Number n = luaL_checknumber(L, arg);
+          if (*(strfrmt - 1) == 'f' && l_mathop(fabs)(n) >= 1e100) {
+            /* 'n' needs more than 99 digits */
+            maxitem = MAX_ITEMF;  /* extra space for '%f' */
+            buff = luaL_prepbuffsize(&b, maxitem);
+          }
           addlenmod(form, LUA_NUMBER_FRMLEN);
-          nb = l_sprintf(buff, MAX_ITEM, form, (LUAI_UACNUMBER)n);
+          nb = l_sprintf(buff, maxitem, form, (LUAI_UACNUMBER)n);
+          break;
+        }
+        case 'p': {
+          const void *p = lua_topointer(L, arg);
+          nb = l_sprintf(buff, maxitem, form, p);
           break;
         }
         case 'q': {
+          if (form[2] != '\0')  /* modifiers? */
+            return luaL_error(L, "specifier '%%q' cannot have modifiers");
           addliteral(L, &b, arg);
           break;
         }

@@ -1173,18 +1262,17 @@
               luaL_addvalue(&b);  /* keep entire string */
             }
             else {  /* format the string into 'buff' */
-              nb = l_sprintf(buff, MAX_ITEM, form, s);
+              nb = l_sprintf(buff, maxitem, form, s);
               lua_pop(L, 1);  /* remove result from 'luaL_tolstring' */
             }
           }
           break;
         }
         default: {  /* also treat cases 'pnLlh' */
-          return luaL_error(L, "invalid option '%%%c' to 'format'",
-                               *(strfrmt - 1));
+          return luaL_error(L, "invalid conversion '%s' to 'format'", form);
         }
       }
-      lua_assert(nb < MAX_ITEM);
+      lua_assert(nb < maxitem);
       luaL_addsize(&b, nb);
     }
   }

@@ -1573,7 +1661,7 @@
   const char *fmt = luaL_checkstring(L, 1);
   size_t ld;
   const char *data = luaL_checklstring(L, 2, &ld);
-  size_t pos = (size_t)posrelat(luaL_optinteger(L, 3, 1), ld) - 1;
+  size_t pos = posrelatI(luaL_optinteger(L, 3, 1), ld) - 1;
   int n = 0;  /* number of results */
   luaL_argcheck(L, pos <= ld, 3, "initial position out of string");
   initheader(L, &h);

src/ltable.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltable.c,v 2.140 2018/06/15 14:18:40 roberto Exp $
+** $Id: ltable.c $
 ** Lua tables (hash)
 ** See Copyright Notice in lua.h
 */

@@ -48,8 +48,8 @@
 
 /*
 ** MAXASIZE is the maximum size of the array part. It is the minimum
-** between 2^MAXABITS and the maximum size such that, measured in bytes,
-** it fits in a 'size_t'.
+** between 2^MAXABITS and the maximum size that, measured in bytes,
+** fits in a 'size_t'.
 */
 #define MAXASIZE	luaM_limitN(1u << MAXABITS, TValue)
 

@@ -214,8 +214,8 @@
     size |= (size >> 4);
     size |= (size >> 8);
     size |= (size >> 16);
-#if (INT_MAX >> 30 >> 1) > 0
-    size |= (size >> 32);  /* int has more than 32 bits */
+#if (UINT_MAX >> 30) > 3
+    size |= (size >> 32);  /* unsigned int has more than 32 bits */
 #endif
     size++;
     lua_assert(ispow2(size) && size/2 < t->alimit && t->alimit < size);

@@ -269,7 +269,7 @@
 ** the array part of a table, 0 otherwise.
 */
 static unsigned int arrayindex (lua_Integer k) {
-  if (0 < k && l_castS2U(k) <= MAXASIZE)
+  if (l_castS2U(k) - 1u < MAXASIZE)  /* 'k' in [1, MAXASIZE]? */
     return cast_uint(k);  /* 'key' is an appropriate array index */
   else
     return 0;

@@ -286,7 +286,7 @@
   unsigned int i;
   if (ttisnil(key)) return 0;  /* first iteration */
   i = ttisinteger(key) ? arrayindex(ivalue(key)) : 0;
-  if (i != 0 && i <= asize)  /* is 'key' inside array part? */
+  if (i - 1u < asize)  /* is 'key' inside array part? */
     return i;  /* yes; that's the index */
   else {
     const TValue *n = getgeneric(t, key);

@@ -678,7 +678,7 @@
 ** changing the real size of the array).
 */
 const TValue *luaH_getint (Table *t, lua_Integer key) {
-  if (l_castS2U(key) - 1u < t->alimit)  /* (1 <= key && key <= t->alimit)? */
+  if (l_castS2U(key) - 1u < t->alimit)  /* 'key' in [1, t->alimit]? */
     return &t->array[key - 1];
   else if (!limitequalsasize(t) &&  /* key still may be in the array part? */
            (l_castS2U(key) == t->alimit + 1 ||

src/ltable.h

@@ -1,5 +1,5 @@
 /*
-** $Id: ltable.h,v 2.28 2018/06/15 14:14:20 roberto Exp $
+** $Id: ltable.h $
 ** Lua tables (hash)
 ** See Copyright Notice in lua.h
 */

src/ltablib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltablib.c,v 1.97 2018/04/04 14:23:41 roberto Exp $
+** $Id: ltablib.c $
 ** Library for Table Manipulation
 ** See Copyright Notice in lua.h
 */

@@ -69,7 +69,9 @@
     case 3: {
       lua_Integer i;
       pos = luaL_checkinteger(L, 2);  /* 2nd argument is the position */
-      luaL_argcheck(L, 1 <= pos && pos <= e, 2, "position out of bounds");
+      /* check whether 'pos' is in [1, e] */
+      luaL_argcheck(L, (lua_Unsigned)pos - 1u < (lua_Unsigned)e, 2,
+                       "position out of bounds");
       for (i = e; i > pos; i--) {  /* move up elements */
         lua_geti(L, 1, i - 1);
         lua_seti(L, 1, i);  /* t[i] = t[i - 1] */

@@ -89,7 +91,9 @@
   lua_Integer size = aux_getn(L, 1, TAB_RW);
   lua_Integer pos = luaL_optinteger(L, 2, size);
   if (pos != size)  /* validate 'pos' if given */
-    luaL_argcheck(L, 1 <= pos && pos <= size + 1, 1, "position out of bounds");
+    /* check whether 'pos' is in [1, size + 1] */
+    luaL_argcheck(L, (lua_Unsigned)pos - 1u <= (lua_Unsigned)size, 1,
+                     "position out of bounds");
   lua_geti(L, 1, pos);  /* result = t[pos] */
   for ( ; pos < size; pos++) {
     lua_geti(L, 1, pos + 1);

@@ -295,7 +299,7 @@
   /* loop invariant: a[lo .. i] <= P <= a[j .. up] */
   for (;;) {
     /* next loop: repeat ++i while a[i] < P */
-    while (lua_geti(L, 1, ++i), sort_comp(L, -1, -2)) {
+    while ((void)lua_geti(L, 1, ++i), sort_comp(L, -1, -2)) {
       if (i == up - 1)  /* a[i] < P  but a[up - 1] == P  ?? */
         luaL_error(L, "invalid order function for sorting");
       lua_pop(L, 1);  /* remove a[i] */

src/ltm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltm.c,v 2.70 2018/06/15 19:31:22 roberto Exp $
+** $Id: ltm.c $
 ** Tag methods
 ** See Copyright Notice in lua.h
 */

@@ -43,7 +43,7 @@
     "__div", "__idiv",
     "__band", "__bor", "__bxor", "__shl", "__shr",
     "__unm", "__bnot", "__lt", "__le",
-    "__concat", "__call"
+    "__concat", "__call", "__close"
   };
   int i;
   for (i=0; i<TM_N; i++) {

@@ -176,7 +176,7 @@
 }
 
 
-void luaT_trybiniTM (lua_State *L, const TValue *p1, int i2,
+void luaT_trybiniTM (lua_State *L, const TValue *p1, lua_Integer i2,
                                    int inv, StkId res, TMS event) {
   TValue aux;
   setivalue(&aux, i2);

@@ -188,6 +188,7 @@
                       TMS event) {
   if (callbinTM(L, p1, p2, L->top, event))  /* try original event */
     return !l_isfalse(s2v(L->top));
+#if defined(LUA_COMPAT_LT_LE)
   else if (event == TM_LE) {
       /* try '!(p2 < p1)' for '(p1 <= p2)' */
       L->ci->callstatus |= CIST_LEQ;  /* mark it is doing 'lt' for 'le' */

@@ -197,15 +198,20 @@
       }
       /* else error will remove this 'ci'; no need to clear mark */
   }
+#endif
   luaG_ordererror(L, p1, p2);  /* no metamethod found */
   return 0;  /* to avoid warnings */
 }
 
 
 int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2,
-                       int inv, TMS event) {
+                       int inv, int isfloat, TMS event) {
   TValue aux; const TValue *p2;
-  setivalue(&aux, v2);
+  if (isfloat) {
+    setfltvalue(&aux, cast_num(v2));
+  }
+  else
+    setivalue(&aux, v2);
   if (inv) {  /* arguments were exchanged? */
     p2 = p1; p1 = &aux;  /* correct them */
   }

src/ltm.h

@@ -1,5 +1,5 @@
 /*
-** $Id: ltm.h,v 2.39 2018/06/18 12:51:05 roberto Exp $
+** $Id: ltm.h $
 ** Tag methods
 ** See Copyright Notice in lua.h
 */

@@ -40,6 +40,7 @@
   TM_LE,
   TM_CONCAT,
   TM_CALL,
+  TM_CLOSE,
   TM_N		/* number of elements in the enum */
 } TMS;
 

@@ -76,12 +77,12 @@
                               StkId res, TMS event);
 LUAI_FUNC void luaT_trybinassocTM (lua_State *L, const TValue *p1,
        const TValue *p2, StkId res, int inv, TMS event);
-LUAI_FUNC void luaT_trybiniTM (lua_State *L, const TValue *p1, int i2,
+LUAI_FUNC void luaT_trybiniTM (lua_State *L, const TValue *p1, lua_Integer i2,
                                int inv, StkId res, TMS event);
 LUAI_FUNC int luaT_callorderTM (lua_State *L, const TValue *p1,
                                 const TValue *p2, TMS event);
 LUAI_FUNC int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2,
-                                 int inv, TMS event);
+                                 int inv, int isfloat, TMS event);
 
 LUAI_FUNC void luaT_adjustvarargs (lua_State *L, int nfixparams,
                                    struct CallInfo *ci, const Proto *p);

src/lua.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lua.c,v 1.235 2018/03/16 14:23:08 roberto Exp $
+** $Id: lua.c $
 ** Lua stand-alone interpreter
 ** See Copyright Notice in lua.h
 */

@@ -383,8 +383,7 @@
 
 #include <readline/readline.h>
 #include <readline/history.h>
-#define lua_initreadline(L)  \
-	((void)L, rl_readline_name="lua", rl_inhibit_completion=1)
+#define lua_initreadline(L)	((void)L, rl_readline_name="lua")
 #define lua_readline(L,b,p)	((void)L, ((b)=readline(p)) != NULL)
 #define lua_saveline(L,line)	((void)L, add_history(line))
 #define lua_freeline(L,b)	((void)L, free(b))

src/lua.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lua.h,v 1.347 2018/06/18 12:08:10 roberto Exp $
+** $Id: lua.h $
 ** Lua - A Scripting Language
 ** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
 ** See Copyright Notice at the end of this file

@@ -18,12 +18,14 @@
 
 #define LUA_VERSION_MAJOR	"5"
 #define LUA_VERSION_MINOR	"4"
-#define LUA_VERSION_NUM		504
 #define LUA_VERSION_RELEASE	"0"
 
+#define LUA_VERSION_NUM			504
+#define LUA_VERSION_RELEASE_NUM		(LUA_VERSION_NUM * 100 + 0)
+
 #define LUA_VERSION	"Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
 #define LUA_RELEASE	LUA_VERSION "." LUA_VERSION_RELEASE
-#define LUA_COPYRIGHT	LUA_RELEASE "  Copyright (C) 1994-2018 Lua.org, PUC-Rio"
+#define LUA_COPYRIGHT	LUA_RELEASE "  Copyright (C) 1994-2019 Lua.org, PUC-Rio"
 #define LUA_AUTHORS	"R. Ierusalimschy, L. H. de Figueiredo, W. Celes"
 
 

@@ -49,8 +51,7 @@
 #define LUA_ERRRUN	2
 #define LUA_ERRSYNTAX	3
 #define LUA_ERRMEM	4
-#define LUA_ERRGCMM	5
-#define LUA_ERRERR	6
+#define LUA_ERRERR	5
 
 
 typedef struct lua_State lua_State;

@@ -124,6 +125,13 @@
 typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);
 
 
+/*
+** Type for warning functions
+*/
+typedef void (*lua_WarnFunction) (void *ud, const char *msg, int tocont);
+
+
+
 
 /*
 ** generic extra include file

@@ -145,6 +153,7 @@
 LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud);
 LUA_API void       (lua_close) (lua_State *L);
 LUA_API lua_State *(lua_newthread) (lua_State *L);
+LUA_API int        (lua_resetthread) (lua_State *L);
 
 LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf);
 

@@ -297,6 +306,13 @@
 
 
 /*
+** Warning-related functions
+*/
+LUA_API void (lua_setwarnf) (lua_State *L, lua_WarnFunction f, void *ud);
+LUA_API void (lua_warning)  (lua_State *L, const char *msg, int tocont);
+
+
+/*
 ** garbage-collection function and options
 */
 

@@ -331,6 +347,8 @@
 LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud);
 LUA_API void      (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud);
 
+LUA_API void  (lua_toclose) (lua_State *L, int idx);
+
 
 /*
 ** {==============================================================

@@ -451,6 +469,7 @@
   const char *namewhat;	/* (n) 'global', 'local', 'field', 'method' */
   const char *what;	/* (S) 'Lua', 'C', 'main', 'tail' */
   const char *source;	/* (S) */
+  size_t srclen;	/* (S) */
   int currentline;	/* (l) */
   int linedefined;	/* (S) */
   int lastlinedefined;	/* (S) */

@@ -469,7 +488,7 @@
 
 
 /******************************************************************************
-* Copyright (C) 1994-2018 Lua.org, PUC-Rio.
+* Copyright (C) 1994-2019 Lua.org, PUC-Rio.
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the

src/luac.c

@@ -18,7 +18,10 @@
 #include "lua.h"
 #include "lauxlib.h"
 
+#include "ldebug.h"
 #include "lobject.h"
+#include "lopcodes.h"
+#include "lopnames.h"
 #include "lstate.h"
 #include "lundump.h"
 

@@ -209,20 +212,8 @@
 ** print bytecodes
 */
 
-#include <ctype.h>
-#include <stdio.h>
-
-#define luac_c
-#define LUA_CORE
-#define LUAI_DEFOPNAMES
-
-#include "ldebug.h"
-#include "lobject.h"
-#include "lopcodes.c"
-
 #define UPVALNAME(x) ((f->upvalues[x].name) ? getstr(f->upvalues[x].name) : "-")
 #define VOID(p) ((const void*)(p))
-#define getfuncline(f,pc) luaG_getfuncline((Proto *)f,pc)
 
 static void PrintString(const TString* ts)
 {

@@ -238,28 +229,28 @@
 	printf("\\\"");
 	break;
    case '\\':
-   	printf("\\\\");
+	printf("\\\\");
 	break;
    case '\a':
-   	printf("\\a");
+	printf("\\a");
 	break;
    case '\b':
-   	printf("\\b");
+	printf("\\b");
 	break;
    case '\f':
-   	printf("\\f");
+	printf("\\f");
 	break;
    case '\n':
-   	printf("\\n");
+	printf("\\n");
 	break;
    case '\r':
-   	printf("\\r");
+	printf("\\r");
 	break;
    case '\t':
-   	printf("\\t");
+	printf("\\t");
 	break;
    case '\v':
-   	printf("\\v");
+	printf("\\v");
 	break;
    default:
 	if (isprint(c)) printf("%c",c); else printf("\\%03d",c);

@@ -269,6 +260,34 @@
  printf("\"");
 }
 
+static void PrintType(const Proto* f, int i)
+{
+ const TValue* o=&f->k[i];
+ switch (ttypetag(o))
+ {
+  case LUA_TNIL:
+  	printf("N");
+	break;
+  case LUA_TBOOLEAN:
+  	printf("B");
+	break;
+  case LUA_TNUMFLT:
+  	printf("F");
+	break;
+  case LUA_TNUMINT:
+  	printf("I");
+	break;
+  case LUA_TSHRSTR:
+  case LUA_TLNGSTR:
+  	printf("S");
+	break;
+  default:				/* cannot happen */
+	printf("?%d",ttypetag(o));
+	break;
+ }
+ printf("\t");
+}
+
 static void PrintConstant(const Proto* f, int i)
 {
  const TValue* o=&f->k[i];

@@ -296,7 +315,7 @@
 	PrintString(tsvalue(o));
 	break;
   default:				/* cannot happen */
-	printf("? type=%d",ttypetag(o));
+	printf("?%d",ttypetag(o));
 	break;
  }
 }

@@ -318,10 +337,10 @@
   int sc=GETARG_sC(i);
   int sbx=GETARG_sBx(i);
   int isk=GETARG_k(i);
-  int line=getfuncline(f,pc);
+  int line=luaG_getfuncline(f,pc);
   printf("\t%d\t",pc+1);
   if (line>0) printf("[%d]\t",line); else printf("[-]\t");
-  printf("%-9s\t",luaP_opnames[o]);
+  printf("%-9s\t",opnames[o]);
   switch (o)
   {
    case OP_MOVE:

@@ -418,17 +437,45 @@
    case OP_IDIVI:
 	printf("%d %d %d",a,b,sc);
 	break;
+   case OP_ADDK:
+	printf("%d %d %d",a,b,c);
+	printf("\t; "); PrintConstant(f,c);
+	break;
+   case OP_SUBK:
+	printf("%d %d %d",a,b,c);
+	printf("\t; "); PrintConstant(f,c);
+	break;
+   case OP_MULK:
+	printf("%d %d %d",a,b,c);
+	printf("\t; "); PrintConstant(f,c);
+	break;
+   case OP_MODK:
+	printf("%d %d %d",a,b,c);
+	printf("\t; "); PrintConstant(f,c);
+	break;
+   case OP_POWK:
+	printf("%d %d %d",a,b,c);
+	printf("\t; "); PrintConstant(f,c);
+	break;
+   case OP_DIVK:
+	printf("%d %d %d",a,b,c);
+	printf("\t; "); PrintConstant(f,c);
+	break;
+   case OP_IDIVK:
+	printf("%d %d %d",a,b,c);
+	printf("\t; "); PrintConstant(f,c);
+	break;
    case OP_BANDK:
 	printf("%d %d %d",a,b,c);
-	printf("\t; "); PrintConstant(f,c); 
+	printf("\t; "); PrintConstant(f,c);
 	break;
    case OP_BORK:
 	printf("%d %d %d",a,b,c);
-	printf("\t; "); PrintConstant(f,c); 
+	printf("\t; "); PrintConstant(f,c);
 	break;
    case OP_BXORK:
 	printf("%d %d %d",a,b,c);
-	printf("\t; "); PrintConstant(f,c); 
+	printf("\t; "); PrintConstant(f,c);
 	break;
    case OP_SHRI:
 	printf("%d %d %d",a,b,c);

@@ -490,6 +537,9 @@
    case OP_CLOSE:
 	printf("%d",a);
 	break;
+   case OP_TBC:
+	printf("%d",a);
+	break;
    case OP_JMP:
 	printf("%d",GETARG_sJ(i));
 	printf("\t; to %d",GETARG_sJ(i)+pc+2);

@@ -531,8 +581,8 @@
    case OP_CALL:
 	printf("%d %d %d",a,b,c);
 	printf("\t; ");
-   	if (b==0) printf("all in "); else printf("%d in ",b-1);
-   	if (c==0) printf("all out"); else printf("%d out",c-1);
+	if (b==0) printf("all in "); else printf("%d in ",b-1);
+	if (c==0) printf("all out"); else printf("%d out",c-1);
 	break;
    case OP_TAILCALL:
 	printf("%d %d %d",a,b,c);

@@ -541,26 +591,22 @@
    case OP_RETURN:
 	printf("%d %d %d",a,b,c);
 	printf("\t; ");
-   	if (b==0) printf("all out"); else printf("%d out",b-1);
+	if (b==0) printf("all out"); else printf("%d out",b-1);
 	break;
    case OP_RETURN0:
 	break;
    case OP_RETURN1:
 	printf("%d",a);
 	break;
-   case OP_FORLOOP1:
+   case OP_FORLOOP:
 	printf("%d %d",a,bx);
 	printf("\t; to %d",pc-bx+2);
 	break;
-   case OP_FORPREP1:
+   case OP_FORPREP:
 	printf("%d %d",a,bx);
 	printf("\t; to %d",pc+bx+2);
 	break;
-   case OP_FORLOOP:
-	printf("%d %d",a,bx);
-	printf("\t; to %d",pc-bx+2);
-	break;
-   case OP_FORPREP:
+   case OP_TFORPREP:
 	printf("%d %d",a,bx);
 	printf("\t; to %d",pc+bx+2);
 	break;

@@ -581,53 +627,23 @@
    case OP_VARARG:
 	printf("%d %d",a,c);
 	printf("\t; ");
-   	if (c==0) printf("all out"); else printf("%d out",c-1);
+	if (c==0) printf("all out"); else printf("%d out",c-1);
 	break;
-   case OP_PREPVARARG:
+   case OP_VARARGPREP:
 	printf("%d",a);
 	break;
    case OP_EXTRAARG:
 	printf("%d",ax);
 	printf("\t; "); PrintConstant(f,ax);
 	break;
+   //default: printf("not handled"); break;
+	//printf("%d %d %d",a,b,c);
+	//break;
   }
   printf("\n");
  }
 }
 
-static void riPrintCode(const Proto* p)
-{
- const Instruction* code=p->code;
- int pc,n=p->sizecode;
- for (pc=0; pc<n; pc++)
- {
-  Instruction i = code[pc];
-  OpCode o = GET_OPCODE(i);
-  const char *name = luaP_opnames[o];
-  int line = luaG_getfuncline(p, pc);
-  printf("(%4d) %4d - ", line, pc);
-  switch (getOpMode(o)) {
-    case iABC:
-      printf("%-12s%4d %4d %4d%s", name,
-              GETARG_A(i), GETARG_B(i), GETARG_C(i),
-              GETARG_k(i) ? " (k)" : "");
-      break;
-    case iABx:
-      printf("%-12s%4d %4d", name, GETARG_A(i), GETARG_Bx(i));
-      break;
-    case iAsBx:
-      printf("%-12s%4d %4d", name, GETARG_A(i), GETARG_sBx(i));
-      break;
-    case iAx:
-      printf("%-12s%4d", name, GETARG_Ax(i));
-      break;
-    case isJ:
-      printf("%-12s%4d (%1d)", name, GETARG_sJ(i), !!GETARG_m(i));
-      break;
-  }
- printf("\n");
- }
-}
 
 #define SS(x)	((x==1)?"":"s")
 #define S(x)	(int)(x),SS(x)

@@ -659,7 +675,8 @@
  printf("constants (%d) for %p:\n",n,VOID(f));
  for (i=0; i<n; i++)
  {
-  printf("\t%d\t",i+1);
+  printf("\t%d\t",i);
+  PrintType(f,i);
   PrintConstant(f,i);
   printf("\n");
  }

@@ -683,7 +700,6 @@
 {
  int i,n=f->sizep;
  PrintHeader(f);
- riPrintCode(f);
  PrintCode(f);
  if (full) PrintDebug(f);
  for (i=0; i<n; i++) PrintFunction(f->p[i],full);

src/luaconf.h

@@ -1,5 +1,5 @@
 /*
-** $Id: luaconf.h,v 1.270 2018/06/18 12:51:05 roberto Exp $
+** $Id: luaconf.h $
 ** Configuration file for Lua
 ** See Copyright Notice in lua.h
 */

@@ -14,6 +14,16 @@
 
 /*
 ** ===================================================================
+** General Configuration File for Lua
+**
+** Some definitions here can be changed externally, through the
+** compiler (e.g., with '-D' options). Those are protected by
+** '#if !defined' guards. However, several other definitions should
+** be changed directly here, either because they affect the Lua
+** ABI (by making the changes here, you ensure that all software
+** connected to Lua, such as C libraries, will be compiled with the
+** same configuration); or because they are seldom changed.
+**
 ** Search for "@@" to find all configurable definitions.
 ** ===================================================================
 */

@@ -22,18 +32,23 @@
 /*
 ** {====================================================================
 ** System Configuration: macros to adapt (if needed) Lua to some
-** particular platform, for instance compiling it with 32-bit numbers or
-** restricting it to C89.
+** particular platform, for instance restricting it to C89.
 ** =====================================================================
 */
 
 /*
-@@ LUA_32BITS enables Lua with 32-bit integers and 32-bit floats. You
-** can also define LUA_32BITS in the make file, but changing here you
-** ensure that all software connected to Lua will be compiled with the
-** same configuration.
+@@ LUAI_MAXCSTACK defines the maximum depth for nested calls and
+** also limits the maximum depth of other recursive algorithms in
+** the implementation, such as syntactic analysis. A value too
+** large may allow the interpreter to crash (C-stack overflow).
+** The default value seems ok for regular machines, but may be
+** too high for restricted hardware.
+** The test file 'cstack.lua' may help finding a good limit.
+** (It will crash with a limit too high.)
 */
-/* #define LUA_32BITS */
+#if !defined(LUAI_MAXCSTACK)
+#define LUAI_MAXCSTACK		2200
+#endif
 
 
 /*

@@ -71,33 +86,41 @@
 
 
 /*
-@@ LUA_C89_NUMBERS ensures that Lua uses the largest types available for
-** C89 ('long' and 'double'); Windows always has '__int64', so it does
-** not need to use this case.
+@@ LUAI_IS32INT is true iff 'int' has (at least) 32 bits.
 */
-#if defined(LUA_USE_C89) && !defined(LUA_USE_WINDOWS)
-#define LUA_C89_NUMBERS
-#endif
+#define LUAI_IS32INT	((UINT_MAX >> 30) >= 3)
+
+/* }================================================================== */
 
 
 
 /*
-@@ LUAI_BITSINT defines the (minimum) number of bits in an 'int'.
+** {==================================================================
+** Configuration for Number types.
+** ===================================================================
 */
-/* avoid undefined shifts */
-#if ((INT_MAX >> 15) >> 15) >= 1
-#define LUAI_BITSINT	32
-#else
-/* 'int' always must have at least 16 bits */
-#define LUAI_BITSINT	16
+
+/*
+@@ LUA_32BITS enables Lua with 32-bit integers and 32-bit floats.
+*/
+/* #define LUA_32BITS */
+
+
+/*
+@@ LUA_C89_NUMBERS ensures that Lua uses the largest types available for
+** C89 ('long' and 'double'); Windows always has '__int64', so it does
+** not need to use this case.
+*/
+#if defined(LUA_USE_C89) && !defined(LUA_USE_WINDOWS)
+#define LUA_C89_NUMBERS
 #endif
 
 
 /*
 @@ LUA_INT_TYPE defines the type for Lua integers.
 @@ LUA_FLOAT_TYPE defines the type for Lua floats.
-** Lua should work fine with any mix of these options (if supported
-** by your C compiler). The usual configurations are 64-bit integers
+** Lua should work fine with any mix of these options supported
+** by your C compiler. The usual configurations are 64-bit integers
 ** and 'double' (the default), 32-bit integers and 'float' (for
 ** restricted platforms), and 'long'/'double' (for C compilers not
 ** compliant with C99, which may not have support for 'long long').

@@ -117,7 +140,7 @@
 /*
 ** 32-bit integers and 'float'
 */
-#if LUAI_BITSINT >= 32  /* use 'int' if big enough */
+#if LUAI_IS32INT  /* use 'int' if big enough */
 #define LUA_INT_TYPE	LUA_INT_INT
 #else  /* otherwise use 'long' */
 #define LUA_INT_TYPE	LUA_INT_LONG

@@ -149,7 +172,6 @@
 
 
 
-
 /*
 ** {==================================================================
 ** Configuration for Paths.

@@ -177,6 +199,7 @@
 ** hierarchy or if you want to install your libraries in
 ** non-conventional directories.
 */
+
 #define LUA_VDIR	LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
 #if defined(_WIN32)	/* { */
 /*

@@ -186,27 +209,40 @@
 #define LUA_LDIR	"!\\lua\\"
 #define LUA_CDIR	"!\\"
 #define LUA_SHRDIR	"!\\..\\share\\lua\\" LUA_VDIR "\\"
+
+#if !defined(LUA_PATH_DEFAULT)
 #define LUA_PATH_DEFAULT  \
 		LUA_LDIR"?.lua;"  LUA_LDIR"?\\init.lua;" \
 		LUA_CDIR"?.lua;"  LUA_CDIR"?\\init.lua;" \
 		LUA_SHRDIR"?.lua;" LUA_SHRDIR"?\\init.lua;" \
 		".\\?.lua;" ".\\?\\init.lua"
+#endif
+
+#if !defined(LUA_CPATH_DEFAULT)
 #define LUA_CPATH_DEFAULT \
 		LUA_CDIR"?.dll;" \
 		LUA_CDIR"..\\lib\\lua\\" LUA_VDIR "\\?.dll;" \
 		LUA_CDIR"loadall.dll;" ".\\?.dll"
+#endif
 
 #else			/* }{ */
 
 #define LUA_ROOT	"/usr/local/"
 #define LUA_LDIR	LUA_ROOT "share/lua/" LUA_VDIR "/"
 #define LUA_CDIR	LUA_ROOT "lib/lua/" LUA_VDIR "/"
+
+#if !defined(LUA_PATH_DEFAULT)
 #define LUA_PATH_DEFAULT  \
 		LUA_LDIR"?.lua;"  LUA_LDIR"?/init.lua;" \
 		LUA_CDIR"?.lua;"  LUA_CDIR"?/init.lua;" \
 		"./?.lua;" "./?/init.lua"
+#endif
+
+#if !defined(LUA_CPATH_DEFAULT)
 #define LUA_CPATH_DEFAULT \
 		LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so"
+#endif
+
 #endif			/* } */
 
 

@@ -215,12 +251,16 @@
 ** CHANGE it if your machine does not use "/" as the directory separator
 ** and is not Windows. (On Windows Lua automatically uses "\".)
 */
+#if !defined(LUA_DIRSEP)
+
 #if defined(_WIN32)
 #define LUA_DIRSEP	"\\"
 #else
 #define LUA_DIRSEP	"/"
 #endif
 
+#endif
+
 /* }================================================================== */
 
 

@@ -255,12 +295,10 @@
 
 
 /*
-** More often than not the libs go together with the core;
-** Functions from the auxiliary library must be exported,
-** but opening functions do not.
+** More often than not the libs go together with the core.
 */
 #define LUALIB_API	LUA_API
-#define LUAMOD_API	LUAI_FUNC
+#define LUAMOD_API	LUA_API
 
 
 /*

@@ -279,7 +317,7 @@
 */
 #if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \
     defined(__ELF__)		/* { */
-#define LUAI_FUNC	__attribute__((visibility("hidden"))) extern
+#define LUAI_FUNC	__attribute__((visibility("internal"))) extern
 #else				/* }{ */
 #define LUAI_FUNC	extern
 #endif				/* } */

@@ -297,7 +335,7 @@
 */
 
 /*
-@@ LUA_COMPAT_5_3 controls other macros for compatibility with Lua 5.2.
+@@ LUA_COMPAT_5_3 controls other macros for compatibility with Lua 5.3.
 ** You can define it to get all options, or change specific options
 ** to fit your specific needs.
 */

@@ -306,8 +344,8 @@
 /*
 @@ LUA_COMPAT_MATHLIB controls the presence of several deprecated
 ** functions in the mathematical library.
-** (These functions were already officially removed in 5.3, but
-** nevertheless they are available by default there.)
+** (These functions were already officially removed in 5.3;
+** nevertheless they are still available here.)
 */
 #define LUA_COMPAT_MATHLIB
 

@@ -315,17 +353,25 @@
 @@ LUA_COMPAT_APIINTCASTS controls the presence of macros for
 ** manipulating other integer types (lua_pushunsigned, lua_tounsigned,
 ** luaL_checkint, luaL_checklong, etc.)
+** (These macros were also officially removed in 5.3, but they are still
+** available here.)
 */
 #define LUA_COMPAT_APIINTCASTS
 
-#endif				/* } */
 
+/*
+@@ LUA_COMPAT_LT_LE controls the emulation of the '__le' metamethod
+** using '__lt'.
+*/
+#define LUA_COMPAT_LT_LE
 
 
 /*
 @@ The following macros supply trivial compatibility for some
 ** changes in the API. The macros themselves document how to
 ** change your code to avoid using them.
+** (Once more, these macros were officially removed in 5.3, but they are
+** still available here.)
 */
 #define lua_strlen(L,i)		lua_rawlen(L, (i))
 

@@ -334,6 +380,8 @@
 #define lua_equal(L,idx1,idx2)		lua_compare(L,(idx1),(idx2),LUA_OPEQ)
 #define lua_lessthan(L,idx1,idx2)	lua_compare(L,(idx1),(idx2),LUA_OPLT)
 
+#endif				/* } */
+
 /* }================================================================== */
 
 

@@ -357,7 +405,7 @@
 @@ lua_number2str converts a float to a string.
 @@ l_mathop allows the addition of an 'l' or 'f' to all math operations.
 @@ l_floor takes the floor of a float.
-@@ lua_str2number converts a decimal numeric string to a number.
+@@ lua_str2number converts a decimal numeral to a number.
 */
 
 

@@ -471,7 +519,6 @@
 */
 #define LUA_UNSIGNED		unsigned LUAI_UACINT
 
-#define LUA_MAXUNSIGNED		(~(lua_Unsigned)0)
 
 #define LUA_UNSIGNEDBITS	(sizeof(LUA_UNSIGNED) * CHAR_BIT)
 

@@ -486,6 +533,8 @@
 #define LUA_MAXINTEGER		INT_MAX
 #define LUA_MININTEGER		INT_MIN
 
+#define LUA_MAXUNSIGNED		UINT_MAX
+
 #elif LUA_INT_TYPE == LUA_INT_LONG	/* }{ long */
 
 #define LUA_INTEGER		long

@@ -494,6 +543,8 @@
 #define LUA_MAXINTEGER		LONG_MAX
 #define LUA_MININTEGER		LONG_MIN
 
+#define LUA_MAXUNSIGNED		ULONG_MAX
+
 #elif LUA_INT_TYPE == LUA_INT_LONGLONG	/* }{ long long */
 
 /* use presence of macro LLONG_MAX as proxy for C99 compliance */

@@ -506,6 +557,8 @@
 #define LUA_MAXINTEGER		LLONG_MAX
 #define LUA_MININTEGER		LLONG_MIN
 
+#define LUA_MAXUNSIGNED		ULLONG_MAX
+
 #elif defined(LUA_USE_WINDOWS) /* }{ */
 /* in Windows, can use specific Windows types */
 

@@ -515,6 +568,8 @@
 #define LUA_MAXINTEGER		_I64_MAX
 #define LUA_MININTEGER		_I64_MIN
 
+#define LUA_MAXUNSIGNED		_UI64_MAX
+
 #else				/* }{ */
 
 #error "Compiler does not support 'long long'. Use option '-DLUA_32BITS' \

@@ -549,7 +604,7 @@
 
 
 /*
-@@ lua_strx2number converts a hexadecimal numeric string to a number.
+@@ lua_strx2number converts a hexadecimal numeral to a number.
 ** In C99, 'strtod' does that conversion. Otherwise, you can
 ** leave 'lua_strx2number' undefined and Lua will provide its own
 ** implementation.

@@ -567,7 +622,7 @@
 
 
 /*
-@@ lua_number2strx converts a float to a hexadecimal numeric string.
+@@ lua_number2strx converts a float to a hexadecimal numeral.
 ** In C99, 'sprintf' (with format specifiers '%a'/'%A') does that.
 ** Otherwise, you can leave 'lua_number2strx' undefined and Lua will
 ** provide its own implementation.

@@ -613,7 +668,7 @@
 /*
 @@ lua_getlocaledecpoint gets the locale "radix character" (decimal point).
 ** Change that if you do not want to use C locales. (Code using this
-** macro must include header 'locale.h'.)
+** macro must include the header 'locale.h'.)
 */
 #if !defined(lua_getlocaledecpoint)
 #define lua_getlocaledecpoint()		(localeconv()->decimal_point[0])

@@ -654,7 +709,7 @@
 ** {==================================================================
 ** Macros that affect the API and must be stable (that is, must be the
 ** same when you compile Lua and when you compile code that links to
-** Lua). You probably do not want/need to change them.
+** Lua).
 ** =====================================================================
 */
 

@@ -665,7 +720,7 @@
 ** space (and to reserve some numbers for pseudo-indices).
 ** (It must fit into max(size_t)/32.)
 */
-#if LUAI_BITSINT >= 32
+#if LUAI_IS32INT
 #define LUAI_MAXSTACK		1000000
 #else
 #define LUAI_MAXSTACK		15000

@@ -690,16 +745,9 @@
 
 /*
 @@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system.
-** CHANGE it if it uses too much C-stack space. (For long double,
-** 'string.format("%.99f", -1e4932)' needs 5034 bytes, so a
-** smaller buffer would force a memory allocation for each call to
-** 'string.format'.)
 */
-#if LUA_FLOAT_TYPE == LUA_FLOAT_LONGDOUBLE
-#define LUAL_BUFFERSIZE		8192
-#else
-#define LUAL_BUFFERSIZE   ((int)(0x80 * sizeof(void*) * sizeof(lua_Integer)))
-#endif
+#define LUAL_BUFFERSIZE   ((int)(16 * sizeof(void*) * sizeof(lua_Number)))
+
 
 /*
 @@ LUAI_MAXALIGN defines fields that, when used in a union, ensure

src/lualib.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lualib.h,v 1.46 2018/02/27 18:47:32 roberto Exp $
+** $Id: lualib.h $
 ** Lua standard libraries
 ** See Copyright Notice in lua.h
 */

src/lundump.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lundump.c,v 2.50 2018/06/01 16:45:58 roberto Exp $
+** $Id: lundump.c $
 ** load precompiled Lua chunks
 ** See Copyright Notice in lua.h
 */

@@ -10,6 +10,7 @@
 #include "lprefix.h"
 
 
+#include <limits.h>
 #include <string.h>
 
 #include "lua.h"

@@ -37,7 +38,7 @@
 
 
 static l_noret error (LoadState *S, const char *why) {
-  luaO_pushfstring(S->L, "%s: %s precompiled chunk", S->name, why);
+  luaO_pushfstring(S->L, "%s: bad binary format (%s)", S->name, why);
   luaD_throw(S->L, LUA_ERRSYNTAX);
 }
 

@@ -50,7 +51,7 @@
 
 static void LoadBlock (LoadState *S, void *b, size_t size) {
   if (luaZ_read(S->Z, b, size) != 0)
-    error(S, "truncated");
+    error(S, "truncated chunk");
 }
 
 

@@ -60,24 +61,32 @@
 static lu_byte LoadByte (LoadState *S) {
   int b = zgetc(S->Z);
   if (b == EOZ)
-    error(S, "truncated");
+    error(S, "truncated chunk");
   return cast_byte(b);
 }
 
 
-static size_t LoadSize (LoadState *S) {
+static size_t LoadUnsigned (LoadState *S, size_t limit) {
   size_t x = 0;
   int b;
+  limit >>= 7;
   do {
     b = LoadByte(S);
+    if (x >= limit)
+      error(S, "integer overflow");
     x = (x << 7) | (b & 0x7f);
   } while ((b & 0x80) == 0);
   return x;
 }
 
 
+static size_t LoadSize (LoadState *S) {
+  return LoadUnsigned(S, ~(size_t)0);
+}
+
+
 static int LoadInt (LoadState *S) {
-  return cast_int(LoadSize(S));
+  return cast_int(LoadUnsigned(S, INT_MAX));
 }
 
 

@@ -255,28 +264,27 @@
 
 static void fchecksize (LoadState *S, size_t size, const char *tname) {
   if (LoadByte(S) != size)
-    error(S, luaO_pushfstring(S->L, "%s size mismatch in", tname));
+    error(S, luaO_pushfstring(S->L, "%s size mismatch", tname));
 }
 
 
 #define checksize(S,t)	fchecksize(S,sizeof(t),#t)
 
 static void checkHeader (LoadState *S) {
-  checkliteral(S, LUA_SIGNATURE + 1, "not a");  /* 1st char already checked */
-  if (LoadByte(S) != LUAC_VERSION)
-    error(S, "version mismatch in");
+  /* skip 1st char (already read and checked) */
+  checkliteral(S, &LUA_SIGNATURE[1], "not a binary chunk");
+  if (LoadInt(S) != LUAC_VERSION)
+    error(S, "version mismatch");
   if (LoadByte(S) != LUAC_FORMAT)
-    error(S, "format mismatch in");
-  checkliteral(S, LUAC_DATA, "corrupted");
-  checksize(S, int);
-  checksize(S, size_t);
+    error(S, "format mismatch");
+  checkliteral(S, LUAC_DATA, "corrupted chunk");
   checksize(S, Instruction);
   checksize(S, lua_Integer);
   checksize(S, lua_Number);
   if (LoadInteger(S) != LUAC_INT)
-    error(S, "endianness mismatch in");
+    error(S, "integer format mismatch");
   if (LoadNumber(S) != LUAC_NUM)
-    error(S, "float format mismatch in");
+    error(S, "float format mismatch");
 }
 
 

src/lundump.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lundump.h,v 1.45 2015/09/08 15:41:05 roberto Exp $
+** $Id: lundump.h $
 ** load precompiled Lua chunks
 ** See Copyright Notice in lua.h
 */

@@ -18,8 +18,7 @@
 #define LUAC_INT	0x5678
 #define LUAC_NUM	cast_num(370.5)
 
-#define MYINT(s)	(s[0]-'0')
-#define LUAC_VERSION	(MYINT(LUA_VERSION_MAJOR)*16+MYINT(LUA_VERSION_MINOR))
+#define LUAC_VERSION	LUA_VERSION_NUM
 #define LUAC_FORMAT	0	/* this is the official format */
 
 /* load one chunk; from lundump.c */

src/lutf8lib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lutf8lib.c,v 1.17 2017/03/14 12:40:44 roberto Exp $
+** $Id: lutf8lib.c $
 ** Standard library for UTF-8 manipulation
 ** See Copyright Notice in lua.h
 */

@@ -20,7 +20,20 @@
 #include "lauxlib.h"
 #include "lualib.h"
 
-#define MAXUNICODE	0x10FFFF
+
+#define MAXUNICODE	0x10FFFFu
+
+#define MAXUTF		0x7FFFFFFFu
+
+/*
+** Integer type for decoded UTF-8 values; MAXUTF needs 31 bits.
+*/
+#if (UINT_MAX >> 30) >= 1
+typedef	unsigned int utfint;
+#else
+typedef unsigned long utfint;
+#endif
+
 
 #define iscont(p)	((*(p) & 0xC0) == 0x80)
 

@@ -35,51 +48,60 @@
 
 
 /*
-** Decode one UTF-8 sequence, returning NULL if byte sequence is invalid.
+** Decode one UTF-8 sequence, returning NULL if byte sequence is
+** invalid.  The array 'limits' stores the minimum value for each
+** sequence length, to check for overlong representations. Its first
+** entry forces an error for non-ascii bytes with no continuation
+** bytes (count == 0).
 */
-static const char *utf8_decode (const char *o, int *val) {
-  static const unsigned int limits[] = {0xFF, 0x7F, 0x7FF, 0xFFFF};
-  const unsigned char *s = (const unsigned char *)o;
-  unsigned int c = s[0];
-  unsigned int res = 0;  /* final result */
+static const char *utf8_decode (const char *s, utfint *val, int strict) {
+  static const utfint limits[] =
+        {~(utfint)0, 0x80, 0x800, 0x10000u, 0x200000u, 0x4000000u};
+  unsigned int c = (unsigned char)s[0];
+  utfint res = 0;  /* final result */
   if (c < 0x80)  /* ascii? */
     res = c;
   else {
     int count = 0;  /* to count number of continuation bytes */
-    while (c & 0x40) {  /* still have continuation bytes? */
-      int cc = s[++count];  /* read next byte */
+    for (; c & 0x40; c <<= 1) {  /* while it needs continuation bytes... */
+      unsigned int cc = (unsigned char)s[++count];  /* read next byte */
       if ((cc & 0xC0) != 0x80)  /* not a continuation byte? */
         return NULL;  /* invalid byte sequence */
       res = (res << 6) | (cc & 0x3F);  /* add lower 6 bits from cont. byte */
-      c <<= 1;  /* to test next bit */
     }
-    res |= ((c & 0x7F) << (count * 5));  /* add first byte */
-    if (count > 3 || res > MAXUNICODE || res <= limits[count])
+    res |= ((utfint)(c & 0x7F) << (count * 5));  /* add first byte */
+    if (count > 5 || res > MAXUTF || res < limits[count])
       return NULL;  /* invalid byte sequence */
     s += count;  /* skip continuation bytes read */
   }
+  if (strict) {
+    /* check for invalid code points; too large or surrogates */
+    if (res > MAXUNICODE || (0xD800u <= res && res <= 0xDFFFu))
+      return NULL;
+  }
   if (val) *val = res;
-  return (const char *)s + 1;  /* +1 to include first byte */
+  return s + 1;  /* +1 to include first byte */
 }
 
 
 /*
-** utf8len(s [, i [, j]]) --> number of characters that start in the
-** range [i,j], or nil + current position if 's' is not well formed in
-** that interval
+** utf8len(s [, i [, j [, lax]]]) --> number of characters that
+** start in the range [i,j], or nil + current position if 's' is not
+** well formed in that interval
 */
 static int utflen (lua_State *L) {
-  int n = 0;
-  size_t len;
+  lua_Integer n = 0;  /* counter for the number of characters */
+  size_t len;  /* string length in bytes */
   const char *s = luaL_checklstring(L, 1, &len);
   lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len);
   lua_Integer posj = u_posrelat(luaL_optinteger(L, 3, -1), len);
+  int lax = lua_toboolean(L, 4);
   luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 2,
                    "initial position out of string");
   luaL_argcheck(L, --posj < (lua_Integer)len, 3,
                    "final position out of string");
   while (posi <= posj) {
-    const char *s1 = utf8_decode(s + posi, NULL);
+    const char *s1 = utf8_decode(s + posi, NULL, !lax);
     if (s1 == NULL) {  /* conversion error? */
       lua_pushnil(L);  /* return nil ... */
       lua_pushinteger(L, posi + 1);  /* ... and current position */

@@ -94,14 +116,15 @@
 
 
 /*
-** codepoint(s, [i, [j]])  -> returns codepoints for all characters
-** that start in the range [i,j]
+** codepoint(s, [i, [j [, lax]]]) -> returns codepoints for all
+** characters that start in the range [i,j]
 */
 static int codepoint (lua_State *L) {
   size_t len;
   const char *s = luaL_checklstring(L, 1, &len);
   lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len);
   lua_Integer pose = u_posrelat(luaL_optinteger(L, 3, posi), len);
+  int lax = lua_toboolean(L, 4);
   int n;
   const char *se;
   luaL_argcheck(L, posi >= 1, 2, "out of range");

@@ -109,13 +132,13 @@
   if (posi > pose) return 0;  /* empty interval; return no values */
   if (pose - posi >= INT_MAX)  /* (lua_Integer -> int) overflow? */
     return luaL_error(L, "string slice too long");
-  n = (int)(pose -  posi) + 1;
+  n = (int)(pose -  posi) + 1;  /* upper bound for number of returns */
   luaL_checkstack(L, n, "string slice too long");
-  n = 0;
-  se = s + pose;
+  n = 0;  /* count the number of returns */
+  se = s + pose;  /* string end */
   for (s += posi - 1; s < se;) {
-    int code;
-    s = utf8_decode(s, &code);
+    utfint code;
+    s = utf8_decode(s, &code, !lax);
     if (s == NULL)
       return luaL_error(L, "invalid UTF-8 code");
     lua_pushinteger(L, code);

@@ -126,8 +149,8 @@
 
 
 static void pushutfchar (lua_State *L, int arg) {
-  lua_Integer code = luaL_checkinteger(L, arg);
-  luaL_argcheck(L, 0 <= code && code <= MAXUNICODE, arg, "value out of range");
+  lua_Unsigned code = (lua_Unsigned)luaL_checkinteger(L, arg);
+  luaL_argcheck(L, code <= MAXUTF, arg, "value out of range");
   lua_pushfstring(L, "%U", (long)code);
 }
 

@@ -198,7 +221,7 @@
 }
 
 
-static int iter_aux (lua_State *L) {
+static int iter_aux (lua_State *L, int strict) {
   size_t len;
   const char *s = luaL_checklstring(L, 1, &len);
   lua_Integer n = lua_tointeger(L, 2) - 1;

@@ -211,9 +234,9 @@
   if (n >= (lua_Integer)len)
     return 0;  /* no more codepoints */
   else {
-    int code;
-    const char *next = utf8_decode(s + n, &code);
-    if (next == NULL || iscont(next))
+    utfint code;
+    const char *next = utf8_decode(s + n, &code, strict);
+    if (next == NULL)
       return luaL_error(L, "invalid UTF-8 code");
     lua_pushinteger(L, n + 1);
     lua_pushinteger(L, code);

@@ -222,9 +245,19 @@
 }
 
 
+static int iter_auxstrict (lua_State *L) {
+  return iter_aux(L, 1);
+}
+
+static int iter_auxlax (lua_State *L) {
+  return iter_aux(L, 0);
+}
+
+
 static int iter_codes (lua_State *L) {
+  int lax = lua_toboolean(L, 2);
   luaL_checkstring(L, 1);
-  lua_pushcfunction(L, iter_aux);
+  lua_pushcfunction(L, lax ? iter_auxlax : iter_auxstrict);
   lua_pushvalue(L, 1);
   lua_pushinteger(L, 0);
   return 3;

@@ -232,7 +265,7 @@
 
 
 /* pattern to match a single UTF-8 character */
-#define UTF8PATT	"[\0-\x7F\xC2-\xF4][\x80-\xBF]*"
+#define UTF8PATT	"[\0-\x7F\xC2-\xFD][\x80-\xBF]*"
 
 
 static const luaL_Reg funcs[] = {

src/lvm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.c,v 2.359 2018/06/18 17:58:21 roberto Exp $
+** $Id: lvm.c $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */

@@ -148,38 +148,38 @@
 
 /*
 ** Try to convert a 'for' limit to an integer, preserving the semantics
-** of the loop.  (The following explanation assumes a non-negative step;
+** of the loop.  (The following explanation assumes a positive step;
 ** it is valid for negative steps mutatis mutandis.)
+** Return true if the loop must not run.
 ** If the limit is an integer or can be converted to an integer,
-** rounding down, that is it.
-** Otherwise, check whether the limit can be converted to a float.  If
-** the number is too large, it is OK to set the limit as LUA_MAXINTEGER,
-** which means no limit.  If the number is too negative, the loop
-** should not run, because any initial integer value is larger than the
-** limit. So, it sets the limit to LUA_MININTEGER. 'stopnow' corrects
-** the extreme case when the initial value is LUA_MININTEGER, in which
-** case the LUA_MININTEGER limit would still run the loop once.
-*/
-static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step,
-                     int *stopnow) {
-  *stopnow = 0;  /* usually, let loops run */
-  if (ttisinteger(obj))
-    *p = ivalue(obj);
-  else if (!luaV_tointeger(obj, p, (step < 0 ? 2 : 1))) {
+** rounding down, that is the limit.
+** Otherwise, check whether the limit can be converted to a float. If
+** the float is too large, clip it to LUA_MAXINTEGER.  If the float
+** is too negative, the loop should not run, because any initial
+** integer value is greater than such limit; so, it returns true to
+** signal that.
+** (For this latter case, no integer limit would be correct; even a
+** limit of LUA_MININTEGER would run the loop once for an initial
+** value equal to LUA_MININTEGER.)
+*/
+static int forlimit (lua_State *L, lua_Integer init, const TValue *lim,
+                                   lua_Integer *p, lua_Integer step) {
+  if (!luaV_tointeger(lim, p, (step < 0 ? 2 : 1))) {
     /* not coercible to in integer */
-    lua_Number n;  /* try to convert to float */
-    if (!tonumber(obj, &n)) /* cannot convert to float? */
-      return 0;  /* not a number */
-    if (luai_numlt(0, n)) {  /* if true, float is larger than max integer */
-      *p = LUA_MAXINTEGER;
-      if (step < 0) *stopnow = 1;
-    }
-    else {  /* float is less than min integer */
-      *p = LUA_MININTEGER;
-      if (step >= 0) *stopnow = 1;
+    lua_Number flim;  /* try to convert to float */
+    if (!tonumber(lim, &flim)) /* cannot convert to float? */
+      luaG_forerror(L, lim, "limit");
+    /* else 'flim' is a float out of integer bounds */
+    if (luai_numlt(0, flim)) {  /* if it is positive, it is too large */
+      if (step < 0) return 1;  /* initial value must be less than it */
+      *p = LUA_MAXINTEGER;  /* truncate */
+    }
+    else {  /* it is less than min integer */
+      if (step > 0) return 1;  /* initial value must be greater than it */
+      *p = LUA_MININTEGER;  /* truncate */
     }
   }
-  return 1;
+  return (step > 0 ? init > *p : init < *p);  /* not to run? */
 }
 
 

@@ -583,7 +583,7 @@
 
 
 /*
-** Main operation 'ra' = #rb'.
+** Main operation 'ra = #rb'.
 */
 void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) {
   const TValue *tm;

@@ -620,9 +620,9 @@
 ** 'floor(q) == trunc(q)' when 'q >= 0' or when 'q' is integer,
 ** otherwise 'floor(q) == trunc(q) - 1'.
 */
-lua_Integer luaV_div (lua_State *L, lua_Integer m, lua_Integer n) {
-  if (l_castS2U(n) + 1u <= 1u) {  /* special cases: -1 or 0 */
-    if (unlikely(n == 0))
+lua_Integer luaV_idiv (lua_State *L, lua_Integer m, lua_Integer n) {
+  if (unlikely(l_castS2U(n) + 1u <= 1u)) {  /* special cases: -1 or 0 */
+    if (n == 0)
       luaG_runerror(L, "attempt to divide by zero");
     return intop(-, 0, m);   /* n==-1; avoid overflow with 0x80000...//-1 */
   }

@@ -638,23 +638,33 @@
 /*
 ** Integer modulus; return 'm % n'. (Assume that C '%' with
 ** negative operands follows C99 behavior. See previous comment
-** about luaV_div.)
+** about luaV_idiv.)
 */
 lua_Integer luaV_mod (lua_State *L, lua_Integer m, lua_Integer n) {
-  if (l_castS2U(n) + 1u <= 1u) {  /* special cases: -1 or 0 */
-    if (unlikely(n == 0))
+  if (unlikely(l_castS2U(n) + 1u <= 1u)) {  /* special cases: -1 or 0 */
+    if (n == 0)
       luaG_runerror(L, "attempt to perform 'n%%0'");
     return 0;   /* m % -1 == 0; avoid overflow with 0x80000...%-1 */
   }
   else {
     lua_Integer r = m % n;
-    if (r != 0 && (m ^ n) < 0)  /* 'm/n' would be non-integer negative? */
+    if (r != 0 && (r ^ n) < 0)  /* 'm/n' would be non-integer negative? */
       r += n;  /* correct result for different rounding */
     return r;
   }
 }
 
 
+/*
+** Float modulus
+*/
+lua_Number luaV_modf (lua_State *L, lua_Number m, lua_Number n) {
+  lua_Number r;
+  luai_nummod(L, m, n, r);
+  return r;
+}
+
+
 /* number of bits in an integer */
 #define NBITS	cast_int(sizeof(lua_Integer) * CHAR_BIT)
 

@@ -674,30 +684,8 @@
 
 
 /*
-** check whether cached closure in prototype 'p' may be reused, that is,
-** whether there is a cached closure with the same upvalues needed by
-** new closure to be created.
-*/
-static LClosure *getcached (Proto *p, UpVal **encup, StkId base) {
-  LClosure *c = p->cache;
-  if (c != NULL) {  /* is there a cached closure? */
-    int nup = p->sizeupvalues;
-    Upvaldesc *uv = p->upvalues;
-    int i;
-    for (i = 0; i < nup; i++) {  /* check whether it has right upvalues */
-      TValue *v = uv[i].instack ? s2v(base + uv[i].idx) : encup[uv[i].idx]->v;
-      if (c->upvals[i]->v != v)
-        return NULL;  /* wrong upvalue; cannot reuse closure */
-    }
-    p->cachemiss = 0;  /* got a hit */
-  }
-  return c;  /* return cached closure (or NULL if no cached closure) */
-}
-
-
-/*
 ** create a new Lua closure, push it in the stack, and initialize
-** its upvalues. ???
+** its upvalues.
 */
 static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base,
                          StkId ra) {

@@ -714,13 +702,6 @@
       ncl->upvals[i] = encup[uv[i].idx];
     luaC_objbarrier(L, ncl, ncl->upvals[i]);
   }
-  if (p->cachemiss >= MAXMISS)  /* too many missings? */
-    p->cache = NULL;  /* give up cache */
-  else {
-    p->cache = ncl;  /* save it on cache for reuse */
-    luaC_protobarrier(L, p, ncl);
-    p->cachemiss++;
-  }
 }
 
 

@@ -754,10 +735,12 @@
     case OP_EQ: {  /* note that 'OP_EQI'/'OP_EQK' cannot yield */
       int res = !l_isfalse(s2v(L->top - 1));
       L->top--;
+#if defined(LUA_COMPAT_LT_LE)
       if (ci->callstatus & CIST_LEQ) {  /* "<=" using "<" instead? */
         ci->callstatus ^= CIST_LEQ;  /* clear mark */
         res = !res;  /* negate result */
       }
+#endif
       lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP);
       if (res != GETARG_k(inst))  /* condition failed? */
         ci->u.l.savedpc++;  /* skip jump instruction */

@@ -774,11 +757,13 @@
       }
       break;
     }
-    case OP_TFORCALL: case OP_CALL: case OP_TAILCALL:
-    case OP_SETTABUP: case OP_SETTABLE:
-    case OP_SETI: case OP_SETFIELD:
+    default: {
+      /* only these other opcodes can yield */
+      lua_assert(op == OP_TFORCALL || op == OP_CALL ||
+           op == OP_TAILCALL || op == OP_SETTABUP || op == OP_SETTABLE ||
+           op == OP_SETI || op == OP_SETFIELD);
       break;
-    default: lua_assert(0);
+    }
   }
 }
 

@@ -787,10 +772,194 @@
 
 /*
 ** {==================================================================
-** Function 'luaV_execute': main interpreter loop
+** Macros for arithmetic/bitwise/comparison opcodes in 'luaV_execute'
 ** ===================================================================
 */
 
+#define l_addi(L,a,b)	intop(+, a, b)
+#define l_subi(L,a,b)	intop(-, a, b)
+#define l_muli(L,a,b)	intop(*, a, b)
+#define l_band(L,a,b)	intop(&, a, b)
+#define l_bor(L,a,b)	intop(|, a, b)
+#define l_bxor(L,a,b)	intop(^, a, b)
+
+#define l_lti(a,b)	(a < b)
+#define l_lei(a,b)	(a <= b)
+#define l_gti(a,b)	(a > b)
+#define l_gei(a,b)	(a >= b)
+
+
+/*
+** Auxiliary macro for arithmetic operations over floats and others
+** with immediate operand. 'fop' is the float operation; 'tm' is the
+** corresponding metamethod; 'flip' is true if operands were flipped.
+*/
+#define op_arithfI_aux(L,v1,imm,fop,tm,flip) {  \
+  lua_Number nb;  \
+  if (tonumberns(v1, nb)) {  \
+    setfltvalue(s2v(ra), fop(L, nb, cast_num(imm)));  \
+  }  \
+  else  \
+    Protect(luaT_trybiniTM(L, v1, imm, flip, ra, tm)); }
+
+
+/*
+** Arithmetic operations over floats and others with immediate operand.
+*/
+#define op_arithfI(L,fop,tm) {  \
+  TValue *v1 = vRB(i);  \
+  int imm = GETARG_sC(i);  \
+  op_arithfI_aux(L, v1, imm, fop, tm, 0); }
+
+/*
+** Arithmetic operations with immediate operands. 'iop' is the integer
+** operation.
+*/
+#define op_arithI(L,iop,fop,tm,flip) {  \
+  TValue *v1 = vRB(i);  \
+  int imm = GETARG_sC(i);  \
+  if (ttisinteger(v1)) {  \
+    setivalue(s2v(ra), iop(L, ivalue(v1), imm));  \
+  }  \
+  else op_arithfI_aux(L, v1, imm, fop, tm, flip); }
+
+
+/*
+** Auxiliary function for arithmetic operations over floats and others
+** with two register operands.
+*/
+#define op_arithf_aux(L,v1,v2,fop,tm) {  \
+  lua_Number n1; lua_Number n2;  \
+  if (tonumberns(v1, n1) && tonumberns(v2, n2)) {  \
+    setfltvalue(s2v(ra), fop(L, n1, n2));  \
+  }  \
+  else  \
+    Protect(luaT_trybinTM(L, v1, v2, ra, tm)); }
+
+
+/*
+** Arithmetic operations over floats and others with register operands.
+*/
+#define op_arithf(L,fop,tm) {  \
+  TValue *v1 = vRB(i);  \
+  TValue *v2 = vRC(i);  \
+  op_arithf_aux(L, v1, v2, fop, tm); }
+
+
+/*
+** Arithmetic operations with register operands.
+*/
+#define op_arith(L,iop,fop,tm) {  \
+  TValue *v1 = vRB(i);  \
+  TValue *v2 = vRC(i);  \
+  if (ttisinteger(v1) && ttisinteger(v2)) {  \
+    lua_Integer i1 = ivalue(v1); lua_Integer i2 = ivalue(v2);  \
+    setivalue(s2v(ra), iop(L, i1, i2));  \
+  }  \
+  else op_arithf_aux(L, v1, v2, fop, tm); }
+
+
+/*
+** Arithmetic operations with K operands.
+*/
+#define op_arithK(L,iop,fop,tm,flip) {  \
+  TValue *v1 = vRB(i);  \
+  TValue *v2 = KC(i);  \
+  if (ttisinteger(v1) && ttisinteger(v2)) {  \
+    lua_Integer i1 = ivalue(v1); lua_Integer i2 = ivalue(v2);  \
+    setivalue(s2v(ra), iop(L, i1, i2));  \
+  }  \
+  else { \
+    lua_Number n1; lua_Number n2;  \
+    if (tonumberns(v1, n1) && tonumberns(v2, n2)) {  \
+      setfltvalue(s2v(ra), fop(L, n1, n2));  \
+    }  \
+    else  \
+      Protect(luaT_trybinassocTM(L, v1, v2, ra, flip, tm)); } }
+
+
+/*
+** Arithmetic operations with K operands for floats.
+*/
+#define op_arithfK(L,fop,tm) {  \
+  TValue *v1 = vRB(i);  \
+  TValue *v2 = KC(i);  \
+  lua_Number n1; lua_Number n2;  \
+  if (tonumberns(v1, n1) && tonumberns(v2, n2)) {  \
+    setfltvalue(s2v(ra), fop(L, n1, n2));  \
+  }  \
+  else  \
+    Protect(luaT_trybinTM(L, v1, v2, ra, tm)); }
+
+
+/*
+** Bitwise operations with constant operand.
+*/
+#define op_bitwiseK(L,op,tm) {  \
+  TValue *v1 = vRB(i);  \
+  TValue *v2 = KC(i);  \
+  lua_Integer i1;  \
+  lua_Integer i2 = ivalue(v2);  \
+  if (tointegerns(v1, &i1)) {  \
+    setivalue(s2v(ra), op(L, i1, i2));  \
+  }  \
+  else  \
+    Protect(luaT_trybiniTM(L, v1, i2, TESTARG_k(i), ra, tm)); }
+
+
+/*
+** Bitwise operations with register operands.
+*/
+#define op_bitwise(L,op,tm) {  \
+  TValue *v1 = vRB(i);  \
+  TValue *v2 = vRC(i);  \
+  lua_Integer i1; lua_Integer i2;  \
+  if (tointegerns(v1, &i1) && tointegerns(v2, &i2)) {  \
+    setivalue(s2v(ra), op(L, i1, i2));  \
+  }  \
+  else  \
+    Protect(luaT_trybinTM(L, v1, v2, ra, tm)); }
+
+
+/*
+** Order operations with register operands.
+*/
+#define op_order(L,opi,opf,other) {  \
+        int cond;  \
+        TValue *rb = vRB(i);  \
+        if (ttisinteger(s2v(ra)) && ttisinteger(rb))  \
+          cond = opi(ivalue(s2v(ra)), ivalue(rb));  \
+        else if (ttisnumber(s2v(ra)) && ttisnumber(rb))  \
+          cond = opf(s2v(ra), rb);  \
+        else  \
+          Protect(cond = other(L, s2v(ra), rb));  \
+        docondjump(); }
+
+
+/*
+** Order operations with immediate operand.
+*/
+#define op_orderI(L,opi,opf,inv,tm) {  \
+        int cond;  \
+        int im = GETARG_sB(i);  \
+        if (ttisinteger(s2v(ra)))  \
+          cond = opi(ivalue(s2v(ra)), im);  \
+        else if (ttisfloat(s2v(ra)))  \
+          cond = opf(fltvalue(s2v(ra)), cast_num(im));  \
+        else {  \
+          int isf = GETARG_C(i);  \
+          Protect(cond = luaT_callorderiTM(L, s2v(ra), im, inv, isf, tm));  \
+        }  \
+        docondjump(); }
+
+/* }================================================================== */
+
+
+/*
+** {==================================================================
+** Function 'luaV_execute': main interpreter loop
+** ===================================================================
+*/
 
 /*
 ** some macros for common tasks in 'luaV_execute'

@@ -813,6 +982,9 @@
 #define updatebase(ci)	(base = ci->func + 1)
 
 
+#define updatestack(ci) { if (trap) { updatebase(ci); ra = RA(i); } }
+
+
 /*
 ** Execute a jump instruction. The 'updatetrap' allows signals to stop
 ** tight loops. (Without it, the local copy of 'trap' could never change.)

@@ -854,7 +1026,9 @@
 #define ProtectNT(exp)  (savepc(L), (exp), updatetrap(ci))
 
 /*
-** Protect code that will finish the loop (returns).
+** Protect code that will finish the loop (returns) or can only raise
+** errors. (That is, it will not return to the interpreter main loop
+** after changing the stack or hooks.)
 */
 #define halfProtect(exp)  (savepc(L), (exp))
 

@@ -896,7 +1070,7 @@
   pc = ci->u.l.savedpc;
   if (trap) {
     if (cl->p->is_vararg)
-      trap = 0;  /* hooks will start after PREPVARARG instruction */
+      trap = 0;  /* hooks will start after VARARGPREP instruction */
     else if (pc == cl->p->code)  /* first instruction (not resuming)? */
       luaD_hookcall(L, ci);
     ci->u.l.trap = 1;  /* there may be other hooks */

@@ -904,7 +1078,6 @@
   base = ci->func + 1;
   /* main loop of interpreter */
   for (;;) {
-    int cond;  /* flag for conditional jumps */
     Instruction i;  /* instruction being executed */
     StkId ra;  /* instruction's A register */
     vmfetch();

@@ -1091,223 +1264,111 @@
         vmbreak;
       }
       vmcase(OP_ADDI) {
-        TValue *rb = vRB(i);
-        int ic = GETARG_sC(i);
-        lua_Number nb;
-        if (ttisinteger(rb)) {
-          setivalue(s2v(ra), intop(+, ivalue(rb), ic));
-        }
-        else if (tonumberns(rb, nb)) {
-          setfltvalue(s2v(ra), luai_numadd(L, nb, cast_num(ic)));
-        }
-        else
-          Protect(luaT_trybiniTM(L, rb, ic, GETARG_k(i), ra, TM_ADD));
+        op_arithI(L, l_addi, luai_numadd, TM_ADD, GETARG_k(i));
         vmbreak;
       }
       vmcase(OP_SUBI) {
-        TValue *rb = vRB(i);
-        int ic = GETARG_sC(i);
-        lua_Number nb;
-        if (ttisinteger(rb)) {
-          setivalue(s2v(ra), intop(-, ivalue(rb), ic));
-        }
-        else if (tonumberns(rb, nb)) {
-          setfltvalue(s2v(ra), luai_numsub(L, nb, cast_num(ic)));
-        }
-        else
-          Protect(luaT_trybiniTM(L, rb, ic, 0, ra, TM_SUB));
+        op_arithI(L, l_subi, luai_numsub, TM_SUB, 0);
         vmbreak;
       }
       vmcase(OP_MULI) {
-        TValue *rb = vRB(i);
-        int ic = GETARG_sC(i);
-        lua_Number nb;
-        if (ttisinteger(rb)) {
-          setivalue(s2v(ra), intop(*, ivalue(rb), ic));
-        }
-        else if (tonumberns(rb, nb)) {
-          setfltvalue(s2v(ra), luai_nummul(L, nb, cast_num(ic)));
-        }
-        else
-          Protect(luaT_trybiniTM(L, rb, ic, GETARG_k(i), ra, TM_MUL));
+        op_arithI(L, l_muli, luai_nummul, TM_MUL, GETARG_k(i));
         vmbreak;
       }
       vmcase(OP_MODI) {
-        TValue *rb = vRB(i);
-        int ic = GETARG_sC(i);
-        lua_Number nb;
-        if (ttisinteger(rb)) {
-          setivalue(s2v(ra), luaV_mod(L, ivalue(rb), ic));
-        }
-        else if (tonumberns(rb, nb)) {
-          lua_Number m;
-          lua_Number nc = cast_num(ic);
-          luai_nummod(L, nb, nc, m);
-          setfltvalue(s2v(ra), m);
-        }
-        else
-          Protect(luaT_trybiniTM(L, rb, ic, 0, ra, TM_MOD));
+        op_arithI(L, luaV_mod, luaV_modf, TM_MOD, 0);
         vmbreak;
       }
       vmcase(OP_POWI) {
-        TValue *rb = vRB(i);
-        int ic = GETARG_sC(i);
-        lua_Number nb;
-        if (tonumberns(rb, nb)) {
-          lua_Number nc = cast_num(ic);
-          setfltvalue(s2v(ra), luai_numpow(L, nb, nc));
-        }
-        else
-          Protect(luaT_trybiniTM(L, rb, ic, 0, ra, TM_POW));
+        op_arithfI(L, luai_numpow, TM_POW);
         vmbreak;
       }
       vmcase(OP_DIVI) {
-        TValue *rb = vRB(i);
-        int ic = GETARG_sC(i);
-        lua_Number nb;
-        if (tonumberns(rb, nb)) {
-          lua_Number nc = cast_num(ic);
-          setfltvalue(s2v(ra), luai_numdiv(L, nb, nc));
-        }
-        else
-          Protect(luaT_trybiniTM(L, rb, ic, 0, ra, TM_DIV));
+        op_arithfI(L, luai_numdiv, TM_DIV);
         vmbreak;
       }
       vmcase(OP_IDIVI) {
-        TValue *rb = vRB(i);
-        int ic = GETARG_sC(i);
-        lua_Number nb;
-        if (ttisinteger(rb)) {
-          setivalue(s2v(ra), luaV_div(L, ivalue(rb), ic));
-        }
-        else if (tonumberns(rb, nb)) {
-          lua_Number nc = cast_num(ic);
-          setfltvalue(s2v(ra), luai_numdiv(L, nb, nc));
-        }
-        else
-          Protect(luaT_trybiniTM(L, rb, ic, 0, ra, TM_IDIV));
+        op_arithI(L, luaV_idiv, luai_numidiv, TM_IDIV, 0);
+        vmbreak;
+      }
+      vmcase(OP_ADDK) {
+        op_arithK(L, l_addi, luai_numadd, TM_ADD, GETARG_k(i));
+        vmbreak;
+      }
+      vmcase(OP_SUBK) {
+        op_arithK(L, l_subi, luai_numsub, TM_SUB, 0);
+        vmbreak;
+      }
+      vmcase(OP_MULK) {
+        op_arithK(L, l_muli, luai_nummul, TM_MUL, GETARG_k(i));
+        vmbreak;
+      }
+      vmcase(OP_MODK) {
+        op_arithK(L, luaV_mod, luaV_modf, TM_MOD, 0);
+        vmbreak;
+      }
+      vmcase(OP_POWK) {
+        op_arithfK(L, luai_numpow, TM_POW);
+        vmbreak;
+      }
+      vmcase(OP_DIVK) {
+        op_arithfK(L, luai_numdiv, TM_DIV);
+        vmbreak;
+      }
+      vmcase(OP_IDIVK) {
+        op_arithK(L, luaV_idiv, luai_numidiv, TM_IDIV, 0);
         vmbreak;
       }
       vmcase(OP_ADD) {
-        TValue *rb = vRB(i);
-        TValue *rc = vRC(i);
-        lua_Number nb; lua_Number nc;
-        if (ttisinteger(rb) && ttisinteger(rc)) {
-          lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc);
-          setivalue(s2v(ra), intop(+, ib, ic));
-        }
-        else if (tonumberns(rb, nb) && tonumberns(rc, nc)) {
-          setfltvalue(s2v(ra), luai_numadd(L, nb, nc));
-        }
-        else
-          Protect(luaT_trybinTM(L, rb, rc, ra, TM_ADD));
+        op_arith(L, l_addi, luai_numadd, TM_ADD);
         vmbreak;
       }
       vmcase(OP_SUB) {
-        TValue *rb = vRB(i);
-        TValue *rc = vRC(i);
-        lua_Number nb; lua_Number nc;
-        if (ttisinteger(rb) && ttisinteger(rc)) {
-          lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc);
-          setivalue(s2v(ra), intop(-, ib, ic));
-        }
-        else if (tonumberns(rb, nb) && tonumberns(rc, nc)) {
-          setfltvalue(s2v(ra), luai_numsub(L, nb, nc));
-        }
-        else
-          Protect(luaT_trybinTM(L, rb, rc, ra, TM_SUB));
+        op_arith(L, l_subi, luai_numsub, TM_SUB);
         vmbreak;
       }
       vmcase(OP_MUL) {
-        TValue *rb = vRB(i);
-        TValue *rc = vRC(i);
-        lua_Number nb; lua_Number nc;
-        if (ttisinteger(rb) && ttisinteger(rc)) {
-          lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc);
-          setivalue(s2v(ra), intop(*, ib, ic));
-        }
-        else if (tonumberns(rb, nb) && tonumberns(rc, nc)) {
-          setfltvalue(s2v(ra), luai_nummul(L, nb, nc));
-        }
-        else
-          Protect(luaT_trybinTM(L, rb, rc, ra, TM_MUL));
+        op_arith(L, l_muli, luai_nummul, TM_MUL);
+        vmbreak;
+      }
+      vmcase(OP_MOD) {
+        op_arith(L, luaV_mod, luaV_modf, TM_MOD);
+        vmbreak;
+      }
+      vmcase(OP_POW) {
+        op_arithf(L, luai_numpow, TM_POW);
         vmbreak;
       }
       vmcase(OP_DIV) {  /* float division (always with floats) */
-        TValue *rb = vRB(i);
-        TValue *rc = vRC(i);
-        lua_Number nb; lua_Number nc;
-        if (tonumberns(rb, nb) && tonumberns(rc, nc)) {
-          setfltvalue(s2v(ra), luai_numdiv(L, nb, nc));
-        }
-        else
-          Protect(luaT_trybinTM(L, rb, rc, ra, TM_DIV));
+        op_arithf(L, luai_numdiv, TM_DIV);
+        vmbreak;
+      }
+      vmcase(OP_IDIV) {  /* floor division */
+        op_arith(L, luaV_idiv, luai_numidiv, TM_IDIV);
         vmbreak;
       }
       vmcase(OP_BANDK) {
-        TValue *p1 = vRB(i);
-        TValue *p2 = KC(i);
-        lua_Integer i1;
-        if (tointegerns(p1, &i1)) {
-          setivalue(s2v(ra), intop(&, i1, ivalue(p2)));
-        }
-        else
-          Protect(luaT_trybinassocTM(L, p1, p2, ra, TESTARG_k(i), TM_BAND));
+        op_bitwiseK(L, l_band, TM_BAND);
         vmbreak;
       }
       vmcase(OP_BORK) {
-        TValue *p1 = vRB(i);
-        TValue *p2 = KC(i);
-        lua_Integer i1;
-        if (tointegerns(p1, &i1)) {
-          setivalue(s2v(ra), intop(|, i1, ivalue(p2)));
-        }
-        else
-          Protect(luaT_trybinassocTM(L, p1, p2, ra, TESTARG_k(i), TM_BOR));
+        op_bitwiseK(L, l_bor, TM_BOR);
         vmbreak;
       }
       vmcase(OP_BXORK) {
-        TValue *p1 = vRB(i);
-        TValue *p2 = KC(i);
-        lua_Integer i1;
-        if (tointegerns(p1, &i1)) {
-          setivalue(s2v(ra), intop(^, i1, ivalue(p2)));
-        }
-        else
-          Protect(luaT_trybinassocTM(L, p1, p2, ra, TESTARG_k(i), TM_BXOR));
+        op_bitwiseK(L, l_bxor, TM_BXOR);
         vmbreak;
       }
       vmcase(OP_BAND) {
-        TValue *rb = vRB(i);
-        TValue *rc = vRC(i);
-        lua_Integer ib; lua_Integer ic;
-        if (tointegerns(rb, &ib) && tointegerns(rc, &ic)) {
-          setivalue(s2v(ra), intop(&, ib, ic));
-        }
-        else
-          Protect(luaT_trybinTM(L, rb, rc, ra, TM_BAND));
+        op_bitwise(L, l_band, TM_BAND);
         vmbreak;
       }
       vmcase(OP_BOR) {
-        TValue *rb = vRB(i);
-        TValue *rc = vRC(i);
-        lua_Integer ib; lua_Integer ic;
-        if (tointegerns(rb, &ib) && tointegerns(rc, &ic)) {
-          setivalue(s2v(ra), intop(|, ib, ic));
-        }
-        else
-          Protect(luaT_trybinTM(L, rb, rc, ra, TM_BOR));
+        op_bitwise(L, l_bor, TM_BOR);
         vmbreak;
       }
       vmcase(OP_BXOR) {
-        TValue *rb = vRB(i);
-        TValue *rc = vRC(i);
-        lua_Integer ib; lua_Integer ic;
-        if (tointegerns(rb, &ib) && tointegerns(rc, &ic)) {
-          setivalue(s2v(ra), intop(^, ib, ic));
-        }
-        else
-          Protect(luaT_trybinTM(L, rb, rc, ra, TM_BXOR));
+        op_bitwise(L, l_bxor, TM_BXOR);
         vmbreak;
       }
       vmcase(OP_SHRI) {

@@ -1337,17 +1398,6 @@
           Protect(luaT_trybiniTM(L, rb, ic, 1, ra, TM_SHL));
         vmbreak;
       }
-      vmcase(OP_SHL) {
-        TValue *rb = vRB(i);
-        TValue *rc = vRC(i);
-        lua_Integer ib; lua_Integer ic;
-        if (tointegerns(rb, &ib) && tointegerns(rc, &ic)) {
-          setivalue(s2v(ra), luaV_shiftl(ib, ic));
-        }
-        else
-          Protect(luaT_trybinTM(L, rb, rc, ra, TM_SHL));
-        vmbreak;
-      }
       vmcase(OP_SHR) {
         TValue *rb = vRB(i);
         TValue *rc = vRC(i);

@@ -1359,47 +1409,15 @@
           Protect(luaT_trybinTM(L, rb, rc, ra, TM_SHR));
         vmbreak;
       }
-      vmcase(OP_MOD) {
-        TValue *rb = vRB(i);
-        TValue *rc = vRC(i);
-        lua_Number nb; lua_Number nc;
-        if (ttisinteger(rb) && ttisinteger(rc)) {
-          lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc);
-          setivalue(s2v(ra), luaV_mod(L, ib, ic));
-        }
-        else if (tonumberns(rb, nb) && tonumberns(rc, nc)) {
-          lua_Number m;
-          luai_nummod(L, nb, nc, m);
-          setfltvalue(s2v(ra), m);
-        }
-        else
-          Protect(luaT_trybinTM(L, rb, rc, ra, TM_MOD));
-        vmbreak;
-      }
-      vmcase(OP_IDIV) {  /* floor division */
-        TValue *rb = vRB(i);
-        TValue *rc = vRC(i);
-        lua_Number nb; lua_Number nc;
-        if (ttisinteger(rb) && ttisinteger(rc)) {
-          lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc);
-          setivalue(s2v(ra), luaV_div(L, ib, ic));
-        }
-        else if (tonumberns(rb, nb) && tonumberns(rc, nc)) {
-          setfltvalue(s2v(ra), luai_numidiv(L, nb, nc));
-        }
-        else
-          Protect(luaT_trybinTM(L, rb, rc, ra, TM_IDIV));
-        vmbreak;
-      }
-      vmcase(OP_POW) {
+      vmcase(OP_SHL) {
         TValue *rb = vRB(i);
         TValue *rc = vRC(i);
-        lua_Number nb; lua_Number nc;
-        if (tonumberns(rb, nb) && tonumberns(rc, nc)) {
-          setfltvalue(s2v(ra), luai_numpow(L, nb, nc));
+        lua_Integer ib; lua_Integer ic;
+        if (tointegerns(rb, &ib) && tointegerns(rc, &ic)) {
+          setivalue(s2v(ra), luaV_shiftl(ib, ic));
         }
         else
-          Protect(luaT_trybinTM(L, rb, rc, ra, TM_POW));
+          Protect(luaT_trybinTM(L, rb, rc, ra, TM_SHL));
         vmbreak;
       }
       vmcase(OP_UNM) {

@@ -1444,7 +1462,13 @@
         vmbreak;
       }
       vmcase(OP_CLOSE) {
-        luaF_close(L, ra);
+        L->top = ra + 1;  /* everything is free after this slot */
+        Protect(luaF_close(L, ra, LUA_OK));
+        vmbreak;
+      }
+      vmcase(OP_TBC) {
+        /* create new to-be-closed upvalue */
+        halfProtect(luaF_newtbcupval(L, ra));
         vmbreak;
       }
       vmcase(OP_JMP) {

@@ -1452,41 +1476,29 @@
         vmbreak;
       }
       vmcase(OP_EQ) {
+        int cond;
         TValue *rb = vRB(i);
         Protect(cond = luaV_equalobj(L, s2v(ra), rb));
         docondjump();
         vmbreak;
       }
       vmcase(OP_LT) {
-        TValue *rb = vRB(i);
-        if (ttisinteger(s2v(ra)) && ttisinteger(rb))
-          cond = (ivalue(s2v(ra)) < ivalue(rb));
-        else if (ttisnumber(s2v(ra)) && ttisnumber(rb))
-          cond = LTnum(s2v(ra), rb);
-        else
-          Protect(cond = lessthanothers(L, s2v(ra), rb));
-        docondjump();
+        op_order(L, l_lti, LTnum, lessthanothers);
         vmbreak;
       }
       vmcase(OP_LE) {
-        TValue *rb = vRB(i);
-        if (ttisinteger(s2v(ra)) && ttisinteger(rb))
-          cond = (ivalue(s2v(ra)) <= ivalue(rb));
-        else if (ttisnumber(s2v(ra)) && ttisnumber(rb))
-          cond = LEnum(s2v(ra), rb);
-        else
-          Protect(cond = lessequalothers(L, s2v(ra), rb));
-        docondjump();
+        op_order(L, l_lei, LEnum, lessequalothers);
         vmbreak;
       }
       vmcase(OP_EQK) {
         TValue *rb = KB(i);
         /* basic types do not use '__eq'; we can use raw equality */
-        cond = luaV_equalobj(NULL, s2v(ra), rb);
+        int cond = luaV_equalobj(NULL, s2v(ra), rb);
         docondjump();
         vmbreak;
       }
       vmcase(OP_EQI) {
+        int cond;
         int im = GETARG_sB(i);
         if (ttisinteger(s2v(ra)))
           cond = (ivalue(s2v(ra)) == im);

@@ -1498,51 +1510,23 @@
         vmbreak;
       }
       vmcase(OP_LTI) {
-        int im = GETARG_sB(i);
-        if (ttisinteger(s2v(ra)))
-          cond = (ivalue(s2v(ra)) < im);
-        else if (ttisfloat(s2v(ra)))
-          cond = luai_numlt(fltvalue(s2v(ra)), cast_num(im));
-        else
-          Protect(cond = luaT_callorderiTM(L, s2v(ra), im, 0, TM_LT));
-        docondjump();
+        op_orderI(L, l_lti, luai_numlt, 0, TM_LT);
         vmbreak;
       }
       vmcase(OP_LEI) {
-        int im = GETARG_sB(i);
-        if (ttisinteger(s2v(ra)))
-          cond = (ivalue(s2v(ra)) <= im);
-        else if (ttisfloat(s2v(ra)))
-          cond = luai_numle(fltvalue(s2v(ra)), cast_num(im));
-        else
-          Protect(cond = luaT_callorderiTM(L, s2v(ra), im, 0, TM_LE));
-        docondjump();
+        op_orderI(L, l_lei, luai_numle, 0, TM_LE);
         vmbreak;
       }
       vmcase(OP_GTI) {
-        int im = GETARG_sB(i);
-        if (ttisinteger(s2v(ra)))
-          cond = (im < ivalue(s2v(ra)));
-        else if (ttisfloat(s2v(ra)))
-          cond = luai_numlt(cast_num(im), fltvalue(s2v(ra)));
-        else
-          Protect(cond = luaT_callorderiTM(L, s2v(ra), im, 1, TM_LT));
-        docondjump();
+        op_orderI(L, l_gti, luai_numgt, 1, TM_LT);
         vmbreak;
       }
       vmcase(OP_GEI) {
-        int im = GETARG_sB(i);
-        if (ttisinteger(s2v(ra)))
-          cond = (im <= ivalue(s2v(ra)));
-        else if (ttisfloat(s2v(ra)))
-          cond = luai_numle(cast_num(im), fltvalue(s2v(ra)));
-        else
-          Protect(cond = luaT_callorderiTM(L, s2v(ra), im, 1, TM_LE));
-        docondjump();
+        op_orderI(L, l_gei, luai_numge, 1, TM_LE);
         vmbreak;
       }
       vmcase(OP_TEST) {
-        cond = !l_isfalse(s2v(ra));
+        int cond = !l_isfalse(s2v(ra));
         docondjump();
         vmbreak;
       }

@@ -1572,12 +1556,14 @@
           L->top = ra + b;
         else  /* previous instruction set top */
           b = cast_int(L->top - ra);
-        savepc(ci);
+        savepc(ci);  /* some calls here can raise errors */
         if (TESTARG_k(i)) {
           int nparams1 = GETARG_C(i);
           if (nparams1)  /* vararg function? */
             delta = ci->u.l.nextraargs + nparams1;
-          luaF_close(L, base);  /* close upvalues from current call */
+          /* close upvalues from current call; the compiler ensures
+             that there are no to-be-closed variables here */
+          luaF_close(L, base, NOCLOSINGMETH);
         }
         if (!ttisfunction(s2v(ra))) {  /* not a function? */
           luaD_tryfuncTM(L, ra);  /* try '__call' metamethod */

@@ -1586,10 +1572,7 @@
         if (!ttisLclosure(s2v(ra))) {  /* C function? */
           luaD_call(L, ra, LUA_MULTRET);  /* call it */
           updatetrap(ci);
-          if (trap) {  /* stack may have been relocated */
-            updatebase(ci);
-            ra = RA(i);
-          }
+          updatestack(ci);  /* stack may have been relocated */
           ci->func -= delta;
           luaD_poscall(L, ci, cast_int(L->top - ra));
           return;

@@ -1607,13 +1590,14 @@
           n = cast_int(L->top - ra);  /* get what is available */
         else
           L->top = ra + n;  /* set call for 'luaD_poscall' */
+        savepc(ci);
         if (TESTARG_k(i)) {
           int nparams1 = GETARG_C(i);
           if (nparams1)  /* vararg function? */
             ci->func -= ci->u.l.nextraargs + nparams1;
-          luaF_close(L, base);  /* there may be open upvalues */
+          luaF_close(L, base, LUA_OK);  /* there may be open upvalues */
         }
-        halfProtect(luaD_poscall(L, ci, n));
+        luaD_poscall(L, ci, n);
         return;
       }
       vmcase(OP_RETURN0) {

@@ -1621,7 +1605,7 @@
           L->top = ra;
           halfProtect(luaD_poscall(L, ci, 0));  /* no hurry... */
         }
-        else {
+        else {  /* do the 'poscall' here */
           int nres = ci->nresults;
           L->ci = ci->previous;  /* back to caller */
           L->top = base - 1;

@@ -1635,7 +1619,7 @@
           L->top = ra + 1;
           halfProtect(luaD_poscall(L, ci, 1));  /* no hurry... */
         }
-        else {
+        else {  /* do the 'poscall' here */
           int nres = ci->nresults;
           L->ci = ci->previous;  /* back to caller */
           if (nres == 0)

@@ -1649,105 +1633,119 @@
         }
         return;
       }
-      vmcase(OP_FORLOOP1) {
-        lua_Integer idx = intop(+, ivalue(s2v(ra)), 1); /* increment index */
-        lua_Integer limit = ivalue(s2v(ra + 1));
-        if (idx <= limit) {
-          pc -= GETARG_Bx(i);  /* jump back */
-          chgivalue(s2v(ra), idx);  /* update internal index... */
-          setivalue(s2v(ra + 3), idx);  /* ...and external index */
-        }
-        updatetrap(ci);
-        vmbreak;
-      }
-      vmcase(OP_FORPREP1) {
-        TValue *init = s2v(ra);
-        TValue *plimit = s2v(ra + 1);
-        lua_Integer ilimit, initv;
-        int stopnow;
-        if (unlikely(!forlimit(plimit, &ilimit, 1, &stopnow))) {
-            savestate(L, ci);  /* for the error message */
-            luaG_runerror(L, "'for' limit must be a number");
-        }
-        initv = (stopnow ? 0 : ivalue(init));
-        setivalue(plimit, ilimit);
-        setivalue(init, intop(-, initv, 1));
-        pc += GETARG_Bx(i);
-        vmbreak;
-      }
       vmcase(OP_FORLOOP) {
-        if (ttisinteger(s2v(ra))) {  /* integer loop? */
-          lua_Integer step = ivalue(s2v(ra + 2));
-          lua_Integer idx = intop(+, ivalue(s2v(ra)), step); /* new index */
-          lua_Integer limit = ivalue(s2v(ra + 1));
-          if ((0 < step) ? (idx <= limit) : (limit <= idx)) {
+        if (ttisinteger(s2v(ra + 2))) {  /* integer loop? */
+          lua_Unsigned count = l_castS2U(ivalue(s2v(ra + 1)));
+          if (count > 0) {  /* still more iterations? */
+            lua_Integer step = ivalue(s2v(ra + 2));
+            lua_Integer idx = ivalue(s2v(ra));  /* internal index */
+            chgivalue(s2v(ra + 1), count - 1);  /* update counter */
+            idx = intop(+, idx, step);  /* add step to index */
+            chgivalue(s2v(ra), idx);  /* update internal index */
+            setivalue(s2v(ra + 3), idx);  /* and control variable */
             pc -= GETARG_Bx(i);  /* jump back */
-            chgivalue(s2v(ra), idx);  /* update internal index... */
-            setivalue(s2v(ra + 3), idx);  /* ...and external index */
           }
         }
         else {  /* floating loop */
           lua_Number step = fltvalue(s2v(ra + 2));
           lua_Number limit = fltvalue(s2v(ra + 1));
           lua_Number idx = fltvalue(s2v(ra));
-          idx = luai_numadd(L, idx, step);  /* inc. index */
+          idx = luai_numadd(L, idx, step);  /* increment index */
           if (luai_numlt(0, step) ? luai_numle(idx, limit)
                                   : luai_numle(limit, idx)) {
+            chgfltvalue(s2v(ra), idx);  /* update internal index */
+            setfltvalue(s2v(ra + 3), idx);  /* and control variable */
             pc -= GETARG_Bx(i);  /* jump back */
-            chgfltvalue(s2v(ra), idx);  /* update internal index... */
-            setfltvalue(s2v(ra + 3), idx);  /* ...and external index */
           }
         }
-        updatetrap(ci);
+        updatetrap(ci);  /* allows a signal to break the loop */
         vmbreak;
       }
       vmcase(OP_FORPREP) {
-        TValue *init = s2v(ra);
+        TValue *pinit = s2v(ra);
         TValue *plimit = s2v(ra + 1);
         TValue *pstep = s2v(ra + 2);
-        lua_Integer ilimit;
-        int stopnow;
-        if (ttisinteger(init) && ttisinteger(pstep) &&
-            forlimit(plimit, &ilimit, ivalue(pstep), &stopnow)) {
-          /* all values are integer */
-          lua_Integer initv = (stopnow ? 0 : ivalue(init));
-          setivalue(plimit, ilimit);
-          setivalue(init, intop(-, initv, ivalue(pstep)));
+        savestate(L, ci);  /* in case of errors */
+        if (ttisinteger(pinit) && ttisinteger(pstep)) { /* integer loop? */
+          lua_Integer init = ivalue(pinit);
+          lua_Integer step = ivalue(pstep);
+          lua_Integer limit;
+          if (step == 0)
+            luaG_runerror(L, "'for' step is zero");
+          setivalue(s2v(ra + 3), init);  /* control variable */
+          if (forlimit(L, init, plimit, &limit, step))
+            pc += GETARG_Bx(i) + 1;  /* skip the loop */
+          else {  /* prepare loop counter */
+            lua_Unsigned count;
+            if (step > 0) {  /* ascending loop? */
+              count = l_castS2U(limit) - l_castS2U(init);
+              if (step != 1)  /* avoid division in the too common case */
+                count /= l_castS2U(step);
+            }
+            else {  /* step < 0; descending loop */
+              count = l_castS2U(init) - l_castS2U(limit);
+              /* 'step+1' avoids negating 'mininteger' */
+              count /= l_castS2U(-(step + 1)) + 1u;
+            }
+            /* store the counter in place of the limit (which won't be
+               needed anymore */
+            setivalue(plimit, l_castU2S(count));
+          }
         }
         else {  /* try making all values floats */
-          lua_Number ninit; lua_Number nlimit; lua_Number nstep;
-          savestate(L, ci);  /* in case of errors */
-          if (unlikely(!tonumber(plimit, &nlimit)))
-            luaG_runerror(L, "'for' limit must be a number");
-          setfltvalue(plimit, nlimit);
-          if (unlikely(!tonumber(pstep, &nstep)))
-            luaG_runerror(L, "'for' step must be a number");
-          setfltvalue(pstep, nstep);
-          if (unlikely(!tonumber(init, &ninit)))
-            luaG_runerror(L, "'for' initial value must be a number");
-          setfltvalue(init, luai_numsub(L, ninit, nstep));
+          lua_Number init; lua_Number limit; lua_Number step;
+          if (unlikely(!tonumber(plimit, &limit)))
+            luaG_forerror(L, plimit, "limit");
+          if (unlikely(!tonumber(pstep, &step)))
+            luaG_forerror(L, pstep, "step");
+          if (unlikely(!tonumber(pinit, &init)))
+            luaG_forerror(L, pinit, "initial value");
+          if (step == 0)
+            luaG_runerror(L, "'for' step is zero");
+          if (luai_numlt(0, step) ? luai_numlt(limit, init)
+                                   : luai_numlt(init, limit))
+            pc += GETARG_Bx(i) + 1;  /* skip the loop */
+          else {
+            /* make sure internal values are all float */
+            setfltvalue(plimit, limit);
+            setfltvalue(pstep, step);
+            setfltvalue(s2v(ra), init);  /* internal index */
+            setfltvalue(s2v(ra + 3), init);  /* control variable */
+          }
         }
-        pc += GETARG_Bx(i);
         vmbreak;
       }
+      vmcase(OP_TFORPREP) {
+        if (!ttisnil(s2v(ra + 3))) {  /* is 'toclose' not nil? */
+          /* create to-be-closed upvalue for it */
+          halfProtect(luaF_newtbcupval(L, ra + 3));
+        }
+        pc += GETARG_Bx(i);
+        i = *(pc++);  /* go to next instruction */
+        lua_assert(GET_OPCODE(i) == OP_TFORCALL && ra == RA(i));
+        goto l_tforcall;
+      }
       vmcase(OP_TFORCALL) {
-        StkId cb = ra + 3;  /* call base */
-        setobjs2s(L, cb+2, ra+2);
-        setobjs2s(L, cb+1, ra+1);
-        setobjs2s(L, cb, ra);
-        L->top = cb + 3;  /* func. + 2 args (state and index) */
-        Protect(luaD_call(L, cb, GETARG_C(i)));
-        if (trap)  /* keep 'base' correct for next instruction */
-          updatebase(ci);
+       l_tforcall:
+        /* 'ra' has the iterator function, 'ra + 1' has the state,
+           'ra + 2' has the control variable, and 'ra + 3' has the
+           to-be-closed variable. The call will use the stack after
+           these values (starting at 'ra + 4')
+        */
+        /* push function, state, and control variable */
+        memcpy(ra + 4, ra, 3 * sizeof(*ra));
+        L->top = ra + 4 + 3;
+        Protect(luaD_call(L, ra + 4, GETARG_C(i)));  /* do the call */
+        updatestack(ci);  /* stack may have changed */
         i = *(pc++);  /* go to next instruction */
-        ra = RA(i);  /* get its 'ra' */
-        lua_assert(GET_OPCODE(i) == OP_TFORLOOP);
+        ra += 2;  /* adjust for next instruction */
+        lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i));
         goto l_tforloop;
       }
       vmcase(OP_TFORLOOP) {
         l_tforloop:
-        if (!ttisnil(s2v(ra + 1))) {  /* continue loop? */
-          setobjs2s(L, ra, ra + 1);  /* save control variable */
+        if (!ttisnil(s2v(ra + 2))) {  /* continue loop? */
+          setobjs2s(L, ra, ra + 2);  /* save control variable */
           pc -= GETARG_Bx(i);  /* jump back */
         }
         vmbreak;

@@ -1778,13 +1776,7 @@
       }
       vmcase(OP_CLOSURE) {
         Proto *p = cl->p->p[GETARG_Bx(i)];
-        LClosure *ncl = getcached(p, cl->upvals, base);  /* cached closure */
-        if (ncl == NULL) {  /* no match? */
-          savestate(L, ci);  /* in case of allocation errors */
-          pushclosure(L, p, cl->upvals, base, ra);  /* create a new one */
-        }
-        else
-          setclLvalue2s(L, ra, ncl);  /* push cashed closure */
+        halfProtect(pushclosure(L, p, cl->upvals, base, ra));
         checkGC(L, ra + 1);
         vmbreak;
       }

@@ -1793,7 +1785,7 @@
         Protect(luaT_getvarargs(L, ci, ra, n));
         vmbreak;
       }
-      vmcase(OP_PREPVARARG) {
+      vmcase(OP_VARARGPREP) {
         luaT_adjustvarargs(L, GETARG_A(i), ci, cl->p);
         updatetrap(ci);
         if (trap) {

src/lvm.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.h,v 2.52 2018/06/15 14:14:20 roberto Exp $
+** $Id: lvm.h $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */

@@ -114,8 +114,9 @@
 LUAI_FUNC void luaV_finishOp (lua_State *L);
 LUAI_FUNC void luaV_execute (lua_State *L, CallInfo *ci);
 LUAI_FUNC void luaV_concat (lua_State *L, int total);
-LUAI_FUNC lua_Integer luaV_div (lua_State *L, lua_Integer x, lua_Integer y);
+LUAI_FUNC lua_Integer luaV_idiv (lua_State *L, lua_Integer x, lua_Integer y);
 LUAI_FUNC lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y);
+LUAI_FUNC lua_Number luaV_modf (lua_State *L, lua_Number x, lua_Number y);
 LUAI_FUNC lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y);
 LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb);
 

src/lzio.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lzio.c,v 1.37 2015/09/08 15:41:05 roberto Exp $
+** $Id: lzio.c $
 ** Buffered streams
 ** See Copyright Notice in lua.h
 */

src/lzio.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lzio.h,v 1.31 2015/09/08 15:41:05 roberto Exp $
+** $Id: lzio.h $
 ** Buffered streams
 ** See Copyright Notice in lua.h
 */