diffu-lua-5.5.0-beta-rc1
README
@@ -1,5 +1,5 @@
-This is Lua 5.5.0 (beta), released on 28 Jun 2025.
+This is Lua 5.5.0, released on 14 Nov 2025.
For installation instructions, license details, and
further information about Lua, see doc/readme.html.
doc/contents.html
@@ -86,6 +86,7 @@
<LI><A HREF="manual.html#3.4.10">3.4.10 – Function Calls</A>
<LI><A HREF="manual.html#3.4.11">3.4.11 – Function Definitions</A>
<LI><A HREF="manual.html#3.4.12">3.4.12 – Lists of expressions, multiple results, and adjustment<A>
+</UL>
<P>
<LI><A HREF="manual.html#4">4 – The Application Program Interface</A>
<UL>
@@ -148,7 +149,7 @@
<TD>
<H3><A NAME="functions">Lua functions</A></H3>
<P>
-<A HREF="manual.html#6.1">basic</A><BR>
+<A HREF="manual.html#6.2">basic</A><BR>
<A HREF="manual.html#pdf-_G">_G</A><BR>
<A HREF="manual.html#pdf-_VERSION">_VERSION</A><BR>
<A HREF="manual.html#pdf-assert">assert</A><BR>
@@ -177,7 +178,7 @@
<A HREF="manual.html#pdf-xpcall">xpcall</A><BR>
<P>
-<A HREF="manual.html#6.2">coroutine</A><BR>
+<A HREF="manual.html#6.3">coroutine</A><BR>
<A HREF="manual.html#pdf-coroutine.close">coroutine.close</A><BR>
<A HREF="manual.html#pdf-coroutine.create">coroutine.create</A><BR>
<A HREF="manual.html#pdf-coroutine.isyieldable">coroutine.isyieldable</A><BR>
@@ -188,7 +189,7 @@
<A HREF="manual.html#pdf-coroutine.yield">coroutine.yield</A><BR>
<P>
-<A HREF="manual.html#6.10">debug</A><BR>
+<A HREF="manual.html#6.11">debug</A><BR>
<A HREF="manual.html#pdf-debug.debug">debug.debug</A><BR>
<A HREF="manual.html#pdf-debug.gethook">debug.gethook</A><BR>
<A HREF="manual.html#pdf-debug.getinfo">debug.getinfo</A><BR>
@@ -207,7 +208,7 @@
<A HREF="manual.html#pdf-debug.upvaluejoin">debug.upvaluejoin</A><BR>
<P>
-<A HREF="manual.html#6.8">io</A><BR>
+<A HREF="manual.html#6.9">io</A><BR>
<A HREF="manual.html#pdf-io.close">io.close</A><BR>
<A HREF="manual.html#pdf-io.flush">io.flush</A><BR>
<A HREF="manual.html#pdf-io.input">io.input</A><BR>
@@ -235,7 +236,7 @@
<TD>
<H3> </H3>
<P>
-<A HREF="manual.html#6.7">math</A><BR>
+<A HREF="manual.html#6.8">math</A><BR>
<A HREF="manual.html#pdf-math.abs">math.abs</A><BR>
<A HREF="manual.html#pdf-math.acos">math.acos</A><BR>
<A HREF="manual.html#pdf-math.asin">math.asin</A><BR>
@@ -246,7 +247,9 @@
<A HREF="manual.html#pdf-math.exp">math.exp</A><BR>
<A HREF="manual.html#pdf-math.floor">math.floor</A><BR>
<A HREF="manual.html#pdf-math.fmod">math.fmod</A><BR>
+<A HREF="manual.html#pdf-math.frexp">math.frexp</A><BR>
<A HREF="manual.html#pdf-math.huge">math.huge</A><BR>
+<A HREF="manual.html#pdf-math.ldexp">math.ldexp</A><BR>
<A HREF="manual.html#pdf-math.log">math.log</A><BR>
<A HREF="manual.html#pdf-math.max">math.max</A><BR>
<A HREF="manual.html#pdf-math.maxinteger">math.maxinteger</A><BR>
@@ -265,7 +268,7 @@
<A HREF="manual.html#pdf-math.ult">math.ult</A><BR>
<P>
-<A HREF="manual.html#6.9">os</A><BR>
+<A HREF="manual.html#6.10">os</A><BR>
<A HREF="manual.html#pdf-os.clock">os.clock</A><BR>
<A HREF="manual.html#pdf-os.date">os.date</A><BR>
<A HREF="manual.html#pdf-os.difftime">os.difftime</A><BR>
@@ -279,7 +282,7 @@
<A HREF="manual.html#pdf-os.tmpname">os.tmpname</A><BR>
<P>
-<A HREF="manual.html#6.3">package</A><BR>
+<A HREF="manual.html#6.4">package</A><BR>
<A HREF="manual.html#pdf-package.config">package.config</A><BR>
<A HREF="manual.html#pdf-package.cpath">package.cpath</A><BR>
<A HREF="manual.html#pdf-package.loaded">package.loaded</A><BR>
@@ -290,7 +293,7 @@
<A HREF="manual.html#pdf-package.searchpath">package.searchpath</A><BR>
<P>
-<A HREF="manual.html#6.4">string</A><BR>
+<A HREF="manual.html#6.5">string</A><BR>
<A HREF="manual.html#pdf-string.byte">string.byte</A><BR>
<A HREF="manual.html#pdf-string.char">string.char</A><BR>
<A HREF="manual.html#pdf-string.dump">string.dump</A><BR>
@@ -310,8 +313,9 @@
<A HREF="manual.html#pdf-string.upper">string.upper</A><BR>
<P>
-<A HREF="manual.html#6.6">table</A><BR>
+<A HREF="manual.html#6.7">table</A><BR>
<A HREF="manual.html#pdf-table.concat">table.concat</A><BR>
+<A HREF="manual.html#pdf-table.create">table.create</A><BR>
<A HREF="manual.html#pdf-table.insert">table.insert</A><BR>
<A HREF="manual.html#pdf-table.move">table.move</A><BR>
<A HREF="manual.html#pdf-table.pack">table.pack</A><BR>
@@ -320,7 +324,7 @@
<A HREF="manual.html#pdf-table.unpack">table.unpack</A><BR>
<P>
-<A HREF="manual.html#6.5">utf8</A><BR>
+<A HREF="manual.html#6.6">utf8</A><BR>
<A HREF="manual.html#pdf-utf8.char">utf8.char</A><BR>
<A HREF="manual.html#pdf-utf8.charpattern">utf8.charpattern</A><BR>
<A HREF="manual.html#pdf-utf8.codepoint">utf8.codepoint</A><BR>
@@ -528,6 +532,7 @@
<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_alloc">luaL_alloc</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>
@@ -669,7 +674,7 @@
<P CLASS="footer">
Last update:
-Tue Jun 24 10:26:21 UTC 2025
+Sat Nov 15 00:51:05 UTC 2025
</P>
<!--
Last change: revised for Lua 5.5.0
doc/manual.html
@@ -190,7 +190,8 @@
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.
+The length of any string in Lua must fit in a Lua integer,
+and the string plus a small header must fit in <code>size_t</code>.
<p>
@@ -314,7 +315,7 @@
<pre>
X = 1 -- Ok, global by default
do
- global Y -- voids implicit initial declaration
+ global Y -- voids the implicit initial declaration
Y = 1 -- Ok, Y declared as global
X = 1 -- ERROR, X not declared
end
@@ -360,7 +361,7 @@
<p>
Notice that, in a declaration like <code>local x = x</code>,
the new <code>x</code> being declared is not in scope yet,
-and so the <code>x</code> in the left-hand side refers to the outside variable.
+and so the <code>x</code> on the right-hand side refers to the outside variable.
<p>
@@ -1895,7 +1896,8 @@
stat ::= <b>for</b> Name ‘<b>=</b>’ exp ‘<b>,</b>’ exp [‘<b>,</b>’ exp] <b>do</b> block <b>end</b>
</pre><p>
The given identifier (Name) defines the control variable,
-which is a new read-only variable local to the loop body (<em>block</em>).
+which is a new read-only (<code>const</code>) variable local to the loop body
+(<em>block</em>).
<p>
@@ -1963,7 +1965,7 @@
<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>,
-which is a read-only variable.
+which is a read-only (<code>const</code>) variable.
<p>
@@ -2015,15 +2017,21 @@
<h3>3.3.7 – <a name="3.3.7">Variable Declarations</a></h3><p>
Local and global variables can be declared anywhere inside a block.
-The declaration for locals can include an initialization:
+The declaration can include an initialization:
<pre>
stat ::= <b>local</b> attnamelist [‘<b>=</b>’ explist]
- stat ::= <b>global</b> attnamelist
+ stat ::= <b>global</b> attnamelist [‘<b>=</b>’ explist]
</pre><p>
-If present, an initial assignment has the same semantics
+If there is no initialization,
+local variables are initialized with <b>nil</b>;
+global variables are left unchanged.
+Otherwise, the initialization gets the same adjustment
of a multiple assignment (see <a href="#3.3.3">§3.3.3</a>).
-Otherwise, all local variables are initialized with <b>nil</b>.
+Moreover, for global variables,
+the initialization will raise a runtime error
+if the variable is already defined,
+that is, it has a non-nil value.
<p>
@@ -2084,7 +2092,8 @@
<p>
Note that, for global variables,
-the effect of any declaration is only syntactical:
+the effect of any declaration is only syntactical
+(except for the optional assignment):
<pre>
global X <const>, _G
@@ -2747,7 +2756,7 @@
<h3>3.4.11 – <a name="3.4.11">Function Definitions</a></h3>
<p>
-The syntax for function definition is
+The syntax for a function definition is
<pre>
functiondef ::= <b>function</b> funcbody
@@ -2810,7 +2819,25 @@
translates to
<pre>
- global f; f = function () <em>body</em> end
+ global f; global f = function () <em>body</em> end
+</pre><p>
+The second <b>global</b> makes the assignment an initialization,
+which will raise an error if that global is already defined.
+
+
+<p>
+The <em>colon</em> syntax
+is used to emulate <em>methods</em>,
+adding an implicit extra parameter <code>self</code> to the function.
+Thus, the statement
+
+<pre>
+ function t.a.b.c:f (<em>params</em>) <em>body</em> end
+</pre><p>
+is syntactic sugar for
+
+<pre>
+ t.a.b.c.f = function (self, <em>params</em>) <em>body</em> end
</pre>
<p>
@@ -2826,11 +2853,29 @@
<p>
+Results are returned using the <b>return</b> statement (see <a href="#3.3.4">§3.3.4</a>).
+If control reaches the end of a function
+without encountering a <b>return</b> statement,
+then the function returns with no results.
+
+
+<p>
+
+There is a system-dependent limit on the number of values
+that a function may return.
+This limit is guaranteed to be at least 1000.
+
+
+
+<h4>Parameters</h4>
+
+<p>
Parameters act as local variables that are
initialized with the argument values:
<pre>
- parlist ::= namelist [‘<b>,</b>’ ‘<b>...</b>’] | ‘<b>...</b>’
+ parlist ::= namelist [‘<b>,</b>’ varargparam] | varargparam
+ varargparam ::= ‘<b>...</b>’ [Name]
</pre><p>
When a Lua function is called,
it adjusts its list of arguments to
@@ -2840,9 +2885,13 @@
at the end of its parameter list.
A variadic function does not adjust its argument list;
instead, it collects all extra arguments and supplies them
-to the function through a <em>vararg expression</em>,
-which is also written as three dots.
-The value of this expression is a list of all actual extra arguments,
+to the function through a <em>vararg expression</em> and,
+if present, a <em>vararg table</em>.
+
+
+<p>
+A vararg expression is also written as three dots,
+and its value is a list of all actual extra arguments,
similar to a function with multiple results (see <a href="#3.4.12">§3.4.12</a>).
@@ -2873,33 +2922,31 @@
</pre>
<p>
-Results are returned using the <b>return</b> statement (see <a href="#3.3.4">§3.3.4</a>).
-If control reaches the end of a function
-without encountering a <b>return</b> statement,
-then the function returns with no results.
+The presence of a varag table in a variadic function is indicated
+by a name after the three dots.
+When present,
+a vararg table behaves like a read-only local variable
+with the given name that is initialized with a table.
+In that table,
+the values at indices 1, 2, etc. are the extra arguments,
+and the value at index "<code>n</code>" is the number of extra arguments.
+In other words, the code behaves as if the function started with
+the following statement,
+assuming the standard behavior of <a href="#pdf-table.pack"><code>table.pack</code></a>:
+<pre>
+ local <const> name = table.pack(...)
+</pre>
<p>
+As an optimization,
+if the vararg table is used only as a base in indexing expressions
+(the <code>t</code> in <code>t[exp]</code> or <code>t.id</code>) and it is not an upvalue,
+the code does not create an actual table and instead translates
+the indexing expressions into accesses to the internal vararg data.
-There is a system-dependent limit on the number of values
-that a function may return.
-This limit is guaranteed to be at least 1000.
-
-
-<p>
-The <em>colon</em> syntax
-is used to emulate <em>methods</em>,
-adding an implicit extra parameter <code>self</code> to the function.
-Thus, the statement
-<pre>
- function t.a.b.c:f (<em>params</em>) <em>body</em> end
-</pre><p>
-is syntactic sugar for
-<pre>
- t.a.b.c.f = function (self, <em>params</em>) <em>body</em> end
-</pre>
@@ -2939,8 +2986,8 @@
<li>A multiple assignment,
for instance <code>a , b, c = e1, e2, e3</code> (see <a href="#3.3.3">§3.3.3</a>).</li>
-<li>A local declaration,
-for instance <code>local a , b, c = e1, e2, e3</code> (see <a href="#3.3.7">§3.3.7</a>).</li>
+<li>A local or global declaration,
+which is similar to a multiple assignment.</li>
<li>The initial values in a generic <b>for</b> loop,
for instance <code>for k in e1, e2, e3 do ... end</code> (see <a href="#3.3.5">§3.3.5</a>).</li>
@@ -2951,8 +2998,7 @@
must be <em>adjusted</em> to a specific length:
the number of parameters in a call to a non-variadic function
(see <a href="#3.4.11">§3.4.11</a>),
-the number of variables in a multiple assignment or
-a local declaration,
+the number of variables in a multiple assignment or a declaration,
and exactly four values for a generic <b>for</b> loop.
The <em>adjustment</em> follows these rules:
If there are more values than needed,
@@ -3422,7 +3468,16 @@
For such errors, Lua does not call the message handler.
</li>
-<li><b><a name="pdf-LUA_ERRERR"><code>LUA_ERRERR</code></a></b>: error while running the message handler.</li>
+<li><b><a name="pdf-LUA_ERRERR"><code>LUA_ERRERR</code></a></b>:
+stack overflow while running the message handler
+due to another stack overflow.
+More often than not,
+this error is the result of some other error while running
+a message handler.
+An error in a message handler will call the handler again,
+which will generate the error again, and so on,
+until this loop exhausts the stack and cause this error.
+</li>
<li><b><a name="pdf-LUA_ERRSYNTAX"><code>LUA_ERRSYNTAX</code></a></b>: syntax error during precompilation
or format error in a binary chunk.</li>
@@ -3631,7 +3686,7 @@
size_t nsize);</pre>
<p>
-The type of the memory-allocation function used by Lua states.
+The type of the memory-allocator function used by Lua states.
The allocator function must provide a
functionality similar to <code>realloc</code>,
but not exactly the same.
@@ -3678,12 +3733,13 @@
<p>
-Here is a simple implementation for the allocator function.
-It is used in the auxiliary library by <a href="#luaL_newstate"><code>luaL_newstate</code></a>.
+Here is a simple implementation for the allocator function,
+corresponding to the function <a href="#luaL_alloc"><code>luaL_alloc</code></a> from the
+auxiliary library.
<pre>
- static void *l_alloc (void *ud, void *ptr, size_t osize,
- size_t nsize) {
+ void *luaL_alloc (void *ud, void *ptr, size_t osize,
+ size_t nsize) {
(void)ud; (void)osize; /* not used */
if (nsize == 0) {
free(ptr);
@@ -4213,7 +4269,7 @@
<pre>lua_Alloc lua_getallocf (lua_State *L, void **ud);</pre>
<p>
-Returns the memory-allocation function of a given state.
+Returns the memory-allocator function of a given state.
If <code>ud</code> is not <code>NULL</code>, Lua stores in <code>*ud</code> the
opaque pointer given when the memory-allocator function was set.
@@ -4855,8 +4911,8 @@
<hr><h3><a name="lua_numbertocstring"><code>lua_numbertocstring</code></a></h3><p>
<span class="apii">[-0, +0, –]</span>
-<pre>unsigned (lua_numbertocstring) (lua_State *L, int idx,
- char *buff);</pre>
+<pre>unsigned lua_numbertocstring (lua_State *L, int idx,
+ char *buff);</pre>
<p>
Converts the number at acceptable index <code>idx</code> to a string
@@ -5024,7 +5080,7 @@
<hr><h3><a name="lua_pushexternalstring"><code>lua_pushexternalstring</code></a></h3><p>
<span class="apii">[-0, +1, <em>m</em>]</span>
-<pre>const char *(lua_pushexternalstring) (lua_State *L,
+<pre>const char *lua_pushexternalstring (lua_State *L,
const char *s, size_t len, lua_Alloc falloc, void *ud);</pre>
<p>
@@ -5051,13 +5107,6 @@
<p>
-Lua always internalizes strings with lengths up to 40 characters.
-So, for strings in that range,
-this function will immediately internalize the string
-and call <code>falloc</code> to free the buffer.
-
-
-<p>
Even when using an external buffer,
Lua still has to allocate a header for the string.
In case of a memory-allocation error,
@@ -5068,7 +5117,7 @@
<hr><h3><a name="lua_pushfstring"><code>lua_pushfstring</code></a></h3><p>
-<span class="apii">[-0, +1, <em>m</em>]</span>
+<span class="apii">[-0, +1, <em>v</em>]</span>
<pre>const char *lua_pushfstring (lua_State *L, const char *fmt, ...);</pre>
<p>
@@ -5093,6 +5142,11 @@
must form a valid conversion specifier.
+<p>
+Besides memory allocation errors,
+this function may raise an error if the resulting string is too large.
+
+
@@ -5140,7 +5194,7 @@
<hr><h3><a name="lua_pushliteral"><code>lua_pushliteral</code></a></h3><p>
-<span class="apii">[-0, +1, <em>m</em>]</span>
+<span class="apii">[-0, +1, <em>v</em>]</span>
<pre>const char *lua_pushliteral (lua_State *L, const char *s);</pre>
<p>
@@ -5153,7 +5207,7 @@
<hr><h3><a name="lua_pushlstring"><code>lua_pushlstring</code></a></h3><p>
-<span class="apii">[-0, +1, <em>m</em>]</span>
+<span class="apii">[-0, +1, <em>v</em>]</span>
<pre>const char *lua_pushlstring (lua_State *L, const char *s, size_t len);</pre>
<p>
@@ -5170,6 +5224,11 @@
Returns a pointer to the internal copy of the string (see <a href="#4.1.3">§4.1.3</a>).
+<p>
+Besides memory allocation errors,
+this function may raise an error if the string is too large.
+
+
@@ -6317,8 +6376,8 @@
<li><b><code>namewhat</code></b>:
explains the <code>name</code> field.
The value of <code>namewhat</code> can be
-<code>"global"</code>, <code>"local"</code>, <code>"method"</code>,
-<code>"field"</code>, <code>"upvalue"</code>, or <code>""</code> (the empty string),
+<code>"global"</code>, <code>"local"</code>, <code>"upvalue"</code>,
+<code>"field"</code>, <code>""</code> (the empty string), plus some other options,
according to how the function was called.
(Lua uses the empty string when no other option seems to apply.)
</li>
@@ -7543,9 +7602,8 @@
<p>
Returns a value with a weak attempt for randomness.
-(It produces that value based on the current date and time
-and the address of an internal variable,
-in case the machine has Address Space Layout Randomization.)
+The parameter <code>L</code> can be <code>NULL</code>
+if there is no Lua state available.
@@ -7623,8 +7681,9 @@
<p>
Creates a new Lua state.
-It calls <a href="#lua_newstate"><code>lua_newstate</code></a> with an
-allocator based on the ISO C allocation functions
+It calls <a href="#lua_newstate"><code>lua_newstate</code></a> with <a href="#luaL_alloc"><code>luaL_alloc</code></a> as
+the allocator function and the result of <code>luaL_makeseed(NULL)</code>
+as the seed,
and then sets a warning function and a panic function (see <a href="#4.4">§4.4</a>)
that print messages to the standard error output.
@@ -7924,6 +7983,17 @@
+<hr><h3><a name="luaL_alloc"><code>luaL_alloc</code></a></h3>
+<pre>void *luaL_alloc (void *ud, void *ptr, size_t osize, size_t nsize);</pre>
+
+<p>
+A standard allocator function for Lua (see <a href="#lua_Alloc"><code>lua_Alloc</code></a>),
+built on top of the C functions <code>realloc</code> and <code>free</code>.
+
+
+
+
+
<hr><h3><a name="luaL_Stream"><code>luaL_Stream</code></a></h3>
<pre>typedef struct luaL_Stream {
FILE *f;
@@ -8341,7 +8411,7 @@
<p>
-Lua rounds these values before storing them;
+Lua stores these values in a compressed format,
so, the value returned as the previous value may not be
exactly the last value set.
</li>
@@ -8359,10 +8429,10 @@
<p>
<hr><h3><a name="pdf-dofile"><code>dofile ([filename])</code></a></h3>
-Opens the named file and executes its content as a Lua chunk.
+Opens the named file and executes its content as a Lua chunk,
+returning all values returned by the chunk.
When called without arguments,
<code>dofile</code> executes the content 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.)
@@ -8560,13 +8630,13 @@
<p>
If <code>t</code> has a metamethod <code>__pairs</code>,
-calls it with <code>t</code> as argument and returns the first three
+calls it with <code>t</code> as argument and returns the first four
results from the call.
<p>
Otherwise,
-returns three values: the <a href="#pdf-next"><code>next</code></a> function, the table <code>t</code>, and <b>nil</b>,
+returns the <a href="#pdf-next"><code>next</code></a> function, the table <code>t</code>, plus two <b>nil</b> values,
so that the construction
<pre>
@@ -8862,7 +8932,7 @@
(either the original error that stopped the coroutine or
errors in closing methods),
this function returns <b>false</b> plus the error object;
-otherwise ir returns <b>true</b>.
+otherwise it returns <b>true</b>.
@@ -10630,6 +10700,21 @@
<p>
+<hr><h3><a name="pdf-math.frexp"><code>math.frexp (x)</code></a></h3>
+
+
+<p>
+Returns two numbers <code>m</code> and <code>e</code> such that <em>x = m2<sup>e</sup></em>,
+where <code>e</code> is an integer.
+When <code>x</code> is zero, NaN, +inf, or -inf,
+<code>m</code> is equal to <code>x</code>;
+otherwise, the absolute value of <code>m</code>
+is in the range <em>[0.5, 1)</em> .
+
+
+
+
+<p>
<hr><h3><a name="pdf-math.huge"><code>math.huge</code></a></h3>
@@ -10641,6 +10726,16 @@
<p>
+<hr><h3><a name="pdf-math.ldexp"><code>math.ldexp(m, e)</code></a></h3>
+
+
+<p>
+Returns <em>m2<sup>e</sup></em>, where <code>e</code> is an integer.
+
+
+
+
+<p>
<hr><h3><a name="pdf-math.log"><code>math.log (x [, base])</code></a></h3>
@@ -10726,7 +10821,7 @@
<p>
When called without arguments,
returns a pseudo-random float with uniform distribution
-in the range <em>[0,1)</em>.
+in the range <em>[0, 1)</em>.
When called with two integers <code>m</code> and <code>n</code>,
<code>math.random</code> returns a pseudo-random integer
with uniform distribution in the range <em>[m, n]</em>.
@@ -12360,7 +12455,9 @@
funcbody ::= ‘<b>(</b>’ [parlist] ‘<b>)</b>’ block <b>end</b>
- parlist ::= namelist [‘<b>,</b>’ ‘<b>...</b>’] | ‘<b>...</b>’
+ parlist ::= namelist [‘<b>,</b>’ varargparam] | varargparam
+
+ varargparam ::= ‘<b>...</b>’ [Name]
tableconstructor ::= ‘<b>{</b>’ [fieldlist] ‘<b>}</b>’
@@ -12388,7 +12485,7 @@
<P CLASS="footer">
Last update:
-Sat Jun 28 10:06:59 UTC 2025
+Sat Nov 15 00:41:28 UTC 2025
</P>
<!--
Last change: revised for Lua 5.5.0
doc/readme.html
@@ -86,8 +86,8 @@
You need to build it before using it.
Building Lua should be straightforward
because
-Lua is implemented in pure ANSI C and compiles unmodified in all known
-platforms that have an ANSI C compiler.
+Lua is implemented in pure ISO C and compiles unmodified in all known
+platforms that have an ISO C compiler.
Lua also compiles unmodified as C++.
The instructions given below for building Lua are for Unix-like platforms,
such as Linux and macOS.
@@ -323,7 +323,7 @@
<P CLASS="footer">
Last update:
-Thu Jun 26 13:06:11 UTC 2025
+Tue Sep 2 21:25:09 UTC 2025
</P>
<!--
Last change: revised for Lua 5.5.0
src/Makefile
@@ -127,7 +127,7 @@
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_MACOSX -DLUA_USE_READLINE" SYSLIBS="-lreadline"
mingw:
- $(MAKE) "LUA_A=lua54.dll" "LUA_T=lua.exe" \
+ $(MAKE) "LUA_A=lua55.dll" "LUA_T=lua.exe" \
"AR=$(CC) -shared -o" "RANLIB=strip --strip-unneeded" \
"SYSCFLAGS=-DLUA_BUILD_AS_DLL" "SYSLIBS=" "SYSLDFLAGS=-s" lua.exe
$(MAKE) "LUAC_T=luac.exe" luac.exe
src/lapi.c
@@ -440,7 +440,13 @@
case LUA_VSHRSTR: return cast(lua_Unsigned, tsvalue(o)->shrlen);
case LUA_VLNGSTR: return cast(lua_Unsigned, tsvalue(o)->u.lnglen);
case LUA_VUSERDATA: return cast(lua_Unsigned, uvalue(o)->len);
- case LUA_VTABLE: return luaH_getn(hvalue(o));
+ case LUA_VTABLE: {
+ lua_Unsigned res;
+ lua_lock(L);
+ res = luaH_getn(L, hvalue(o));
+ lua_unlock(L);
+ return res;
+ }
default: return 0;
}
}
@@ -478,7 +484,7 @@
/*
** Returns a pointer to the internal representation of an object.
-** Note that ANSI C does not allow the conversion of a pointer to
+** Note that ISO 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.)
@@ -679,7 +685,7 @@
/*
** The following function assumes that the registry cannot be a weak
-** table, so that en mergency collection while using the global table
+** table; so, an emergency collection while using the global table
** cannot collect it.
*/
static void getGlobalTable (lua_State *L, TValue *gt) {
src/lauxlib.c
@@ -742,7 +742,7 @@
static const char *getF (lua_State *L, void *ud, size_t *size) {
LoadF *lf = (LoadF *)ud;
- (void)L; /* not used */
+ UNUSED(L);
if (lf->n > 0) { /* are there pre-read characters to be read? */
*size = lf->n; /* return them (chars already in buffer) */
lf->n = 0; /* no more pre-read characters */
@@ -856,7 +856,7 @@
static const char *getS (lua_State *L, void *ud, size_t *size) {
LoadS *ls = (LoadS *)ud;
- (void)L; /* not used */
+ UNUSED(L);
if (ls->size == 0) return NULL;
*size = ls->size;
ls->size = 0;
@@ -1046,8 +1046,8 @@
}
-static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
- (void)ud; (void)osize; /* not used */
+void *luaL_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
+ UNUSED(ud); UNUSED(osize);
if (nsize == 0) {
free(ptr);
return NULL;
@@ -1172,13 +1172,17 @@
LUALIB_API unsigned int luaL_makeseed (lua_State *L) {
- (void)L; /* unused */
+ UNUSED(L);
return luai_makeseed();
}
-LUALIB_API lua_State *luaL_newstate (void) {
- lua_State *L = lua_newstate(l_alloc, NULL, luai_makeseed());
+/*
+** Use the name with parentheses so that headers can redefine it
+** as a macro.
+*/
+LUALIB_API lua_State *(luaL_newstate) (void) {
+ lua_State *L = lua_newstate(luaL_alloc, NULL, luaL_makeseed(NULL));
if (l_likely(L)) {
lua_atpanic(L, &panic);
lua_setwarnf(L, warnfoff, L); /* default is warnings off */
src/lauxlib.h
@@ -81,6 +81,9 @@
LUALIB_API int (luaL_fileresult) (lua_State *L, int stat, const char *fname);
LUALIB_API int (luaL_execresult) (lua_State *L, int stat);
+LUALIB_API void *luaL_alloc (void *ud, void *ptr, size_t osize,
+ size_t nsize);
+
/* predefined references */
#define LUA_NOREF (-2)
src/lbaselib.c
@@ -279,21 +279,22 @@
static int pairscont (lua_State *L, int status, lua_KContext k) {
(void)L; (void)status; (void)k; /* unused */
- return 3;
+ return 4; /* __pairs did all the work, just return its results */
}
static int luaB_pairs (lua_State *L) {
luaL_checkany(L, 1);
if (luaL_getmetafield(L, 1, "__pairs") == LUA_TNIL) { /* no metamethod? */
- lua_pushcfunction(L, luaB_next); /* will return generator, */
- lua_pushvalue(L, 1); /* state, */
- lua_pushnil(L); /* and initial value */
+ lua_pushcfunction(L, luaB_next); /* will return generator and */
+ lua_pushvalue(L, 1); /* state */
+ lua_pushnil(L); /* initial value */
+ lua_pushnil(L); /* to-be-closed object */
}
else {
lua_pushvalue(L, 1); /* argument 'self' to metamethod */
- lua_callk(L, 1, 3, 0, pairscont); /* get 3 values from metamethod */
+ lua_callk(L, 1, 4, 0, pairscont); /* get 4 values from metamethod */
}
- return 3;
+ return 4;
}
src/lcode.c
@@ -45,6 +45,7 @@
va_list argp;
pushvfstring(ls->L, argp, fmt, msg);
ls->t.token = 0; /* remove "near <token>" from final message */
+ ls->linenumber = ls->lastline; /* back to line of last used token */
luaX_syntaxerror(ls, msg);
}
@@ -565,20 +566,20 @@
TValue val;
Proto *f = fs->f;
int tag = luaH_get(fs->kcache, key, &val); /* query scanner table */
- int k;
if (!tagisempty(tag)) { /* is there an index there? */
- k = cast_int(ivalue(&val));
+ int k = cast_int(ivalue(&val));
/* collisions can happen only for float keys */
lua_assert(ttisfloat(key) || luaV_rawequalobj(&f->k[k], v));
return k; /* reuse index */
}
- /* constant not found; create a new entry */
- k = addk(fs, f, v);
- /* cache it for reuse; numerical value does not need GC barrier;
- table is not a metatable, so it does not need to invalidate cache */
- setivalue(&val, k);
- luaH_set(fs->ls->L, fs->kcache, key, &val);
- return k;
+ else { /* constant not found; create a new entry */
+ int k = addk(fs, f, v);
+ /* cache it for reuse; numerical value does not need GC barrier;
+ table is not a metatable, so it does not need to invalidate cache */
+ setivalue(&val, k);
+ luaH_set(fs->ls->L, fs->kcache, key, &val);
+ return k;
+ }
}
@@ -604,13 +605,14 @@
/*
** Add a float to list of constants and return its index. Floats
** with integral values need a different key, to avoid collision
-** with actual integers. To that, we add to the number its smaller
+** with actual integers. To that end, we add to the number its smaller
** power-of-two fraction that is still significant in its scale.
-** For doubles, that would be 1/2^52.
+** (For doubles, the fraction would be 2^-52).
** This method is not bulletproof: different numbers may generate the
** same key (e.g., very large numbers will overflow to 'inf') and for
-** floats larger than 2^53 the result is still an integer. At worst,
-** this only wastes an entry with a duplicate.
+** floats larger than 2^53 the result is still an integer. For those
+** cases, just generate a new entry. At worst, this only wastes an entry
+** with a duplicate.
*/
static int luaK_numberK (FuncState *fs, lua_Number r) {
TValue o, kv;
@@ -625,7 +627,7 @@
const lua_Number k = r * (1 + q); /* key */
lua_Integer ik;
setfltvalue(&kv, k); /* key as a TValue */
- if (!luaV_flttointeger(k, &ik, F2Ieq)) { /* not an integral value? */
+ if (!luaV_flttointeger(k, &ik, F2Ieq)) { /* not an integer value? */
int n = k2proto(fs, &kv, &o); /* use key */
if (luaV_rawequalobj(&fs->f->k[n], &o)) /* correct value? */
return n;
@@ -705,6 +707,22 @@
/*
+** Get the value of 'var' in a register and generate an opcode to check
+** whether that register is nil. 'k' is the index of the variable name
+** in the list of constants. If its value cannot be encoded in Bx, a 0
+** will use '?' for the name.
+*/
+void luaK_codecheckglobal (FuncState *fs, expdesc *var, int k, int line) {
+ luaK_exp2anyreg(fs, var);
+ luaK_fixline(fs, line);
+ k = (k >= MAXARG_Bx) ? 0 : k + 1;
+ luaK_codeABx(fs, OP_ERRNNIL, var->u.info, k);
+ luaK_fixline(fs, line);
+ freeexp(fs, var);
+}
+
+
+/*
** Convert a constant in 'v' into an expression description 'e'
*/
static void const2exp (TValue *v, expdesc *e) {
@@ -784,6 +802,15 @@
}
}
+/*
+** Change a vararg parameter into a regular local variable
+*/
+void luaK_vapar2local (FuncState *fs, expdesc *var) {
+ fs->f->flag |= PF_VATAB; /* function will need a vararg table */
+ /* now a vararg parameter is equivalent to a regular local variable */
+ var->k = VLOCAL;
+}
+
/*
** Ensure that expression 'e' is not a variable (nor a <const>).
@@ -795,6 +822,9 @@
const2exp(const2val(fs, e), e);
break;
}
+ case VVARGVAR: {
+ luaK_vapar2local(fs, e); /* turn it into a local variable */
+ } /* FALLTHROUGH */
case VLOCAL: { /* already in a register */
int temp = e->u.var.ridx;
e->u.info = temp; /* (can't do a direct assignment; values overlap) */
@@ -829,6 +859,12 @@
e->k = VRELOC;
break;
}
+ case VVARGIND: {
+ freeregs(fs, e->u.ind.t, e->u.ind.idx);
+ e->u.info = luaK_codeABC(fs, OP_GETVARG, 0, e->u.ind.t, e->u.ind.idx);
+ e->k = VRELOC;
+ break;
+ }
case VVARARG: case VCALL: {
luaK_setoneret(fs, e);
break;
@@ -991,11 +1027,11 @@
/*
-** Ensures final expression result is either in a register
-** or in an upvalue.
+** Ensures final expression result is either in a register,
+** in an upvalue, or it is the vararg parameter.
*/
void luaK_exp2anyregup (FuncState *fs, expdesc *e) {
- if (e->k != VUPVAL || hasjumps(e))
+ if ((e->k != VUPVAL && e->k != VVARGVAR) || hasjumps(e))
luaK_exp2anyreg(fs, e);
}
@@ -1090,6 +1126,10 @@
codeABRK(fs, OP_SETFIELD, var->u.ind.t, var->u.ind.idx, ex);
break;
}
+ case VVARGIND: {
+ fs->f->flag |= PF_VATAB; /* function will need a vararg table */
+ /* now, assignment is to a regular table */
+ } /* FALLTHROUGH */
case VINDEXED: {
codeABRK(fs, OP_SETTABLE, var->u.ind.t, var->u.ind.idx, ex);
break;
@@ -1162,7 +1202,7 @@
/*
** Emit code to go through if 'e' is false, jump otherwise.
*/
-void luaK_goiffalse (FuncState *fs, expdesc *e) {
+static void luaK_goiffalse (FuncState *fs, expdesc *e) {
int pc; /* pc of new jump */
luaK_dischargevars(fs, e);
switch (e->k) {
@@ -1223,7 +1263,7 @@
** Check whether expression 'e' is a short literal string
*/
static int isKstr (FuncState *fs, expdesc *e) {
- return (e->k == VK && !hasjumps(e) && e->u.info <= MAXARG_B &&
+ return (e->k == VK && !hasjumps(e) && e->u.info <= MAXINDEXRK &&
ttisshrstring(&fs->f->k[e->u.info]));
}
@@ -1301,6 +1341,13 @@
}
+/* auxiliary function to define indexing expressions */
+static void fillidxk (expdesc *t, int idx, expkind k) {
+ t->u.ind.idx = cast_byte(idx);
+ t->k = k;
+}
+
+
/*
** Create expression 't[k]'. 't' must have its final result already in a
** register or upvalue. Upvalues can only be indexed by literal strings.
@@ -1312,31 +1359,30 @@
if (k->k == VKSTR)
keystr = str2K(fs, k);
lua_assert(!hasjumps(t) &&
- (t->k == VLOCAL || t->k == VNONRELOC || t->k == VUPVAL));
+ (t->k == VLOCAL || t->k == VVARGVAR ||
+ t->k == VNONRELOC || t->k == VUPVAL));
if (t->k == VUPVAL && !isKstr(fs, k)) /* upvalue indexed by non 'Kstr'? */
luaK_exp2anyreg(fs, t); /* put it in a register */
if (t->k == VUPVAL) {
lu_byte temp = cast_byte(t->u.info); /* upvalue index */
t->u.ind.t = temp; /* (can't do a direct assignment; values overlap) */
lua_assert(isKstr(fs, k));
- t->u.ind.idx = cast_short(k->u.info); /* literal short string */
- t->k = VINDEXUP;
+ fillidxk(t, k->u.info, VINDEXUP); /* literal short string */
+ }
+ else if (t->k == VVARGVAR) { /* indexing the vararg parameter? */
+ lua_assert(t->u.ind.t == fs->f->numparams);
+ t->u.ind.t = cast_byte(t->u.var.ridx);
+ fillidxk(t, luaK_exp2anyreg(fs, k), VVARGIND); /* register */
}
else {
/* register index of the table */
t->u.ind.t = cast_byte((t->k == VLOCAL) ? t->u.var.ridx: t->u.info);
- if (isKstr(fs, k)) {
- t->u.ind.idx = cast_short(k->u.info); /* literal short string */
- t->k = VINDEXSTR;
- }
- else if (isCint(k)) { /* int. constant in proper range? */
- t->u.ind.idx = cast_short(k->u.ival);
- t->k = VINDEXI;
- }
- else {
- t->u.ind.idx = cast_short(luaK_exp2anyreg(fs, k)); /* register */
- t->k = VINDEXED;
- }
+ if (isKstr(fs, k))
+ fillidxk(t, k->u.info, VINDEXSTR); /* literal short string */
+ else if (isCint(k)) /* int. constant in proper range? */
+ fillidxk(t, cast_int(k->u.ival), VINDEXI);
+ else
+ fillidxk(t, luaK_exp2anyreg(fs, k), VINDEXED); /* register */
}
t->u.ind.keystr = keystr; /* string index in 'k' */
t->u.ind.ro = 0; /* by default, not read-only */
@@ -1900,9 +1946,14 @@
SETARG_C(*pc, p->numparams + 1); /* signal that it is vararg */
break;
}
- case OP_JMP: {
+ case OP_GETVARG: {
+ if (p->flag & PF_VATAB) /* function has a vararg table? */
+ SET_OPCODE(*pc, OP_GETTABLE); /* must get vararg there */
+ break;
+ }
+ case OP_JMP: { /* to optimize jumps to jumps */
int target = finaltarget(p->code, i);
- fixjump(fs, i, target);
+ fixjump(fs, i, target); /* jump directly to final target */
break;
}
default: break;
src/lcode.h
@@ -68,9 +68,12 @@
LUAI_FUNC int luaK_exp2const (FuncState *fs, const expdesc *e, TValue *v);
LUAI_FUNC void luaK_fixline (FuncState *fs, int line);
LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n);
+LUAI_FUNC void luaK_codecheckglobal (FuncState *fs, expdesc *var, int k,
+ int line);
LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n);
LUAI_FUNC void luaK_checkstack (FuncState *fs, int n);
LUAI_FUNC void luaK_int (FuncState *fs, int reg, lua_Integer n);
+LUAI_FUNC void luaK_vapar2local (FuncState *fs, expdesc *var);
LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e);
LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e);
LUAI_FUNC void luaK_exp2anyregup (FuncState *fs, expdesc *e);
@@ -79,7 +82,6 @@
LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key);
LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k);
LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e);
-LUAI_FUNC void luaK_goiffalse (FuncState *fs, expdesc *e);
LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e);
LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults);
LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e);
src/lctype.c
@@ -18,7 +18,7 @@
#if defined (LUA_UCID) /* accept UniCode IDentifiers? */
-/* consider all non-ascii codepoints to be alphabetic */
+/* consider all non-ASCII codepoints to be alphabetic */
#define NONA 0x01
#else
#define NONA 0x00 /* default */
src/ldebug.c
@@ -814,6 +814,14 @@
}
+l_noret luaG_errnnil (lua_State *L, LClosure *cl, int k) {
+ const char *globalname = "?"; /* default name if k == 0 */
+ if (k > 0)
+ kname(cl->p, k - 1, &globalname);
+ luaG_runerror(L, "global '%s' already defined", globalname);
+}
+
+
/* add src:line information to 'msg' */
const char *luaG_addinfo (lua_State *L, const char *msg, TString *src,
int line) {
src/ldebug.h
@@ -53,6 +53,7 @@
const TValue *p2);
LUAI_FUNC l_noret luaG_ordererror (lua_State *L, const TValue *p1,
const TValue *p2);
+LUAI_FUNC l_noret luaG_errnnil (lua_State *L, LClosure *cl, int k);
LUAI_FUNC l_noret luaG_runerror (lua_State *L, const char *fmt, ...);
LUAI_FUNC const char *luaG_addinfo (lua_State *L, const char *msg,
TString *src, int line);
src/ldo.c
@@ -57,10 +57,18 @@
** =======================================================
*/
+/* chained list of long jump buffers */
+typedef struct lua_longjmp {
+ struct lua_longjmp *previous;
+ jmp_buf b;
+ volatile TStatus status; /* error code */
+} lua_longjmp;
+
+
/*
** LUAI_THROW/LUAI_TRY define how Lua does exception handling. By
** default, Lua handles errors with exceptions when compiling as
-** C++ code, with _longjmp/_setjmp when asked to use them, and with
+** C++ code, with _longjmp/_setjmp when available (POSIX), and with
** longjmp/setjmp otherwise.
*/
#if !defined(LUAI_THROW) /* { */
@@ -69,38 +77,38 @@
/* C++ exceptions */
#define LUAI_THROW(L,c) throw(c)
-#define LUAI_TRY(L,c,f,ud) \
- try { (f)(L, ud); } catch(...) { if ((c)->status == 0) (c)->status = -1; }
-#define luai_jmpbuf int /* dummy field */
+
+static void LUAI_TRY (lua_State *L, lua_longjmp *c, Pfunc f, void *ud) {
+ try {
+ f(L, ud); /* call function protected */
+ }
+ catch (lua_longjmp *c1) { /* Lua error */
+ if (c1 != c) /* not the correct level? */
+ throw; /* rethrow to upper level */
+ }
+ catch (...) { /* non-Lua exception */
+ c->status = -1; /* create some error code */
+ }
+}
+
#elif defined(LUA_USE_POSIX) /* }{ */
-/* in POSIX, try _longjmp/_setjmp (more efficient) */
+/* in POSIX, use _longjmp/_setjmp (more efficient) */
#define LUAI_THROW(L,c) _longjmp((c)->b, 1)
#define LUAI_TRY(L,c,f,ud) if (_setjmp((c)->b) == 0) ((f)(L, ud))
-#define luai_jmpbuf jmp_buf
#else /* }{ */
/* ISO C handling with long jumps */
#define LUAI_THROW(L,c) longjmp((c)->b, 1)
#define LUAI_TRY(L,c,f,ud) if (setjmp((c)->b) == 0) ((f)(L, ud))
-#define luai_jmpbuf jmp_buf
#endif /* } */
#endif /* } */
-
-/* chain list of long jump buffers */
-struct lua_longjmp {
- struct lua_longjmp *previous;
- luai_jmpbuf b;
- volatile TStatus status; /* error code */
-};
-
-
void luaD_seterrorobj (lua_State *L, TStatus errcode, StkId oldtop) {
if (errcode == LUA_ERRMEM) { /* memory error? */
setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */
@@ -151,7 +159,7 @@
TStatus luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
l_uint32 oldnCcalls = L->nCcalls;
- struct lua_longjmp lj;
+ lua_longjmp lj;
lj.status = LUA_OK;
lj.previous = L->errorJmp; /* chain new error handler */
L->errorJmp = &lj;
@@ -174,6 +182,20 @@
#define STACKERRSPACE 200
+/*
+** LUAI_MAXSTACK limits the size of the Lua stack.
+** It must fit into INT_MAX/2.
+*/
+
+#if !defined(LUAI_MAXSTACK)
+#if 1000000 < (INT_MAX / 2)
+#define LUAI_MAXSTACK 1000000
+#else
+#define LUAI_MAXSTACK (INT_MAX / 2u)
+#endif
+#endif
+
+
/* maximum stack size that respects size_t */
#define MAXSTACK_BYSIZET ((MAX_SIZET / sizeof(StackValue)) - STACKERRSPACE)
@@ -189,7 +211,7 @@
#define ERRORSTACKSIZE (MAXSTACK + STACKERRSPACE)
-/* raise an error while running the message handler */
+/* raise a stack error while running the message handler */
l_noret luaD_errerr (lua_State *L) {
TString *msg = luaS_newliteral(L, "error in error handling");
setsvalue2s(L, L->top.p, msg);
@@ -325,7 +347,7 @@
a stack error; cannot grow further than that. */
lua_assert(stacksize(L) == ERRORSTACKSIZE);
if (raiseerror)
- luaD_errerr(L); /* error inside message handler */
+ luaD_errerr(L); /* stack error inside message handler */
return 0; /* if not 'raiseerror', just signal it */
}
else if (n < MAXSTACK) { /* avoids arithmetic overflows */
src/ldump.c
@@ -132,27 +132,31 @@
/*
-** Dump a String. First dump its "size": size==0 means NULL;
-** size==1 is followed by an index and means "reuse saved string with
-** that index"; size>=2 is followed by the string contents with real
-** size==size-2 and means that string, which will be saved with
-** the next available index.
+** Dump a String. First dump its "size":
+** size==0 is followed by an index and means "reuse saved string with
+** that index"; index==0 means NULL.
+** size>=1 is followed by the string contents with real size==size-1 and
+** means that string, which will be saved with the next available index.
+** The real size does not include the ending '\0' (which is not dumped),
+** so adding 1 to it cannot overflow a size_t.
*/
static void dumpString (DumpState *D, TString *ts) {
- if (ts == NULL)
- dumpSize(D, 0);
+ if (ts == NULL) {
+ dumpVarint(D, 0); /* will "reuse" NULL */
+ dumpVarint(D, 0); /* special index for NULL */
+ }
else {
TValue idx;
int tag = luaH_getstr(D->h, ts, &idx);
if (!tagisempty(tag)) { /* string already saved? */
- dumpVarint(D, 1); /* reuse a saved string */
+ dumpVarint(D, 0); /* reuse a saved string */
dumpVarint(D, l_castS2U(ivalue(&idx))); /* index of saved string */
}
else { /* must write and save the string */
TValue key, value; /* to save the string in the hash */
size_t size;
const char *s = getlstr(ts, size);
- dumpSize(D, size + 2);
+ dumpSize(D, size + 1);
dumpVector(D, s, size + 1); /* include ending '\0' */
D->nstr++; /* one more saved string */
setsvalue(D->L, &key, ts); /* the string is the key */
src/lfunc.c
@@ -196,8 +196,7 @@
*/
void luaF_closeupval (lua_State *L, StkId level) {
UpVal *uv;
- StkId upl; /* stack index pointed by 'uv' */
- while ((uv = L->openupval) != NULL && (upl = uplevel(uv)) >= level) {
+ while ((uv = L->openupval) != NULL && uplevel(uv) >= level) {
TValue *slot = &uv->u.value; /* new position for value */
lua_assert(uplevel(uv) < L->top.p);
luaF_unlinkupval(uv); /* remove upvalue from 'openupval' list */
src/lgc.c
@@ -594,10 +594,10 @@
*/
static int getmode (global_State *g, Table *h) {
const TValue *mode = gfasttm(g, h->metatable, TM_MODE);
- if (mode == NULL || !ttisshrstring(mode))
- return 0; /* ignore non-(short)string modes */
+ if (mode == NULL || !ttisstring(mode))
+ return 0; /* ignore non-string modes */
else {
- const char *smode = getshrstr(tsvalue(mode));
+ const char *smode = getstr(tsvalue(mode));
const char *weakkey = strchr(smode, 'k');
const char *weakvalue = strchr(smode, 'v');
return ((weakkey != NULL) << 1) | (weakvalue != NULL);
@@ -624,7 +624,7 @@
linkgclist(h, g->allweak); /* must clear collected entries */
break;
}
- return 1 + 2*sizenode(h) + h->asize;
+ return cast(l_mem, 1 + 2*sizenode(h) + h->asize);
}
src/liolib.c
@@ -114,7 +114,7 @@
#if !defined(l_fseek) /* { */
-#if defined(LUA_USE_POSIX) /* { */
+#if defined(LUA_USE_POSIX) || defined(LUA_USE_OFF_T) /* { */
#include <sys/types.h>
src/ljumptab.h
@@ -21,7 +21,7 @@
#if 0
** you can update the following list with this command:
**
-** sed -n '/^OP_/\!d; s/OP_/\&\&L_OP_/ ; s/,.*/,/ ; s/\/.*// ; p' lopcodes.h
+** sed -n '/^OP_/!d; s/OP_/\&\&L_OP_/ ; s/,.*/,/ ; s/\/.*// ; p' lopcodes.h
**
#endif
@@ -57,8 +57,8 @@
&&L_OP_BANDK,
&&L_OP_BORK,
&&L_OP_BXORK,
-&&L_OP_SHRI,
&&L_OP_SHLI,
+&&L_OP_SHRI,
&&L_OP_ADD,
&&L_OP_SUB,
&&L_OP_MUL,
@@ -106,6 +106,8 @@
&&L_OP_SETLIST,
&&L_OP_CLOSURE,
&&L_OP_VARARG,
+&&L_OP_GETVARG,
+&&L_OP_ERRNNIL,
&&L_OP_VARARGPREP,
&&L_OP_EXTRAARG
src/llimits.h
@@ -20,8 +20,8 @@
/*
** 'l_mem' is a signed integer big enough to count the total memory
** used by Lua. (It is signed due to the use of debt in several
-** computations.) Usually, 'ptrdiff_t' should work, but we use 'long'
-** for 16-bit machines.
+** computations.) 'lu_mem' is a corresponding unsigned type. Usually,
+** 'ptrdiff_t' should work, but we use 'long' for 16-bit machines.
*/
#if defined(LUAI_MEM) /* { external definitions? */
typedef LUAI_MEM l_mem;
@@ -60,13 +60,6 @@
: cast_sizet(LUA_MAXINTEGER))
/*
-** floor of the log2 of the maximum signed value for integral type 't'.
-** (That is, maximum 'n' such that '2^n' fits in the given signed type.)
-*/
-#define log2maxs(t) (l_numbits(t) - 2)
-
-
-/*
** test whether an unsigned value is a power of 2 (or zero)
*/
#define ispow2(x) (((x) & ((x) - 1)) == 0)
@@ -287,6 +280,55 @@
#endif
+
+/*
+** lua_numbertointeger converts a float number with an integral value
+** to an integer, or returns 0 if the float is not within the range of
+** a lua_Integer. (The range comparisons are tricky because of
+** rounding. The tests here assume a two-complement representation,
+** where MININTEGER always has an exact representation as a float;
+** MAXINTEGER may not have one, and therefore its conversion to float
+** may have an ill-defined value.)
+*/
+#define lua_numbertointeger(n,p) \
+ ((n) >= (LUA_NUMBER)(LUA_MININTEGER) && \
+ (n) < -(LUA_NUMBER)(LUA_MININTEGER) && \
+ (*(p) = (LUA_INTEGER)(n), 1))
+
+
+
+/*
+** LUAI_FUNC is a mark for all extern functions that are not to be
+** exported to outside modules.
+** LUAI_DDEF and LUAI_DDEC are marks for all extern (const) variables,
+** none of which to be exported to outside modules (LUAI_DDEF for
+** definitions and LUAI_DDEC for declarations).
+** Elf and MACH/gcc (versions 3.2 and later) mark them as "hidden" to
+** optimize access when Lua is compiled as a shared library. Not all elf
+** targets support this attribute. Unfortunately, gcc does not offer
+** a way to check whether the target offers that support, and those
+** without support give a warning about it. To avoid these warnings,
+** change to the default definition.
+*/
+#if !defined(LUAI_FUNC)
+
+#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \
+ (defined(__ELF__) || defined(__MACH__))
+#define LUAI_FUNC __attribute__((visibility("internal"))) extern
+#else
+#define LUAI_FUNC extern
+#endif
+
+#define LUAI_DDEC(dec) LUAI_FUNC dec
+#define LUAI_DDEF /* empty */
+
+#endif
+
+
+/* Give these macros simpler names for internal use */
+#define l_likely(x) luai_likely(x)
+#define l_unlikely(x) luai_unlikely(x)
+
/*
** {==================================================================
** "Abstraction Layer" for basic report of messages and errors
src/lmathlib.c
@@ -38,31 +38,37 @@
return 1;
}
+
static int math_sin (lua_State *L) {
lua_pushnumber(L, l_mathop(sin)(luaL_checknumber(L, 1)));
return 1;
}
+
static int math_cos (lua_State *L) {
lua_pushnumber(L, l_mathop(cos)(luaL_checknumber(L, 1)));
return 1;
}
+
static int math_tan (lua_State *L) {
lua_pushnumber(L, l_mathop(tan)(luaL_checknumber(L, 1)));
return 1;
}
+
static int math_asin (lua_State *L) {
lua_pushnumber(L, l_mathop(asin)(luaL_checknumber(L, 1)));
return 1;
}
+
static int math_acos (lua_State *L) {
lua_pushnumber(L, l_mathop(acos)(luaL_checknumber(L, 1)));
return 1;
}
+
static int math_atan (lua_State *L) {
lua_Number y = luaL_checknumber(L, 1);
lua_Number x = luaL_optnumber(L, 2, 1);
@@ -167,6 +173,7 @@
return 1;
}
+
static int math_log (lua_State *L) {
lua_Number x = luaL_checknumber(L, 1);
lua_Number res;
@@ -188,22 +195,42 @@
return 1;
}
+
static int math_exp (lua_State *L) {
lua_pushnumber(L, l_mathop(exp)(luaL_checknumber(L, 1)));
return 1;
}
+
static int math_deg (lua_State *L) {
lua_pushnumber(L, luaL_checknumber(L, 1) * (l_mathop(180.0) / PI));
return 1;
}
+
static int math_rad (lua_State *L) {
lua_pushnumber(L, luaL_checknumber(L, 1) * (PI / l_mathop(180.0)));
return 1;
}
+static int math_frexp (lua_State *L) {
+ lua_Number x = luaL_checknumber(L, 1);
+ int ep;
+ lua_pushnumber(L, l_mathop(frexp)(x, &ep));
+ lua_pushinteger(L, ep);
+ return 2;
+}
+
+
+static int math_ldexp (lua_State *L) {
+ lua_Number x = luaL_checknumber(L, 1);
+ int ep = (int)luaL_checkinteger(L, 2);
+ lua_pushnumber(L, l_mathop(ldexp)(x, ep));
+ return 1;
+}
+
+
static int math_min (lua_State *L) {
int n = lua_gettop(L); /* number of arguments */
int imin = 1; /* index of current minimum value */
@@ -251,7 +278,7 @@
*/
/*
-** This code uses lots of shifts. ANSI C does not allow shifts greater
+** This code uses lots of shifts. ISO C does not allow shifts greater
** than or equal to the width of the type being shifted, so some shifts
** are written in convoluted ways to match that restriction. For
** preprocessor tests, it assumes a width of 32 bits, so the maximum
@@ -666,20 +693,6 @@
return 1;
}
-static int math_frexp (lua_State *L) {
- int e;
- lua_pushnumber(L, l_mathop(frexp)(luaL_checknumber(L, 1), &e));
- lua_pushinteger(L, e);
- return 2;
-}
-
-static int math_ldexp (lua_State *L) {
- lua_Number x = luaL_checknumber(L, 1);
- int ep = (int)luaL_checkinteger(L, 2);
- lua_pushnumber(L, l_mathop(ldexp)(x, ep));
- return 1;
-}
-
static int math_log10 (lua_State *L) {
lua_pushnumber(L, l_mathop(log10)(luaL_checknumber(L, 1)));
return 1;
@@ -702,7 +715,9 @@
{"tointeger", math_toint},
{"floor", math_floor},
{"fmod", math_fmod},
+ {"frexp", math_frexp},
{"ult", math_ult},
+ {"ldexp", math_ldexp},
{"log", math_log},
{"max", math_max},
{"min", math_min},
@@ -718,8 +733,6 @@
{"sinh", math_sinh},
{"tanh", math_tanh},
{"pow", math_pow},
- {"frexp", math_frexp},
- {"ldexp", math_ldexp},
{"log10", math_log10},
#endif
/* placeholders */
src/loadlib.c
@@ -307,6 +307,16 @@
/*
+** External strings created by DLLs may need the DLL code to be
+** deallocated. This implies that a DLL can only be unloaded after all
+** its strings were deallocated. To ensure that, we create a 'library
+** string' to represent each DLL, and when this string is deallocated
+** it closes its corresponding DLL.
+** (The string itself is irrelevant; its userdata is the DLL pointer.)
+*/
+
+
+/*
** return registry.CLIBS[path]
*/
static void *checkclib (lua_State *L, const char *path) {
@@ -320,34 +330,41 @@
/*
-** registry.CLIBS[path] = plib -- for queries
-** registry.CLIBS[#CLIBS + 1] = plib -- also keep a list of all libraries
+** Deallocate function for library strings.
+** Unload the DLL associated with the string being deallocated.
*/
-static void addtoclib (lua_State *L, const char *path, void *plib) {
- lua_getfield(L, LUA_REGISTRYINDEX, CLIBS);
- lua_pushlightuserdata(L, plib);
- lua_pushvalue(L, -1);
- lua_setfield(L, -3, path); /* CLIBS[path] = plib */
- lua_rawseti(L, -2, luaL_len(L, -2) + 1); /* CLIBS[#CLIBS + 1] = plib */
- lua_pop(L, 1); /* pop CLIBS table */
+static void *freelib (void *ud, void *ptr, size_t osize, size_t nsize) {
+ /* string itself is irrelevant and static */
+ (void)ptr; (void)osize; (void)nsize;
+ lsys_unloadlib(ud); /* unload library represented by the string */
+ return NULL;
}
/*
-** __gc tag method for CLIBS table: calls 'lsys_unloadlib' for all lib
-** handles in list CLIBS
+** Create a library string that, when deallocated, will unload 'plib'
*/
-static int gctm (lua_State *L) {
- lua_Integer n = luaL_len(L, 1);
- for (; n >= 1; n--) { /* for each handle, in reverse order */
- lua_rawgeti(L, 1, n); /* get handle CLIBS[n] */
- lsys_unloadlib(lua_touserdata(L, -1));
- lua_pop(L, 1); /* pop handle */
- }
- return 0;
+static void createlibstr (lua_State *L, void *plib) {
+ /* common content for all library strings */
+ static const char dummy[] = "01234567890";
+ lua_pushexternalstring(L, dummy, sizeof(dummy) - 1, freelib, plib);
}
+/*
+** registry.CLIBS[path] = plib -- for queries.
+** Also create a reference to strlib, so that the library string will
+** only be collected when registry.CLIBS is collected.
+*/
+static void addtoclib (lua_State *L, const char *path, void *plib) {
+ lua_getfield(L, LUA_REGISTRYINDEX, CLIBS);
+ lua_pushlightuserdata(L, plib);
+ lua_setfield(L, -2, path); /* CLIBS[path] = plib */
+ createlibstr(L, plib);
+ luaL_ref(L, -2); /* keep library string in CLIBS */
+ lua_pop(L, 1); /* pop CLIBS table */
+}
+
/* error codes for 'lookforfunc' */
#define ERRLIB 1
@@ -361,8 +378,8 @@
** Then, if 'sym' is '*', return true (as library has been loaded).
** Otherwise, look for symbol 'sym' in the library and push a
** C function with that symbol.
-** Return 0 and 'true' or a function in the stack; in case of
-** errors, return an error code and an error message in the stack.
+** Return 0 with 'true' or a function in the stack; in case of
+** errors, return an error code with an error message in the stack.
*/
static int lookforfunc (lua_State *L, const char *path, const char *sym) {
void *reg = checkclib(L, path); /* check loaded C libraries */
@@ -704,21 +721,9 @@
}
-/*
-** create table CLIBS to keep track of loaded C libraries,
-** setting a finalizer to close all libraries when closing state.
-*/
-static void createclibstable (lua_State *L) {
- luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS); /* create CLIBS table */
- lua_createtable(L, 0, 1); /* create metatable for CLIBS */
- lua_pushcfunction(L, gctm);
- lua_setfield(L, -2, "__gc"); /* set finalizer for CLIBS table */
- lua_setmetatable(L, -2);
-}
-
-
LUAMOD_API int luaopen_package (lua_State *L) {
- createclibstable(L);
+ luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS); /* create CLIBS table */
+ lua_pop(L, 1); /* will not use it now */
luaL_newlib(L, pk_funcs); /* create 'package' table */
createsearcherstable(L);
/* set paths */
src/lobject.c
@@ -31,7 +31,8 @@
/*
-** Computes ceil(log2(x))
+** Computes ceil(log2(x)), which is the smallest integer n such that
+** x <= (1 << n).
*/
lu_byte luaO_ceillog2 (unsigned int x) {
static const lu_byte log_2[256] = { /* log_2[i - 1] = ceil(log2(i)) */
@@ -86,7 +87,7 @@
** overflow, so we check which order is best.
*/
l_mem luaO_applyparam (lu_byte p, l_mem x) {
- unsigned int m = p & 0xF; /* mantissa */
+ int m = p & 0xF; /* mantissa */
int e = (p >> 4); /* exponent */
if (e > 0) { /* normalized? */
e--; /* correct exponent */
@@ -385,7 +386,7 @@
int luaO_utf8esc (char *buff, l_uint32 x) {
int n = 1; /* number of bytes put in buffer (backwards) */
lua_assert(x <= 0x7FFFFFFFu);
- if (x < 0x80) /* ascii? */
+ if (x < 0x80) /* ASCII? */
buff[UTF8BUFFSZ - 1] = cast_char(x);
else { /* need continuation bytes */
unsigned int mfb = 0x3f; /* maximum that fits in first byte */
src/lobject.h
@@ -418,6 +418,7 @@
#define strisshr(ts) ((ts)->shrlen >= 0)
+#define isextstr(ts) (ttislngstring(ts) && tsvalue(ts)->shrlen != LSTRREG)
/*
@@ -582,8 +583,10 @@
/*
** Flags in Prototypes
*/
-#define PF_ISVARARG 1
-#define PF_FIXED 2 /* prototype has parts in fixed memory */
+#define PF_ISVARARG 1 /* function is vararg */
+#define PF_VAVAR 2 /* function has vararg parameter */
+#define PF_VATAB 4 /* function has vararg table */
+#define PF_FIXED 8 /* prototype has parts in fixed memory */
/*
src/lopcodes.c
@@ -53,8 +53,8 @@
,opmode(0, 0, 0, 0, 1, iABC) /* OP_BANDK */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_BORK */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_BXORK */
- ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SHRI */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_SHLI */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SHRI */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_ADD */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_SUB */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_MUL */
@@ -102,6 +102,8 @@
,opmode(0, 0, 1, 0, 0, ivABC) /* OP_SETLIST */
,opmode(0, 0, 0, 0, 1, iABx) /* OP_CLOSURE */
,opmode(0, 1, 0, 0, 1, iABC) /* OP_VARARG */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_GETVARG */
+ ,opmode(0, 0, 0, 0, 0, iABx) /* OP_ERRNNIL */
,opmode(0, 0, 1, 0, 1, iABC) /* OP_VARARGPREP */
,opmode(0, 0, 0, 0, 0, iAx) /* OP_EXTRAARG */
};
src/lopcodes.h
@@ -272,8 +272,8 @@
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 sC R[A] := R[B] >> sC */
OP_SHLI,/* A B sC R[A] := sC << R[B] */
+OP_SHRI,/* A B sC R[A] := R[B] >> sC */
OP_ADD,/* A B C R[A] := R[B] + R[C] */
OP_SUB,/* A B C R[A] := R[B] - R[C] */
@@ -338,7 +338,11 @@
OP_VARARG,/* A C R[A], R[A+1], ..., R[A+C-2] = vararg */
-OP_VARARGPREP,/*A (adjust vararg parameters) */
+OP_GETVARG, /* A B C R[A] := R[B][R[C]], R[B] is vararg parameter */
+
+OP_ERRNNIL,/* A Bx raise error if R[A] ~= nil (K[Bx] is global name)*/
+
+OP_VARARGPREP,/* (adjust vararg parameters) */
OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */
} OpCode;
src/lopnames.h
@@ -45,8 +45,8 @@
"BANDK",
"BORK",
"BXORK",
- "SHRI",
"SHLI",
+ "SHRI",
"ADD",
"SUB",
"MUL",
@@ -94,6 +94,8 @@
"SETLIST",
"CLOSURE",
"VARARG",
+ "GETVARG",
+ "ERRNNIL",
"VARARGPREP",
"EXTRAARG",
NULL
src/loslib.c
@@ -34,7 +34,7 @@
#if defined(LUA_USE_WINDOWS)
#define LUA_STRFTIMEOPTIONS "aAbBcdHIjmMpSUwWxXyYzZ%" \
"||" "#c#x#d#H#I#j#m#M#S#U#w#W#y#Y" /* two-char options */
-#elif defined(LUA_USE_C89) /* ANSI C 89 (only 1-char options) */
+#elif defined(LUA_USE_C89) /* C89 (only 1-char options) */
#define LUA_STRFTIMEOPTIONS "aAbBcdHIjmMpSUwWxXyYZ%"
#else /* C99 specification */
#define LUA_STRFTIMEOPTIONS "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%" \
src/lparser.c
@@ -30,7 +30,7 @@
-/* maximum number of variable declarationss per function (must be
+/* maximum number of variable declarations per function (must be
smaller than 250, due to the bytecode format) */
#define MAXVARS 200
@@ -197,7 +197,7 @@
Dyndata *dyd = ls->dyd;
Vardesc *var;
luaM_growvector(L, dyd->actvar.arr, dyd->actvar.n + 1,
- dyd->actvar.size, Vardesc, SHRT_MAX, "variable declarationss");
+ dyd->actvar.size, Vardesc, SHRT_MAX, "variable declarations");
var = &dyd->actvar.arr[dyd->actvar.n++];
var->vd.kind = kind; /* default */
var->vd.name = name;
@@ -279,7 +279,9 @@
/*
-** Raises an error if variable described by 'e' is read only
+** Raises an error if variable described by 'e' is read only; moreover,
+** if 'e' is t[exp] where t is the vararg parameter, change it to index
+** a real table. (Virtual vararg tables cannot be changed.)
*/
static void check_readonly (LexState *ls, expdesc *e) {
FuncState *fs = ls->fs;
@@ -289,7 +291,7 @@
varname = ls->dyd->actvar.arr[e->u.info].vd.name;
break;
}
- case VLOCAL: {
+ case VLOCAL: case VVARGVAR: {
Vardesc *vardesc = getlocalvardesc(fs, e->u.var.vidx);
if (vardesc->vd.kind != VDKREG) /* not a regular variable? */
varname = vardesc->vd.name;
@@ -301,6 +303,10 @@
varname = up->name;
break;
}
+ case VVARGIND: {
+ fs->f->flag |= PF_VATAB; /* function will need a vararg table */
+ e->k = VINDEXED;
+ } /* FALLTHROUGH */
case VINDEXUP: case VINDEXSTR: case VINDEXED: { /* global variable */
if (e->u.ind.ro) /* read-only? */
varname = tsvalue(&fs->f->k[e->u.ind.keystr]);
@@ -426,8 +432,11 @@
else if (eqstr(n, vd->vd.name)) { /* found? */
if (vd->vd.kind == RDKCTC) /* compile-time constant? */
init_exp(var, VCONST, fs->firstlocal + i);
- else /* local variable */
+ else { /* local variable */
init_var(fs, var, i);
+ if (vd->vd.kind == RDKVAVAR) /* vararg parameter? */
+ var->k = VVARGVAR;
+ }
return cast_int(var->k);
}
}
@@ -467,8 +476,13 @@
static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
int v = searchvar(fs, n, var); /* look up variables at current level */
if (v >= 0) { /* found? */
- if (v == VLOCAL && !base)
- markupval(fs, var->u.var.vidx); /* local will be used as an upval */
+ if (!base) {
+ if (var->k == VVARGVAR) /* vararg parameter? */
+ luaK_vapar2local(fs, var); /* change it to a regular local */
+ if (var->k == VLOCAL)
+ markupval(fs, var->u.var.vidx); /* will be used as an upvalue */
+ }
+ /* else nothing else to be done */
}
else { /* not found at current level; try upvalues */
int idx = searchupvalue(fs, n); /* try existing upvalues */
@@ -485,6 +499,20 @@
}
+static void buildglobal (LexState *ls, TString *varname, expdesc *var) {
+ FuncState *fs = ls->fs;
+ expdesc key;
+ init_exp(var, VGLOBAL, -1); /* global by default */
+ singlevaraux(fs, ls->envn, var, 1); /* get environment variable */
+ if (var->k == VGLOBAL)
+ luaK_semerror(ls, "_ENV is global when accessing variable '%s'",
+ getstr(varname));
+ luaK_exp2anyregup(fs, var); /* _ENV could be a constant */
+ codestring(&key, varname); /* key is variable name */
+ luaK_indexed(fs, var, &key); /* 'var' represents _ENV[varname] */
+}
+
+
/*
** Find a variable with the given name 'n', handling global variables
** too.
@@ -494,18 +522,11 @@
init_exp(var, VGLOBAL, -1); /* global by default */
singlevaraux(fs, varname, var, 1);
if (var->k == VGLOBAL) { /* global name? */
- expdesc key;
int info = var->u.info;
/* global by default in the scope of a global declaration? */
if (info == -2)
luaK_semerror(ls, "variable '%s' not declared", getstr(varname));
- singlevaraux(fs, ls->envn, var, 1); /* get environment variable */
- if (var->k == VGLOBAL)
- luaK_semerror(ls, "_ENV is global when accessing variable '%s'",
- getstr(varname));
- luaK_exp2anyregup(fs, var); /* but could be a constant */
- codestring(&key, varname); /* key is variable name */
- luaK_indexed(fs, var, &key); /* env[varname] */
+ buildglobal(ls, varname, var);
if (info != -1 && ls->dyd->actvar.arr[info].vd.kind == GDKCONST)
var->u.ind.ro = 1; /* mark variable as read-only */
else /* anyway must be a global */
@@ -526,6 +547,7 @@
static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) {
FuncState *fs = ls->fs;
int needed = nvars - nexps; /* extra values needed */
+ luaK_checkstack(fs, needed);
if (hasmultret(e->k)) { /* last expression has multiple returns? */
int extra = needed + 1; /* discount last expression itself */
if (extra < 0)
@@ -665,7 +687,7 @@
/*
-** Traverse the pending goto's of the finishing block checking whether
+** Traverse the pending gotos of the finishing block checking whether
** each match some label of that block. Those that do not match are
** "exported" to the outer block, to be solved there. In particular,
** its 'nactvar' is updated with the level of the inner block,
@@ -898,6 +920,19 @@
} ConsControl;
+/*
+** Maximum number of elements in a constructor, to control the following:
+** * counter overflows;
+** * overflows in 'extra' for OP_NEWTABLE and OP_SETLIST;
+** * overflows when adding multiple returns in OP_SETLIST.
+*/
+#define MAX_CNST (INT_MAX/2)
+#if MAX_CNST/(MAXARG_vC + 1) > MAXARG_Ax
+#undef MAX_CNST
+#define MAX_CNST (MAXARG_Ax * (MAXARG_vC + 1))
+#endif
+
+
static void recfield (LexState *ls, ConsControl *cc) {
/* recfield -> (NAME | '['exp']') = exp */
FuncState *fs = ls->fs;
@@ -918,7 +953,7 @@
static void closelistfield (FuncState *fs, ConsControl *cc) {
- if (cc->v.k == VVOID) return; /* there is no list item */
+ lua_assert(cc->tostore > 0);
luaK_exp2nextreg(fs, &cc->v);
cc->v.k = VVOID;
if (cc->tostore >= cc->maxtostore) {
@@ -1006,10 +1041,12 @@
checknext(ls, '{' /*}*/);
cc.maxtostore = maxtostore(fs);
do {
- lua_assert(cc.v.k == VVOID || cc.tostore > 0);
if (ls->t.token == /*{*/ '}') break;
- closelistfield(fs, &cc);
+ if (cc.v.k != VVOID) /* is there a previous list item? */
+ closelistfield(fs, &cc); /* close it */
field(ls, &cc);
+ luaY_checklimit(fs, cc.tostore + cc.na + cc.nh, MAX_CNST,
+ "items in a constructor");
} while (testnext(ls, ',') || testnext(ls, ';'));
check_match(ls, /*{*/ '}', '{' /*}*/, line);
lastlistfield(fs, &cc);
@@ -1019,9 +1056,10 @@
/* }====================================================================== */
-static void setvararg (FuncState *fs, int nparams) {
- fs->f->flag |= PF_ISVARARG;
- luaK_codeABC(fs, OP_VARARGPREP, nparams, 0, 0);
+static void setvararg (FuncState *fs, int kind) {
+ lua_assert(kind & PF_ISVARARG);
+ fs->f->flag |= cast_byte(kind);
+ luaK_codeABC(fs, OP_VARARGPREP, 0, 0, 0);
}
@@ -1030,7 +1068,7 @@
FuncState *fs = ls->fs;
Proto *f = fs->f;
int nparams = 0;
- int isvararg = 0;
+ int varargk = 0;
if (ls->t.token != ')') { /* is 'parlist' not empty? */
do {
switch (ls->t.token) {
@@ -1040,19 +1078,27 @@
break;
}
case TK_DOTS: {
- luaX_next(ls);
- isvararg = 1;
+ varargk |= PF_ISVARARG;
+ luaX_next(ls); /* skip '...' */
+ if (ls->t.token == TK_NAME) {
+ new_varkind(ls, str_checkname(ls), RDKVAVAR);
+ varargk |= PF_VAVAR;
+ }
break;
}
default: luaX_syntaxerror(ls, "<name> or '...' expected");
}
- } while (!isvararg && testnext(ls, ','));
+ } while (!varargk && testnext(ls, ','));
}
adjustlocalvars(ls, nparams);
f->numparams = cast_byte(fs->nactvar);
- if (isvararg)
- setvararg(fs, f->numparams); /* declared vararg */
- luaK_reserveregs(fs, fs->nactvar); /* reserve registers for parameters */
+ if (varargk != 0) {
+ setvararg(fs, varargk); /* declared vararg */
+ if (varargk & PF_VAVAR)
+ adjustlocalvars(ls, 1); /* vararg parameter */
+ }
+ /* reserve registers for parameters (plus vararg parameter, if present) */
+ luaK_reserveregs(fs, fs->nactvar);
}
@@ -1435,6 +1481,15 @@
}
}
+
+/* Create code to store the "top" register in 'var' */
+static void storevartop (FuncState *fs, expdesc *var) {
+ expdesc e;
+ init_exp(&e, VNONRELOC, fs->freereg - 1);
+ luaK_storevar(fs, var, &e); /* will also free the top register */
+}
+
+
/*
** Parse and compile a multiple assignment. The first "variable"
** (a 'suffixedexp') was already read by the caller.
@@ -1468,8 +1523,7 @@
return; /* avoid default */
}
}
- init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */
- luaK_storevar(ls->fs, &lh->v, &e);
+ storevartop(ls->fs, &lh->v); /* default assignment */
}
@@ -1812,7 +1866,7 @@
switch (kind) {
case RDKTOCLOSE:
luaK_semerror(ls, "global variables cannot be to-be-closed");
- break; /* to avoid warnings */
+ return kind; /* to avoid warnings */
case RDKCONST:
return GDKCONST; /* adjust kind for global variable */
default:
@@ -1821,25 +1875,74 @@
}
+static void checkglobal (LexState *ls, TString *varname, int line) {
+ FuncState *fs = ls->fs;
+ expdesc var;
+ int k;
+ buildglobal(ls, varname, &var); /* create global variable in 'var' */
+ k = var.u.ind.keystr; /* index of global name in 'k' */
+ luaK_codecheckglobal(fs, &var, k, line);
+}
+
+
+/*
+** Recursively traverse list of globals to be initalized. When
+** going, generate table description for the global. In the end,
+** after all indices have been generated, read list of initializing
+** expressions. When returning, generate the assignment of the value on
+** the stack to the corresponding table description. 'n' is the variable
+** being handled, range [0, nvars - 1].
+*/
+static void initglobal (LexState *ls, int nvars, int firstidx, int n,
+ int line) {
+ if (n == nvars) { /* traversed all variables? */
+ expdesc e;
+ int nexps = explist(ls, &e); /* read list of expressions */
+ adjust_assign(ls, nvars, nexps, &e);
+ }
+ else { /* handle variable 'n' */
+ FuncState *fs = ls->fs;
+ expdesc var;
+ TString *varname = getlocalvardesc(fs, firstidx + n)->vd.name;
+ buildglobal(ls, varname, &var); /* create global variable in 'var' */
+ enterlevel(ls); /* control recursion depth */
+ initglobal(ls, nvars, firstidx, n + 1, line);
+ leavelevel(ls);
+ checkglobal(ls, varname, line);
+ storevartop(fs, &var);
+ }
+}
+
+
+static void globalnames (LexState *ls, lu_byte defkind) {
+ FuncState *fs = ls->fs;
+ int nvars = 0;
+ int lastidx; /* index of last registered variable */
+ do { /* for each name */
+ TString *vname = str_checkname(ls);
+ lu_byte kind = getglobalattribute(ls, defkind);
+ lastidx = new_varkind(ls, vname, kind);
+ nvars++;
+ } while (testnext(ls, ','));
+ if (testnext(ls, '=')) /* initialization? */
+ initglobal(ls, nvars, lastidx - nvars + 1, 0, ls->linenumber);
+ fs->nactvar = cast_short(fs->nactvar + nvars); /* activate declaration */
+}
+
+
static void globalstat (LexState *ls) {
/* globalstat -> (GLOBAL) attrib '*'
globalstat -> (GLOBAL) attrib NAME attrib {',' NAME attrib} */
FuncState *fs = ls->fs;
/* get prefixed attribute (if any); default is regular global variable */
lu_byte defkind = getglobalattribute(ls, GDKREG);
- if (testnext(ls, '*')) {
+ if (!testnext(ls, '*'))
+ globalnames(ls, defkind);
+ else {
/* use NULL as name to represent '*' entries */
new_varkind(ls, NULL, defkind);
fs->nactvar++; /* activate declaration */
}
- else {
- do { /* list of names */
- TString *vname = str_checkname(ls);
- lu_byte kind = getglobalattribute(ls, defkind);
- new_varkind(ls, vname, kind);
- fs->nactvar++; /* activate declaration */
- } while (testnext(ls, ','));
- }
}
@@ -1850,8 +1953,9 @@
TString *fname = str_checkname(ls);
new_varkind(ls, fname, GDKREG); /* declare global variable */
fs->nactvar++; /* enter its scope */
- buildvar(ls, fname, &var);
+ buildglobal(ls, fname, &var);
body(ls, &b, 0, ls->linenumber); /* compile and return closure in 'b' */
+ checkglobal(ls, fname, line);
luaK_storevar(fs, &var, &b);
luaK_fixline(fs, line); /* definition "happens" in the first line */
}
@@ -2049,7 +2153,7 @@
BlockCnt bl;
Upvaldesc *env;
open_func(ls, fs, &bl);
- setvararg(fs, 0); /* main function is always declared vararg */
+ setvararg(fs, PF_ISVARARG); /* main function is always vararg */
env = allocupvalue(fs); /* ...set environment upvalue */
env->instack = 1;
env->idx = 0;
src/lparser.h
@@ -37,6 +37,8 @@
info = result register */
VLOCAL, /* local variable; var.ridx = register index;
var.vidx = relative index in 'actvar.arr' */
+ VVARGVAR, /* vararg parameter; var.ridx = register index;
+ var.vidx = relative index in 'actvar.arr' */
VGLOBAL, /* global variable;
info = relative index in 'actvar.arr' (or -1 for
implicit declaration) */
@@ -49,6 +51,8 @@
ind.ro = true if it represents a read-only global;
ind.keystr = if key is a string, index in 'k' of that string;
-1 if key is not a string */
+ VVARGIND, /* indexed vararg parameter;
+ ind.* as in VINDEXED */
VINDEXUP, /* indexed upvalue;
ind.idx = key's K index;
ind.* as in VINDEXED */
@@ -97,10 +101,11 @@
/* kinds of variables */
#define VDKREG 0 /* regular local */
#define RDKCONST 1 /* local constant */
-#define RDKTOCLOSE 2 /* to-be-closed */
-#define RDKCTC 3 /* local compile-time constant */
-#define GDKREG 4 /* regular global */
-#define GDKCONST 5 /* global constant */
+#define RDKVAVAR 2 /* vararg parameter */
+#define RDKTOCLOSE 3 /* to-be-closed */
+#define RDKCTC 4 /* local compile-time constant */
+#define GDKREG 5 /* regular global */
+#define GDKCONST 6 /* global constant */
/* variables that live in registers */
#define varinreg(v) ((v)->vd.kind <= RDKTOCLOSE)
src/lstate.h
@@ -85,7 +85,7 @@
** they must be visited again at the end of the cycle), but they are
** marked black because assignments to them must activate barriers (to
** move them back to TOUCHED1).
-** - Open upvales are kept gray to avoid barriers, but they stay out
+** - Open upvalues are kept gray to avoid barriers, but they stay out
** of gray lists. (They don't even have a 'gclist' field.)
*/
@@ -232,7 +232,7 @@
/* call is running a C function (still in first 16 bits) */
#define CIST_C (1u << (CIST_RECST + 3))
/* call is on a fresh "luaV_execute" frame */
-#define CIST_FRESH cast(l_uint32, CIST_C << 1)
+#define CIST_FRESH (cast(l_uint32, CIST_C) << 1)
/* function is closing tbc variables */
#define CIST_CLSRET (CIST_FRESH << 1)
/* function has tbc variables to close */
@@ -249,10 +249,6 @@
#define CIST_HOOKYIELD (CIST_TAIL << 1)
/* function "called" a finalizer */
#define CIST_FIN (CIST_HOOKYIELD << 1)
-#if defined(LUA_COMPAT_LT_LE)
-/* using __lt for __le */
-#define CIST_LEQ (CIST_FIN << 1)
-#endif
#define get_nresults(cs) (cast_int((cs) & CIST_NRESULTS) - 1)
@@ -430,9 +426,9 @@
/*
** macro to convert a Lua object into a GCObject
-** (The access to 'tt' tries to ensure that 'v' is actually a Lua object.)
*/
-#define obj2gco(v) check_exp((v)->tt >= LUA_TSTRING, &(cast_u(v)->gc))
+#define obj2gco(v) \
+ check_exp(novariant((v)->tt) >= LUA_TSTRING, &(cast_u(v)->gc))
/* actual number of total memory allocated */
src/lstring.c
@@ -39,18 +39,18 @@
/*
-** equality for long strings
+** generic equality for strings
*/
-int luaS_eqlngstr (TString *a, TString *b) {
- size_t len = a->u.lnglen;
- lua_assert(a->tt == LUA_VLNGSTR && b->tt == LUA_VLNGSTR);
- return (a == b) || /* same instance or... */
- ((len == b->u.lnglen) && /* equal length and ... */
- (memcmp(getlngstr(a), getlngstr(b), len) == 0)); /* equal contents */
+int luaS_eqstr (TString *a, TString *b) {
+ size_t len1, len2;
+ const char *s1 = getlstr(a, len1);
+ const char *s2 = getlstr(b, len2);
+ return ((len1 == len2) && /* equal length and ... */
+ (memcmp(s1, s2, len1) == 0)); /* equal contents */
}
-unsigned luaS_hash (const char *str, size_t l, unsigned seed) {
+static unsigned luaS_hash (const char *str, size_t l, unsigned seed) {
unsigned int h = seed ^ cast_uint(l);
for (; l > 0; l--)
h ^= ((h<<5) + (h>>2) + cast_byte(str[l - 1]));
@@ -315,28 +315,9 @@
}
-static void f_pintern (lua_State *L, void *ud) {
- struct NewExt *ne = cast(struct NewExt *, ud);
- ne->ts = internshrstr(L, ne->s, ne->len);
-}
-
-
TString *luaS_newextlstr (lua_State *L,
const char *s, size_t len, lua_Alloc falloc, void *ud) {
struct NewExt ne;
- if (len <= LUAI_MAXSHORTLEN) { /* short string? */
- ne.s = s; ne.len = len;
- if (!falloc)
- f_pintern(L, &ne); /* just internalize string */
- else {
- TStatus status = luaD_rawrunprotected(L, f_pintern, &ne);
- (*falloc)(ud, cast_voidp(s), len + 1, 0); /* free external string */
- if (status != LUA_OK) /* memory error? */
- luaM_error(L); /* re-raise memory error */
- }
- return ne.ts;
- }
- /* "normal" case: long strings */
if (!falloc) {
ne.kind = LSTRFIX;
f_newext(L, &ne); /* just create header */
@@ -357,3 +338,16 @@
}
+/*
+** Normalize an external string: If it is short, internalize it.
+*/
+TString *luaS_normstr (lua_State *L, TString *ts) {
+ size_t len = ts->u.lnglen;
+ if (len > LUAI_MAXSHORTLEN)
+ return ts; /* long string; keep the original */
+ else {
+ const char *str = getlngstr(ts);
+ return internshrstr(L, str, len);
+ }
+}
+
src/lstring.h
@@ -54,9 +54,8 @@
#define eqshrstr(a,b) check_exp((a)->tt == LUA_VSHRSTR, (a) == (b))
-LUAI_FUNC unsigned luaS_hash (const char *str, size_t l, unsigned seed);
LUAI_FUNC unsigned luaS_hashlongstr (TString *ts);
-LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b);
+LUAI_FUNC int luaS_eqstr (TString *a, TString *b);
LUAI_FUNC void luaS_resize (lua_State *L, int newsize);
LUAI_FUNC void luaS_clearcache (global_State *g);
LUAI_FUNC void luaS_init (lua_State *L);
@@ -69,5 +68,6 @@
LUAI_FUNC TString *luaS_newextlstr (lua_State *L,
const char *s, size_t len, lua_Alloc falloc, void *ud);
LUAI_FUNC size_t luaS_sizelngstr (size_t len, int kind);
+LUAI_FUNC TString *luaS_normstr (lua_State *L, TString *ts);
#endif
src/lstrlib.c
@@ -132,27 +132,31 @@
}
+/*
+** MAX_SIZE is limited both by size_t and lua_Integer.
+** When x <= MAX_SIZE, x can be safely cast to size_t or lua_Integer.
+*/
static int str_rep (lua_State *L) {
- size_t l, lsep;
- const char *s = luaL_checklstring(L, 1, &l);
+ size_t len, lsep;
+ const char *s = luaL_checklstring(L, 1, &len);
lua_Integer n = luaL_checkinteger(L, 2);
const char *sep = luaL_optlstring(L, 3, "", &lsep);
if (n <= 0)
lua_pushliteral(L, "");
- else if (l_unlikely(l + lsep < l || l + lsep > MAX_SIZE / cast_sizet(n)))
+ else if (l_unlikely(len > MAX_SIZE - lsep ||
+ cast_st2S(len + lsep) > cast_st2S(MAX_SIZE) / n))
return luaL_error(L, "resulting string too large");
else {
- size_t totallen = ((size_t)n * (l + lsep)) - lsep;
+ size_t totallen = (cast_sizet(n) * (len + lsep)) - lsep;
luaL_Buffer b;
char *p = luaL_buffinitsize(L, &b, totallen);
while (n-- > 1) { /* first n-1 copies (followed by separator) */
- memcpy(p, s, l * sizeof(char)); p += l;
+ memcpy(p, s, len * sizeof(char)); p += len;
if (lsep > 0) { /* empty 'memcpy' is not that cheap */
- memcpy(p, sep, lsep * sizeof(char));
- p += lsep;
+ memcpy(p, sep, lsep * sizeof(char)); p += lsep;
}
}
- memcpy(p, s, l * sizeof(char)); /* last copy (not followed by separator) */
+ memcpy(p, s, len * sizeof(char)); /* last copy without separator */
luaL_pushresultsize(&b, totallen);
}
return 1;
@@ -265,11 +269,18 @@
}
-static void trymt (lua_State *L, const char *mtname) {
+/*
+** To be here, either the first operand was a string or the first
+** operand didn't have a corresponding metamethod. (Otherwise, that
+** other metamethod would have been called.) So, if this metamethod
+** doesn't work, the only other option would be for the second
+** operand to have a different metamethod.
+*/
+static void trymt (lua_State *L, const char *mtkey, const char *opname) {
lua_settop(L, 2); /* back to the original arguments */
if (l_unlikely(lua_type(L, 2) == LUA_TSTRING ||
- !luaL_getmetafield(L, 2, mtname)))
- luaL_error(L, "attempt to %s a '%s' with a '%s'", mtname + 2,
+ !luaL_getmetafield(L, 2, mtkey)))
+ luaL_error(L, "attempt to %s a '%s' with a '%s'", opname,
luaL_typename(L, -2), luaL_typename(L, -1));
lua_insert(L, -3); /* put metamethod before arguments */
lua_call(L, 2, 1); /* call metamethod */
@@ -280,7 +291,7 @@
if (tonum(L, 1) && tonum(L, 2))
lua_arith(L, op); /* result will be on the top */
else
- trymt(L, mtname);
+ trymt(L, mtname, mtname + 2);
return 1;
}
@@ -1811,8 +1822,8 @@
lua_Unsigned len = (lua_Unsigned)unpackint(L, data + pos,
h.islittle, cast_int(size), 0);
luaL_argcheck(L, len <= ld - pos - size, 2, "data string too short");
- lua_pushlstring(L, data + pos + size, len);
- pos += len; /* skip string */
+ lua_pushlstring(L, data + pos + size, cast_sizet(len));
+ pos += cast_sizet(len); /* skip string */
break;
}
case Kzstr: {
src/ltable.c
@@ -156,7 +156,7 @@
** The main computation should be just
** n = frexp(n, &i); return (n * INT_MAX) + i
** but there are some numerical subtleties.
-** In a two-complement representation, INT_MAX does not has an exact
+** In a two-complement representation, INT_MAX may not have an exact
** representation as a float, but INT_MIN does; because the absolute
** value of 'frexp' is smaller than 1 (unless 'n' is inf/NaN), the
** absolute value of the product 'frexp * -INT_MIN' is smaller or equal
@@ -234,41 +234,51 @@
** Check whether key 'k1' is equal to the key in node 'n2'. This
** equality is raw, so there are no metamethods. Floats with integer
** values have been normalized, so integers cannot be equal to
-** floats. It is assumed that 'eqshrstr' is simply pointer equality, so
-** that short strings are handled in the default case.
-** A true 'deadok' means to accept dead keys as equal to their original
-** values. All dead keys are compared in the default case, by pointer
-** identity. (Only collectable objects can produce dead keys.) Note that
-** dead long strings are also compared by identity.
-** Once a key is dead, its corresponding value may be collected, and
-** then another value can be created with the same address. If this
-** other value is given to 'next', 'equalkey' will signal a false
-** positive. In a regular traversal, this situation should never happen,
-** as all keys given to 'next' came from the table itself, and therefore
-** could not have been collected. Outside a regular traversal, we
-** have garbage in, garbage out. What is relevant is that this false
-** positive does not break anything. (In particular, 'next' will return
-** some other valid item on the table or nil.)
+** floats. It is assumed that 'eqshrstr' is simply pointer equality,
+** so that short strings are handled in the default case. The flag
+** 'deadok' means to accept dead keys as equal to their original values.
+** (Only collectable objects can produce dead keys.) Note that dead
+** long strings are also compared by identity. Once a key is dead,
+** its corresponding value may be collected, and then another value
+** can be created with the same address. If this other value is given
+** to 'next', 'equalkey' will signal a false positive. In a regular
+** traversal, this situation should never happen, as all keys given to
+** 'next' came from the table itself, and therefore could not have been
+** collected. Outside a regular traversal, we have garbage in, garbage
+** out. What is relevant is that this false positive does not break
+** anything. (In particular, 'next' will return some other valid item
+** on the table or nil.)
*/
static int equalkey (const TValue *k1, const Node *n2, int deadok) {
- if ((rawtt(k1) != keytt(n2)) && /* not the same variants? */
- !(deadok && keyisdead(n2) && iscollectable(k1)))
- return 0; /* cannot be same key */
- switch (keytt(n2)) {
- case LUA_VNIL: case LUA_VFALSE: case LUA_VTRUE:
- return 1;
- case LUA_VNUMINT:
- return (ivalue(k1) == keyival(n2));
- case LUA_VNUMFLT:
- return luai_numeq(fltvalue(k1), fltvalueraw(keyval(n2)));
- case LUA_VLIGHTUSERDATA:
- return pvalue(k1) == pvalueraw(keyval(n2));
- case LUA_VLCF:
- return fvalue(k1) == fvalueraw(keyval(n2));
- case ctb(LUA_VLNGSTR):
- return luaS_eqlngstr(tsvalue(k1), keystrval(n2));
- default:
+ if (rawtt(k1) != keytt(n2)) { /* not the same variants? */
+ if (keyisshrstr(n2) && ttislngstring(k1)) {
+ /* an external string can be equal to a short-string key */
+ return luaS_eqstr(tsvalue(k1), keystrval(n2));
+ }
+ else if (deadok && keyisdead(n2) && iscollectable(k1)) {
+ /* a collectable value can be equal to a dead key */
return gcvalue(k1) == gcvalueraw(keyval(n2));
+ }
+ else
+ return 0; /* otherwise, different variants cannot be equal */
+ }
+ else { /* equal variants */
+ switch (keytt(n2)) {
+ case LUA_VNIL: case LUA_VFALSE: case LUA_VTRUE:
+ return 1;
+ case LUA_VNUMINT:
+ return (ivalue(k1) == keyival(n2));
+ case LUA_VNUMFLT:
+ return luai_numeq(fltvalue(k1), fltvalueraw(keyval(n2)));
+ case LUA_VLIGHTUSERDATA:
+ return pvalue(k1) == pvalueraw(keyval(n2));
+ case LUA_VLCF:
+ return fvalue(k1) == fvalueraw(keyval(n2));
+ case ctb(LUA_VLNGSTR):
+ return luaS_eqstr(tsvalue(k1), keystrval(n2));
+ default:
+ return gcvalue(k1) == gcvalueraw(keyval(n2));
+ }
}
}
@@ -1158,6 +1168,14 @@
else if (l_unlikely(luai_numisnan(f)))
luaG_runerror(L, "table index is NaN");
}
+ else if (isextstr(key)) { /* external string? */
+ /* If string is short, must internalize it to be used as table key */
+ TString *ts = luaS_normstr(L, tsvalue(key));
+ setsvalue2s(L, L->top.p++, ts); /* anchor 'ts' (EXTRA_STACK) */
+ luaH_newkey(L, t, s2v(L->top.p - 1), value);
+ L->top.p--;
+ return;
+ }
luaH_newkey(L, t, key, value);
}
else if (hres > 0) { /* regular Node? */
@@ -1202,24 +1220,36 @@
/*
** Try to find a boundary in the hash part of table 't'. From the
-** caller, we know that 'j' is zero or present and that 'j + 1' is
-** present. We want to find a larger key that is absent from the
-** table, so that we can do a binary search between the two keys to
-** find a boundary. We keep doubling 'j' until we get an absent index.
-** If the doubling would overflow, we try LUA_MAXINTEGER. If it is
-** absent, we are ready for the binary search. ('j', being max integer,
-** is larger or equal to 'i', but it cannot be equal because it is
-** absent while 'i' is present; so 'j > i'.) Otherwise, 'j' is a
-** boundary. ('j + 1' cannot be a present integer key because it is
-** not a valid integer in Lua.)
-*/
-static lua_Unsigned hash_search (Table *t, lua_Unsigned j) {
- lua_Unsigned i;
- if (j == 0) j++; /* the caller ensures 'j + 1' is present */
- do {
+** caller, we know that 'asize + 1' is present. We want to find a larger
+** key that is absent from the table, so that we can do a binary search
+** between the two keys to find a boundary. We keep doubling 'j' until
+** we get an absent index. If the doubling would overflow, we try
+** LUA_MAXINTEGER. If it is absent, we are ready for the binary search.
+** ('j', being max integer, is larger or equal to 'i', but it cannot be
+** equal because it is absent while 'i' is present.) Otherwise, 'j' is a
+** boundary. ('j + 1' cannot be a present integer key because it is not
+** a valid integer in Lua.)
+** About 'rnd': If we used a fixed algorithm, a bad actor could fill
+** a table with only the keys that would be probed, in such a way that
+** a small table could result in a huge length. To avoid that, we use
+** the state's seed as a source of randomness. For the first probe,
+** we "randomly double" 'i' by adding to it a random number roughly its
+** width.
+*/
+static lua_Unsigned hash_search (lua_State *L, Table *t, unsigned asize) {
+ lua_Unsigned i = asize + 1; /* caller ensures t[i] is present */
+ unsigned rnd = G(L)->seed;
+ int n = (asize > 0) ? luaO_ceillog2(asize) : 0; /* width of 'asize' */
+ unsigned mask = (1u << n) - 1; /* 11...111 with the width of 'asize' */
+ unsigned incr = (rnd & mask) + 1; /* first increment (at least 1) */
+ lua_Unsigned j = (incr <= l_castS2U(LUA_MAXINTEGER) - i) ? i + incr : i + 1;
+ rnd >>= n; /* used 'n' bits from 'rnd' */
+ while (!hashkeyisempty(t, j)) { /* repeat until an absent t[j] */
i = j; /* 'i' is a present index */
- if (j <= l_castS2U(LUA_MAXINTEGER) / 2)
- j *= 2;
+ if (j <= l_castS2U(LUA_MAXINTEGER)/2 - 1) {
+ j = j*2 + (rnd & 1); /* try again with 2j or 2j+1 */
+ rnd >>= 1;
+ }
else {
j = LUA_MAXINTEGER;
if (hashkeyisempty(t, j)) /* t[j] not present? */
@@ -1227,7 +1257,7 @@
else /* weird case */
return j; /* well, max integer is a boundary... */
}
- } while (!hashkeyisempty(t, j)); /* repeat until an absent t[j] */
+ }
/* i < j && t[i] present && t[j] absent */
while (j - i > 1u) { /* do a binary search between them */
lua_Unsigned m = (i + j) / 2;
@@ -1268,7 +1298,7 @@
** If there is no array part, or its last element is non empty, the
** border may be in the hash part.
*/
-lua_Unsigned luaH_getn (Table *t) {
+lua_Unsigned luaH_getn (lua_State *L, Table *t) {
unsigned asize = t->asize;
if (asize > 0) { /* is there an array part? */
const unsigned maxvicinity = 4;
@@ -1309,7 +1339,7 @@
if (isdummy(t) || hashkeyisempty(t, asize + 1))
return asize; /* 'asize + 1' is empty */
else /* 'asize + 1' is also non empty */
- return hash_search(t, asize);
+ return hash_search(L, t, asize);
}
src/ltable.h
@@ -173,7 +173,7 @@
LUAI_FUNC lu_mem luaH_size (Table *t);
LUAI_FUNC void luaH_free (lua_State *L, Table *t);
LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key);
-LUAI_FUNC lua_Unsigned luaH_getn (Table *t);
+LUAI_FUNC lua_Unsigned luaH_getn (lua_State *L, Table *t);
#if defined(LUA_DEBUG)
src/ltm.c
@@ -196,28 +196,12 @@
/*
** Calls an order tag method.
-** For lessequal, LUA_COMPAT_LT_LE keeps compatibility with old
-** behavior: if there is no '__le', try '__lt', based on l <= r iff
-** !(r < l) (assuming a total order). If the metamethod yields during
-** this substitution, the continuation has to know about it (to negate
-** the result of r<l); bit CIST_LEQ in the call status keeps that
-** information.
*/
int luaT_callorderTM (lua_State *L, const TValue *p1, const TValue *p2,
TMS event) {
int tag = callbinTM(L, p1, p2, L->top.p, event); /* try original event */
if (tag >= 0) /* found tag method? */
return !tagisfalse(tag);
-#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' */
- tag = callbinTM(L, p2, p1, L->top.p, TM_LT);
- L->ci->callstatus ^= CIST_LEQ; /* clear mark */
- if (tag >= 0) /* found tag method? */
- return tagisfalse(tag);
- }
-#endif
luaG_ordererror(L, p1, p2); /* no metamethod found */
return 0; /* to avoid warnings */
}
@@ -240,11 +224,38 @@
}
-void luaT_adjustvarargs (lua_State *L, int nfixparams, CallInfo *ci,
- const Proto *p) {
+/*
+** Create a vararg table at the top of the stack, with 'n' elements
+** starting at 'f'.
+*/
+static void createvarargtab (lua_State *L, StkId f, int n) {
int i;
- int actual = cast_int(L->top.p - ci->func.p) - 1; /* number of arguments */
- int nextra = actual - nfixparams; /* number of extra arguments */
+ TValue key, value;
+ Table *t = luaH_new(L);
+ sethvalue(L, s2v(L->top.p), t);
+ L->top.p++;
+ luaH_resize(L, t, cast_uint(n), 1);
+ setsvalue(L, &key, luaS_new(L, "n")); /* key is "n" */
+ setivalue(&value, n); /* value is n */
+ /* No need to anchor the key: Due to the resize, the next operation
+ cannot trigger a garbage collection */
+ luaH_set(L, t, &key, &value); /* t.n = n */
+ for (i = 0; i < n; i++)
+ luaH_setint(L, t, i + 1, s2v(f + i));
+}
+
+
+/*
+** initial stack: func arg1 ... argn extra1 ...
+** ^ ci->func ^ L->top
+** final stack: func nil ... nil extra1 ... func arg1 ... argn
+** ^ ci->func ^ L->top
+*/
+void luaT_adjustvarargs (lua_State *L, CallInfo *ci, const Proto *p) {
+ int i;
+ int totalargs = cast_int(L->top.p - ci->func.p) - 1;
+ int nfixparams = p->numparams;
+ int nextra = totalargs - nfixparams; /* number of extra arguments */
ci->u.l.nextraargs = nextra;
luaD_checkstack(L, p->maxstacksize + 1);
/* copy function to the top of the stack */
@@ -254,12 +265,40 @@
setobjs2s(L, L->top.p++, ci->func.p + i);
setnilvalue(s2v(ci->func.p + i)); /* erase original parameter (for GC) */
}
- ci->func.p += actual + 1;
- ci->top.p += actual + 1;
+ if (p->flag & PF_VAVAR) { /* is there a vararg parameter? */
+ if (p->flag & PF_VATAB) /* does it need a vararg table? */
+ createvarargtab(L, ci->func.p + nfixparams + 1, nextra);
+ else /* no table; set parameter to nil */
+ setnilvalue(s2v(L->top.p));
+ }
+ ci->func.p += totalargs + 1;
+ ci->top.p += totalargs + 1;
lua_assert(L->top.p <= ci->top.p && ci->top.p <= L->stack_last.p);
}
+void luaT_getvararg (CallInfo *ci, StkId ra, TValue *rc) {
+ int nextra = ci->u.l.nextraargs;
+ lua_Integer n;
+ if (tointegerns(rc, &n)) { /* integral value? */
+ if (l_castS2U(n) - 1 < cast_uint(nextra)) {
+ StkId slot = ci->func.p - nextra + cast_int(n) - 1;
+ setobjs2s(((lua_State*)NULL), ra, slot);
+ return;
+ }
+ }
+ else if (ttisstring(rc)) { /* string value? */
+ size_t len;
+ const char *s = getlstr(tsvalue(rc), len);
+ if (len == 1 && s[0] == 'n') { /* key is "n"? */
+ setivalue(s2v(ra), nextra);
+ return;
+ }
+ }
+ setnilvalue(s2v(ra)); /* else produce nil */
+}
+
+
void luaT_getvarargs (lua_State *L, CallInfo *ci, StkId where, int wanted) {
int i;
int nextra = ci->u.l.nextraargs;
src/ltm.h
@@ -95,8 +95,9 @@
LUAI_FUNC int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2,
int inv, int isfloat, TMS event);
-LUAI_FUNC void luaT_adjustvarargs (lua_State *L, int nfixparams,
- struct CallInfo *ci, const Proto *p);
+LUAI_FUNC void luaT_adjustvarargs (lua_State *L, struct CallInfo *ci,
+ const Proto *p);
+LUAI_FUNC void luaT_getvararg (CallInfo *ci, StkId ra, TValue *rc);
LUAI_FUNC void luaT_getvarargs (lua_State *L, struct CallInfo *ci,
StkId where, int wanted);
src/lua.c
@@ -303,7 +303,8 @@
case '-': /* '--' */
if (argv[i][2] != '\0') /* extra characters after '--'? */
return has_error; /* invalid option */
- *first = i + 1;
+ /* if there is a script name, it comes after '--' */
+ *first = (argv[i + 1] != NULL) ? i + 1 : 0;
return args;
case '\0': /* '-' */
return args; /* script "name" is '-' */
@@ -437,13 +438,24 @@
** the standard input.
** * lua_saveline defines how to "save" a read line in a "history".
** * lua_freeline defines how to free a line read by lua_readline.
-**
-** If lua_readline is defined, all of them should be defined.
*/
#if !defined(lua_readline) /* { */
+/* Otherwise, all previously listed functions should be defined. */
-/* Code to use the readline library, either statically or dynamically linked */
+#if defined(LUA_USE_READLINE) /* { */
+/* Lua will be linked with '-lreadline' */
+
+#include <readline/readline.h>
+#include <readline/history.h>
+
+#define lua_initreadline(L) ((void)L, rl_readline_name="lua")
+#define lua_readline(buff,prompt) ((void)buff, readline(prompt))
+#define lua_saveline(line) add_history(line)
+#define lua_freeline(line) free(line)
+
+#else /* }{ */
+/* use dynamically loaded readline (or nothing) */
/* pointer to 'readline' function (if any) */
typedef char *(*l_readlineT) (const char *prompt);
@@ -479,22 +491,9 @@
}
-#if defined(LUA_USE_READLINE) /* { */
-
-/* assume Lua will be linked with '-lreadline' */
-#include <readline/readline.h>
-#include <readline/history.h>
-
-static void lua_initreadline(lua_State *L) {
- UNUSED(L);
- rl_readline_name = "lua";
- l_readline = cast(l_readlineT, readline);
- l_addhist = cast(l_addhistT, add_history);
-}
-
-#elif defined(LUA_USE_DLOPEN) && defined(LUA_READLINELIB) /* }{ */
-
+#if defined(LUA_USE_DLOPEN) && defined(LUA_READLINELIB) /* { */
/* try to load 'readline' dynamically */
+
#include <dlfcn.h>
static void lua_initreadline (lua_State *L) {
@@ -507,15 +506,20 @@
*name = "lua";
l_readline = cast(l_readlineT, cast_func(dlsym(lib, "readline")));
l_addhist = cast(l_addhistT, cast_func(dlsym(lib, "add_history")));
+ if (l_readline == NULL)
+ lua_warning(L, "unable to load 'readline'", 0);
}
}
-#else /* }{ */
+#else /* }{ */
+/* no dlopen or LUA_READLINELIB undefined */
-/* no readline; leave function pointers as NULL */
-#define lua_initreadline(L) cast(void, L)
+/* Leave pointers with NULL */
+#define lua_initreadline(L) ((void)L)
-#endif /* } */
+#endif /* } */
+
+#endif /* } */
#endif /* } */
src/lua.h
@@ -37,10 +37,10 @@
/*
** Pseudo-indices
-** (-LUAI_MAXSTACK is the minimum valid index; we keep some free empty
-** space after that to help overflow detection)
+** (The stack size is limited to INT_MAX/2; we keep some free empty
+** space after that to help overflow detection.)
*/
-#define LUA_REGISTRYINDEX (-LUAI_MAXSTACK - 1000)
+#define LUA_REGISTRYINDEX (-(INT_MAX/2 + 1000))
#define lua_upvalueindex(i) (LUA_REGISTRYINDEX - (i))
@@ -432,13 +432,6 @@
** compatibility macros
** ===============================================================
*/
-#if defined(LUA_COMPAT_APIINTCASTS)
-
-#define lua_pushunsigned(L,n) lua_pushinteger(L, (lua_Integer)(n))
-#define lua_tounsignedx(L,i,is) ((lua_Unsigned)lua_tointegerx(L,i,is))
-#define lua_tounsigned(L,i) lua_tounsignedx(L,(i),NULL)
-
-#endif
#define lua_newuserdata(L,s) lua_newuserdatauv(L,s,1)
#define lua_getuservalue(L,idx) lua_getiuservalue(L,idx,1)
src/luac.c
@@ -478,10 +478,10 @@
printf("%d %d %d",a,b,c);
printf(COMMENT); PrintConstant(f,c);
break;
- case OP_SHRI:
+ case OP_SHLI:
printf("%d %d %d",a,b,sc);
break;
- case OP_SHLI:
+ case OP_SHRI:
printf("%d %d %d",a,b,sc);
break;
case OP_ADD:
@@ -645,6 +645,13 @@
printf(COMMENT);
if (c==0) printf("all out"); else printf("%d out",c-1);
break;
+ case OP_GETVARG:
+ printf("%d %d %d",a,b,c);
+ break;
+ case OP_ERRNNIL:
+ printf("%d %d",a,bx);
+ printf(COMMENT); PrintConstant(f,bx);
+ break;
case OP_VARARGPREP:
printf("%d",a);
break;
@@ -662,7 +669,6 @@
}
}
-
#define SS(x) ((x==1)?"":"s")
#define S(x) (int)(x),SS(x)
src/luaconf.h
@@ -59,7 +59,7 @@
/*
-** When Posix DLL ('LUA_USE_DLOPEN') is enabled, the Lua stand-alone
+** When POSIX DLL ('LUA_USE_DLOPEN') is enabled, the Lua stand-alone
** application will try to dynamically link a 'readline' facility
** for its REPL. In that case, LUA_READLINELIB is the name of the
** library it will look for those facilities. If lua.c cannot open
@@ -76,7 +76,7 @@
#if defined(LUA_USE_MACOSX)
#define LUA_USE_POSIX
-#define LUA_USE_DLOPEN /* MacOS does not need -ldl */
+#define LUA_USE_DLOPEN /* macOS does not need -ldl */
#define LUA_READLINELIB "libedit.dylib"
#endif
@@ -88,7 +88,7 @@
#if defined(LUA_USE_C89) && defined(LUA_USE_POSIX)
-#error "Posix is not compatible with C89"
+#error "POSIX is not compatible with C89"
#endif
@@ -138,7 +138,7 @@
/*
@@ LUA_32BITS enables Lua with 32-bit integers and 32-bit floats.
*/
-#define LUA_32BITS 0
+/* #define LUA_32BITS */
/*
@@ -153,7 +153,7 @@
#endif
-#if LUA_32BITS /* { */
+#if defined(LUA_32BITS) /* { */
/*
** 32-bit integers and 'float'
*/
@@ -319,32 +319,13 @@
** More often than not the libs go together with the core.
*/
#define LUALIB_API LUA_API
-#define LUAMOD_API LUA_API
-
-/*
-@@ LUAI_FUNC is a mark for all extern functions that are not to be
-** exported to outside modules.
-@@ LUAI_DDEF and LUAI_DDEC are marks for all extern (const) variables,
-** none of which to be exported to outside modules (LUAI_DDEF for
-** definitions and LUAI_DDEC for declarations).
-** CHANGE them if you need to mark them in some special way. Elf/gcc
-** (versions 3.2 and later) mark them as "hidden" to optimize access
-** when Lua is compiled as a shared library. Not all elf targets support
-** this attribute. Unfortunately, gcc does not offer a way to check
-** whether the target offers that support, and those without support
-** give a warning about it. To avoid these warnings, change to the
-** default definition.
-*/
-#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \
- defined(__ELF__) /* { */
-#define LUAI_FUNC __attribute__((visibility("internal"))) extern
-#else /* }{ */
-#define LUAI_FUNC extern
-#endif /* } */
-
-#define LUAI_DDEC(dec) LUAI_FUNC dec
-#define LUAI_DDEF /* empty */
+#if defined(__cplusplus)
+/* Lua uses the "C name" when calling open functions */
+#define LUAMOD_API extern "C"
+#else
+#define LUAMOD_API LUA_API
+#endif
/* }================================================================== */
@@ -362,35 +343,12 @@
/*
-@@ 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.
-*/
-#if defined(LUA_COMPAT_5_3) /* { */
-
-/*
@@ LUA_COMPAT_MATHLIB controls the presence of several deprecated
** functions in the mathematical library.
** (These functions were already officially removed in 5.3;
** nevertheless they are still available here.)
*/
-#define LUA_COMPAT_MATHLIB
-
-/*
-@@ 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
-
-
-/*
-@@ LUA_COMPAT_LT_LE controls the emulation of the '__le' metamethod
-** using '__lt'.
-*/
-#define LUA_COMPAT_LT_LE
+/* #define LUA_COMPAT_MATHLIB */
/*
@@ -407,8 +365,6 @@
#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 /* } */
-
/* }================================================================== */
@@ -440,26 +396,11 @@
*/
-/* The following definitions are good for most cases here */
+/* The following definition is good for most cases here */
#define l_floor(x) (l_mathop(floor)(x))
-/*
-@@ lua_numbertointeger converts a float number with an integral value
-** to an integer, or returns 0 if float is not within the range of
-** a lua_Integer. (The range comparisons are tricky because of
-** rounding. The tests here assume a two-complement representation,
-** where MININTEGER always has an exact representation as a float;
-** MAXINTEGER may not have one, and therefore its conversion to float
-** may have an ill-defined value.)
-*/
-#define lua_numbertointeger(n,p) \
- ((n) >= (LUA_NUMBER)(LUA_MININTEGER) && \
- (n) < -(LUA_NUMBER)(LUA_MININTEGER) && \
- (*(p) = (LUA_INTEGER)(n), 1))
-
-
/* now the variable definitions */
#if LUA_FLOAT_TYPE == LUA_FLOAT_FLOAT /* { single float */
@@ -719,13 +660,6 @@
#endif
-#if defined(LUA_CORE) || defined(LUA_LIB)
-/* shorter names for Lua's own use */
-#define l_likely(x) luai_likely(x)
-#define l_unlikely(x) luai_unlikely(x)
-#endif
-
-
/* }================================================================== */
@@ -764,20 +698,6 @@
*/
/*
-@@ LUAI_MAXSTACK limits the size of the Lua stack.
-** CHANGE it if you need a different limit. This limit is arbitrary;
-** its only purpose is to stop Lua from consuming unlimited stack
-** space and to reserve some numbers for pseudo-indices.
-** (It must fit into max(int)/2.)
-*/
-#if 1000000 < (INT_MAX / 2)
-#define LUAI_MAXSTACK 1000000
-#else
-#define LUAI_MAXSTACK (INT_MAX / 2u)
-#endif
-
-
-/*
@@ LUA_EXTRASPACE defines the size of a raw memory area associated with
** a Lua state with very fast access.
** CHANGE it if you need a different size.
@@ -821,7 +741,5 @@
-
-
#endif
src/lundump.c
@@ -109,7 +109,7 @@
static size_t loadSize (LoadState *S) {
- return loadVarint(S, MAX_SIZE);
+ return cast_sizet(loadVarint(S, MAX_SIZE));
}
@@ -147,20 +147,20 @@
TString *ts;
TValue sv;
size_t size = loadSize(S);
- if (size == 0) { /* no string? */
- lua_assert(*sl == NULL); /* must be prefilled */
- return;
- }
- else if (size == 1) { /* previously saved string? */
+ if (size == 0) { /* previously saved string? */
lua_Unsigned idx = loadVarint(S, LUA_MAXUNSIGNED); /* get its index */
TValue stv;
+ if (idx == 0) { /* no string? */
+ lua_assert(*sl == NULL); /* must be prefilled */
+ return;
+ }
if (novariant(luaH_getint(S->h, l_castU2S(idx), &stv)) != LUA_TSTRING)
error(S, "invalid string index");
*sl = ts = tsvalue(&stv); /* get its value */
luaC_objbarrier(L, p, ts);
return; /* do not save it again */
}
- else if ((size -= 2) <= LUAI_MAXSHORTLEN) { /* short string? */
+ else if ((size -= 1) <= LUAI_MAXSHORTLEN) { /* short string? */
char buff[LUAI_MAXSHORTLEN + 1]; /* extra space for '\0' */
loadVector(S, buff, size + 1); /* load string into buffer */
*sl = ts = luaS_newlstr(L, buff, size); /* create string */
@@ -327,7 +327,8 @@
f->linedefined = loadInt(S);
f->lastlinedefined = loadInt(S);
f->numparams = loadByte(S);
- f->flag = loadByte(S) & PF_ISVARARG; /* get only the meaningful flags */
+ /* get only the meaningful flags */
+ f->flag = cast_byte(loadByte(S) & ~PF_FIXED);
if (S->fixed)
f->flag |= PF_FIXED; /* signal that code is fixed */
f->maxstacksize = loadByte(S);
src/lutf8lib.c
@@ -10,7 +10,6 @@
#include "lprefix.h"
-#include <assert.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
@@ -47,7 +46,7 @@
** 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
+** entry forces an error for non-ASCII bytes with no continuation
** bytes (count == 0).
*/
static const char *utf8_decode (const char *s, l_uint32 *val, int strict) {
@@ -55,7 +54,7 @@
{~(l_uint32)0, 0x80, 0x800, 0x10000u, 0x200000u, 0x4000000u};
unsigned int c = (unsigned char)s[0];
l_uint32 res = 0; /* final result */
- if (c < 0x80) /* ascii? */
+ if (c < 0x80) /* ASCII? */
res = c;
else {
int count = 0; /* to count number of continuation bytes */
@@ -215,9 +214,10 @@
}
lua_pushinteger(L, posi + 1); /* initial position */
if ((s[posi] & 0x80) != 0) { /* multi-byte character? */
- do {
- posi++;
- } while (iscontp(s + posi + 1)); /* skip to final byte */
+ if (iscont(s[posi]))
+ return luaL_error(L, "initial position is a continuation byte");
+ while (iscontp(s + posi + 1))
+ posi++; /* skip to last continuation byte */
}
/* else one-byte character: final position is the initial one */
lua_pushinteger(L, posi + 1); /* 'posi' now is the final position */
src/lvm.c
@@ -373,6 +373,14 @@
/*
+** Function to be used for 0-terminated string order comparison
+*/
+#if !defined(l_strcoll)
+#define l_strcoll strcoll
+#endif
+
+
+/*
** Compare two strings 'ts1' x 'ts2', returning an integer less-equal-
** -greater than zero if 'ts1' is less-equal-greater than 'ts2'.
** The code is a little tricky because it allows '\0' in the strings
@@ -386,7 +394,7 @@
size_t rl2;
const char *s2 = getlstr(ts2, rl2);
for (;;) { /* for each segment */
- int temp = strcoll(s1, s2);
+ int temp = l_strcoll(s1, s2);
if (temp != 0) /* not equal? */
return temp; /* done */
else { /* strings are equal up to a '\0' */
@@ -573,52 +581,74 @@
*/
int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) {
const TValue *tm;
- if (ttypetag(t1) != ttypetag(t2)) { /* not the same variant? */
- if (ttype(t1) != ttype(t2) || ttype(t1) != LUA_TNUMBER)
- return 0; /* only numbers can be equal with different variants */
- else { /* two numbers with different variants */
- /* One of them is an integer. If the other does not have an
- integer value, they cannot be equal; otherwise, compare their
- integer values. */
- lua_Integer i1, i2;
- return (luaV_tointegerns(t1, &i1, F2Ieq) &&
- luaV_tointegerns(t2, &i2, F2Ieq) &&
- i1 == i2);
+ if (ttype(t1) != ttype(t2)) /* not the same type? */
+ return 0;
+ else if (ttypetag(t1) != ttypetag(t2)) {
+ switch (ttypetag(t1)) {
+ case LUA_VNUMINT: { /* integer == float? */
+ /* integer and float can only be equal if float has an integer
+ value equal to the integer */
+ lua_Integer i2;
+ return (luaV_flttointeger(fltvalue(t2), &i2, F2Ieq) &&
+ ivalue(t1) == i2);
+ }
+ case LUA_VNUMFLT: { /* float == integer? */
+ lua_Integer i1; /* see comment in previous case */
+ return (luaV_flttointeger(fltvalue(t1), &i1, F2Ieq) &&
+ i1 == ivalue(t2));
+ }
+ case LUA_VSHRSTR: case LUA_VLNGSTR: {
+ /* compare two strings with different variants: they can be
+ equal when one string is a short string and the other is
+ an external string */
+ return luaS_eqstr(tsvalue(t1), tsvalue(t2));
+ }
+ default:
+ /* only numbers (integer/float) and strings (long/short) can have
+ equal values with different variants */
+ return 0;
}
}
- /* values have same type and same variant */
- switch (ttypetag(t1)) {
- case LUA_VNIL: case LUA_VFALSE: case LUA_VTRUE: return 1;
- case LUA_VNUMINT: return (ivalue(t1) == ivalue(t2));
- case LUA_VNUMFLT: return luai_numeq(fltvalue(t1), fltvalue(t2));
- case LUA_VLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);
- case LUA_VLCF: return fvalue(t1) == fvalue(t2);
- case LUA_VSHRSTR: return eqshrstr(tsvalue(t1), tsvalue(t2));
- case LUA_VLNGSTR: return luaS_eqlngstr(tsvalue(t1), tsvalue(t2));
- case LUA_VUSERDATA: {
- if (uvalue(t1) == uvalue(t2)) return 1;
- else if (L == NULL) return 0;
- tm = fasttm(L, uvalue(t1)->metatable, TM_EQ);
- if (tm == NULL)
- tm = fasttm(L, uvalue(t2)->metatable, TM_EQ);
- break; /* will try TM */
+ else { /* equal variants */
+ switch (ttypetag(t1)) {
+ case LUA_VNIL: case LUA_VFALSE: case LUA_VTRUE:
+ return 1;
+ case LUA_VNUMINT:
+ return (ivalue(t1) == ivalue(t2));
+ case LUA_VNUMFLT:
+ return (fltvalue(t1) == fltvalue(t2));
+ case LUA_VLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);
+ case LUA_VSHRSTR:
+ return eqshrstr(tsvalue(t1), tsvalue(t2));
+ case LUA_VLNGSTR:
+ return luaS_eqstr(tsvalue(t1), tsvalue(t2));
+ case LUA_VUSERDATA: {
+ if (uvalue(t1) == uvalue(t2)) return 1;
+ else if (L == NULL) return 0;
+ tm = fasttm(L, uvalue(t1)->metatable, TM_EQ);
+ if (tm == NULL)
+ tm = fasttm(L, uvalue(t2)->metatable, TM_EQ);
+ break; /* will try TM */
+ }
+ case LUA_VTABLE: {
+ if (hvalue(t1) == hvalue(t2)) return 1;
+ else if (L == NULL) return 0;
+ tm = fasttm(L, hvalue(t1)->metatable, TM_EQ);
+ if (tm == NULL)
+ tm = fasttm(L, hvalue(t2)->metatable, TM_EQ);
+ break; /* will try TM */
+ }
+ case LUA_VLCF:
+ return (fvalue(t1) == fvalue(t2));
+ default: /* functions and threads */
+ return (gcvalue(t1) == gcvalue(t2));
}
- case LUA_VTABLE: {
- if (hvalue(t1) == hvalue(t2)) return 1;
- else if (L == NULL) return 0;
- tm = fasttm(L, hvalue(t1)->metatable, TM_EQ);
- if (tm == NULL)
- tm = fasttm(L, hvalue(t2)->metatable, TM_EQ);
- break; /* will try TM */
+ if (tm == NULL) /* no TM? */
+ return 0; /* objects are different */
+ else {
+ int tag = luaT_callTMres(L, tm, t1, t2, L->top.p); /* call TM */
+ return !tagisfalse(tag);
}
- default:
- return gcvalue(t1) == gcvalue(t2);
- }
- if (tm == NULL) /* no TM? */
- return 0; /* objects are different */
- else {
- int tag = luaT_callTMres(L, tm, t1, t2, L->top.p); /* call TM */
- return !tagisfalse(tag);
}
}
@@ -627,6 +657,11 @@
#define tostring(L,o) \
(ttisstring(o) || (cvt2str(o) && (luaO_tostring(L, o), 1)))
+/*
+** Check whether object is a short empty string to optimize concatenation.
+** (External strings can be empty too; they will be concatenated like
+** non-empty ones.)
+*/
#define isemptystr(o) (ttisshrstring(o) && tsvalue(o)->shrlen == 0)
/* copy strings in stack from top - n up to top - 1 to buffer */
@@ -661,8 +696,8 @@
setobjs2s(L, top - 2, top - 1); /* result is second op. */
}
else {
- /* at least two non-empty string values; get as many as possible */
- size_t tl = tsslen(tsvalue(s2v(top - 1)));
+ /* at least two string values; get as many as possible */
+ size_t tl = tsslen(tsvalue(s2v(top - 1))); /* total length */
TString *ts;
/* collect total length and number of strings */
for (n = 1; n < total && tostring(L, s2v(top - n - 1)); n++) {
@@ -700,7 +735,7 @@
Table *h = hvalue(rb);
tm = fasttm(L, h->metatable, TM_LEN);
if (tm) break; /* metamethod? break switch to call it */
- setivalue(s2v(ra), l_castU2S(luaH_getn(h))); /* else primitive len */
+ setivalue(s2v(ra), l_castU2S(luaH_getn(L, h))); /* else primitive len */
return;
}
case LUA_VSHRSTR: {
@@ -839,12 +874,6 @@
case OP_EQ: { /* note that 'OP_EQI'/'OP_EQK' cannot yield */
int res = !l_isfalse(s2v(L->top.p - 1));
L->top.p--;
-#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 */
@@ -888,6 +917,10 @@
/*
** {==================================================================
** Macros for arithmetic/bitwise/comparison opcodes in 'luaV_execute'
+**
+** All these macros are to be used exclusively inside the main
+** iterpreter loop (function luaV_execute) and may access directly
+** the local variables of that function (L, i, pc, ci, etc.).
** ===================================================================
*/
@@ -909,17 +942,17 @@
** operation, 'fop' is the float operation.
*/
#define op_arithI(L,iop,fop) { \
- StkId ra = RA(i); \
+ TValue *ra = vRA(i); \
TValue *v1 = vRB(i); \
int imm = GETARG_sC(i); \
if (ttisinteger(v1)) { \
lua_Integer iv1 = ivalue(v1); \
- pc++; setivalue(s2v(ra), iop(L, iv1, imm)); \
+ pc++; setivalue(ra, iop(L, iv1, imm)); \
} \
else if (ttisfloat(v1)) { \
lua_Number nb = fltvalue(v1); \
lua_Number fimm = cast_num(imm); \
- pc++; setfltvalue(s2v(ra), fop(L, nb, fimm)); \
+ pc++; setfltvalue(ra, fop(L, nb, fimm)); \
}}
@@ -930,6 +963,7 @@
#define op_arithf_aux(L,v1,v2,fop) { \
lua_Number n1; lua_Number n2; \
if (tonumberns(v1, n1) && tonumberns(v2, n2)) { \
+ StkId ra = RA(i); \
pc++; setfltvalue(s2v(ra), fop(L, n1, n2)); \
}}
@@ -938,7 +972,6 @@
** Arithmetic operations over floats and others with register operands.
*/
#define op_arithf(L,fop) { \
- StkId ra = RA(i); \
TValue *v1 = vRB(i); \
TValue *v2 = vRC(i); \
op_arithf_aux(L, v1, v2, fop); }
@@ -948,7 +981,6 @@
** Arithmetic operations with K operands for floats.
*/
#define op_arithfK(L,fop) { \
- StkId ra = RA(i); \
TValue *v1 = vRB(i); \
TValue *v2 = KC(i); lua_assert(ttisnumber(v2)); \
op_arithf_aux(L, v1, v2, fop); }
@@ -958,8 +990,8 @@
** Arithmetic operations over integers and floats.
*/
#define op_arith_aux(L,v1,v2,iop,fop) { \
- StkId ra = RA(i); \
if (ttisinteger(v1) && ttisinteger(v2)) { \
+ StkId ra = RA(i); \
lua_Integer i1 = ivalue(v1); lua_Integer i2 = ivalue(v2); \
pc++; setivalue(s2v(ra), iop(L, i1, i2)); \
} \
@@ -988,12 +1020,12 @@
** Bitwise operations with constant operand.
*/
#define op_bitwiseK(L,op) { \
- StkId ra = RA(i); \
TValue *v1 = vRB(i); \
TValue *v2 = KC(i); \
lua_Integer i1; \
lua_Integer i2 = ivalue(v2); \
if (tointegerns(v1, &i1)) { \
+ StkId ra = RA(i); \
pc++; setivalue(s2v(ra), op(i1, i2)); \
}}
@@ -1002,11 +1034,11 @@
** Bitwise operations with register operands.
*/
#define op_bitwise(L,op) { \
- StkId ra = RA(i); \
TValue *v1 = vRB(i); \
TValue *v2 = vRC(i); \
lua_Integer i1; lua_Integer i2; \
if (tointegerns(v1, &i1) && tointegerns(v2, &i2)) { \
+ StkId ra = RA(i); \
pc++; setivalue(s2v(ra), op(i1, i2)); \
}}
@@ -1017,18 +1049,18 @@
** integers.
*/
#define op_order(L,opi,opn,other) { \
- StkId ra = RA(i); \
+ TValue *ra = vRA(i); \
int cond; \
TValue *rb = vRB(i); \
- if (ttisinteger(s2v(ra)) && ttisinteger(rb)) { \
- lua_Integer ia = ivalue(s2v(ra)); \
+ if (ttisinteger(ra) && ttisinteger(rb)) { \
+ lua_Integer ia = ivalue(ra); \
lua_Integer ib = ivalue(rb); \
cond = opi(ia, ib); \
} \
- else if (ttisnumber(s2v(ra)) && ttisnumber(rb)) \
- cond = opn(s2v(ra), rb); \
+ else if (ttisnumber(ra) && ttisnumber(rb)) \
+ cond = opn(ra, rb); \
else \
- Protect(cond = other(L, s2v(ra), rb)); \
+ Protect(cond = other(L, ra, rb)); \
docondjump(); }
@@ -1037,19 +1069,19 @@
** always small enough to have an exact representation as a float.)
*/
#define op_orderI(L,opi,opf,inv,tm) { \
- StkId ra = RA(i); \
+ TValue *ra = vRA(i); \
int cond; \
int im = GETARG_sB(i); \
- if (ttisinteger(s2v(ra))) \
- cond = opi(ivalue(s2v(ra)), im); \
- else if (ttisfloat(s2v(ra))) { \
- lua_Number fa = fltvalue(s2v(ra)); \
+ if (ttisinteger(ra)) \
+ cond = opi(ivalue(ra), im); \
+ else if (ttisfloat(ra)) { \
+ lua_Number fa = fltvalue(ra); \
lua_Number fim = cast_num(im); \
cond = opf(fa, fim); \
} \
else { \
int isf = GETARG_C(i); \
- Protect(cond = luaT_callorderiTM(L, s2v(ra), im, inv, isf, tm)); \
+ Protect(cond = luaT_callorderiTM(L, ra, im, inv, isf, tm)); \
} \
docondjump(); }
@@ -1068,6 +1100,7 @@
#define RA(i) (base+GETARG_A(i))
+#define vRA(i) s2v(RA(i))
#define RB(i) (base+GETARG_B(i))
#define vRB(i) s2v(RB(i))
#define KB(i) (k+GETARG_B(i))
@@ -1108,14 +1141,14 @@
/*
** Correct global 'pc'.
*/
-#define savepc(L) (ci->u.l.savedpc = pc)
+#define savepc(ci) (ci->u.l.savedpc = pc)
/*
** Whenever code can raise errors, the global 'pc' and the global
** 'top' must be correct to report occasional errors.
*/
-#define savestate(L,ci) (savepc(L), L->top.p = ci->top.p)
+#define savestate(L,ci) (savepc(ci), L->top.p = ci->top.p)
/*
@@ -1125,7 +1158,7 @@
#define Protect(exp) (savestate(L,ci), (exp), updatetrap(ci))
/* special version that does not change the top */
-#define ProtectNT(exp) (savepc(L), (exp), updatetrap(ci))
+#define ProtectNT(exp) (savepc(ci), (exp), updatetrap(ci))
/*
** Protect code that can only raise errors. (That is, it cannot change
@@ -1143,7 +1176,7 @@
/* 'c' is the limit of live values in the stack */
#define checkGC(L,c) \
- { luaC_condGC(L, (savepc(L), L->top.p = (c)), \
+ { luaC_condGC(L, (savepc(ci), L->top.p = (c)), \
updatetrap(ci)); \
luai_threadyield(L); }
@@ -1450,23 +1483,23 @@
op_bitwiseK(L, l_bxor);
vmbreak;
}
- vmcase(OP_SHRI) {
+ vmcase(OP_SHLI) {
StkId ra = RA(i);
TValue *rb = vRB(i);
int ic = GETARG_sC(i);
lua_Integer ib;
if (tointegerns(rb, &ib)) {
- pc++; setivalue(s2v(ra), luaV_shiftl(ib, -ic));
+ pc++; setivalue(s2v(ra), luaV_shiftl(ic, ib));
}
vmbreak;
}
- vmcase(OP_SHLI) {
+ vmcase(OP_SHRI) {
StkId ra = RA(i);
TValue *rb = vRB(i);
int ic = GETARG_sC(i);
lua_Integer ib;
if (tointegerns(rb, &ib)) {
- pc++; setivalue(s2v(ra), luaV_shiftl(ic, ib));
+ pc++; setivalue(s2v(ra), luaV_shiftl(ib, -ic));
}
vmbreak;
}
@@ -1512,14 +1545,14 @@
op_bitwise(L, l_bxor);
vmbreak;
}
- vmcase(OP_SHR) {
- op_bitwise(L, luaV_shiftr);
- vmbreak;
- }
vmcase(OP_SHL) {
op_bitwise(L, luaV_shiftl);
vmbreak;
}
+ vmcase(OP_SHR) {
+ op_bitwise(L, luaV_shiftr);
+ vmbreak;
+ }
vmcase(OP_MMBIN) {
StkId ra = RA(i);
Instruction pi = *(pc - 2); /* original arith. expression */
@@ -1692,7 +1725,7 @@
if (b != 0) /* fixed number of arguments? */
L->top.p = ra + b; /* top signals number of arguments */
/* else previous instruction set top */
- savepc(L); /* in case of errors */
+ savepc(ci); /* in case of errors */
if ((newci = luaD_precall(L, ra, nresults)) == NULL)
updatetrap(ci); /* C call; nothing else to be done */
else { /* Lua call: run function in this same C frame */
@@ -1868,7 +1901,7 @@
vmcase(OP_SETLIST) {
StkId ra = RA(i);
unsigned n = cast_uint(GETARG_vB(i));
- unsigned int last = cast_uint(GETARG_vC(i));
+ unsigned last = cast_uint(GETARG_vC(i));
Table *h = hvalue(s2v(ra));
if (n == 0)
n = cast_uint(L->top.p - ra) - 1; /* get up to the top */
@@ -1906,8 +1939,20 @@
Protect(luaT_getvarargs(L, ci, ra, n));
vmbreak;
}
+ vmcase(OP_GETVARG) {
+ StkId ra = RA(i);
+ TValue *rc = vRC(i);
+ luaT_getvararg(ci, ra, rc);
+ vmbreak;
+ }
+ vmcase(OP_ERRNNIL) {
+ TValue *ra = vRA(i);
+ if (!ttisnil(ra))
+ halfProtect(luaG_errnnil(L, cl, GETARG_Bx(i)));
+ vmbreak;
+ }
vmcase(OP_VARARGPREP) {
- ProtectNT(luaT_adjustvarargs(L, GETARG_A(i), ci, cl->p));
+ ProtectNT(luaT_adjustvarargs(L, ci, cl->p));
if (l_unlikely(trap)) { /* previous "Protect" updated trap */
luaD_hookcall(L, ci);
L->oldpc = 1; /* next opcode will be seen as a "new" line */