mirror of
https://github.com/walterschell/Lua.git
synced 2024-11-22 05:04:35 +00:00
Merge pull request #13 from walterschell/feature/5.4.4
Released 2022-01-26
This commit is contained in:
commit
0ab5db21e8
@ -1,5 +1,5 @@
|
|||||||
cmake_minimum_required(VERSION 3.1)
|
cmake_minimum_required(VERSION 3.1)
|
||||||
project(lua LANGUAGES C VERSION 5.4.3)
|
project(lua LANGUAGES C VERSION 5.4.4)
|
||||||
|
|
||||||
option(LUA_SUPPORT_DL "Support dynamic loading of compiled modules" OFF)
|
option(LUA_SUPPORT_DL "Support dynamic loading of compiled modules" OFF)
|
||||||
option(LUA_BUILD_AS_CXX "Build lua as C++" OFF)
|
option(LUA_BUILD_AS_CXX "Build lua as C++" OFF)
|
||||||
@ -20,4 +20,4 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
add_subdirectory(lua-5.4.3)
|
add_subdirectory(lua-5.4.4)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# Lua
|
# Lua
|
||||||
CMake based build of Lua 5.4.3
|
CMake based build of Lua 5.4.4
|
||||||
| Build as C | Build as C++ |
|
| Build as C | Build as C++ |
|
||||||
| --: | --: |
|
| --: | --: |
|
||||||
| ![Build Linux](https://github.com/walterschell/Lua/actions/workflows/build-linux.yml/badge.svg?branch=master) | ![Build Linux as C++](https://github.com/walterschell/Lua/actions/workflows/build-emscripten-cxx.yml/badge.svg?branch=master) |
|
| ![Build Linux](https://github.com/walterschell/Lua/actions/workflows/build-linux.yml/badge.svg?branch=master) | ![Build Linux as C++](https://github.com/walterschell/Lua/actions/workflows/build-emscripten-cxx.yml/badge.svg?branch=master) |
|
||||||
|
@ -46,7 +46,7 @@ TO_MAN= lua.1 luac.1
|
|||||||
|
|
||||||
# Lua version and release.
|
# Lua version and release.
|
||||||
V= 5.4
|
V= 5.4
|
||||||
R= $V.3
|
R= $V.4
|
||||||
|
|
||||||
# Targets start here.
|
# Targets start here.
|
||||||
all: $(PLAT)
|
all: $(PLAT)
|
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
This is Lua 5.4.3, released on 15 Mar 2021.
|
This is Lua 5.4.4, released on 13 Jan 2022.
|
||||||
|
|
||||||
For installation instructions, license details, and
|
For installation instructions, license details, and
|
||||||
further information about Lua, see doc/readme.html.
|
further information about Lua, see doc/readme.html.
|
@ -32,7 +32,7 @@ For a complete introduction to Lua programming, see the book
|
|||||||
|
|
||||||
<P>
|
<P>
|
||||||
<SMALL>
|
<SMALL>
|
||||||
Copyright © 2020–2021 Lua.org, PUC-Rio.
|
Copyright © 2020–2022 Lua.org, PUC-Rio.
|
||||||
Freely available under the terms of the
|
Freely available under the terms of the
|
||||||
<A HREF="http://www.lua.org/license.html">Lua license</A>.
|
<A HREF="http://www.lua.org/license.html">Lua license</A>.
|
||||||
</SMALL>
|
</SMALL>
|
||||||
@ -664,10 +664,10 @@ Freely available under the terms of the
|
|||||||
|
|
||||||
<P CLASS="footer">
|
<P CLASS="footer">
|
||||||
Last update:
|
Last update:
|
||||||
Wed Mar 3 13:04:44 UTC 2021
|
Thu Jan 13 11:32:22 UTC 2022
|
||||||
</P>
|
</P>
|
||||||
<!--
|
<!--
|
||||||
Last change: revised for Lua 5.4.3
|
Last change: revised for Lua 5.4.4
|
||||||
-->
|
-->
|
||||||
|
|
||||||
</BODY>
|
</BODY>
|
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 9.7 KiB |
@ -19,7 +19,7 @@ by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes
|
|||||||
|
|
||||||
<P>
|
<P>
|
||||||
<SMALL>
|
<SMALL>
|
||||||
Copyright © 2020–2021 Lua.org, PUC-Rio.
|
Copyright © 2020–2022 Lua.org, PUC-Rio.
|
||||||
Freely available under the terms of the
|
Freely available under the terms of the
|
||||||
<a href="http://www.lua.org/license.html">Lua license</a>.
|
<a href="http://www.lua.org/license.html">Lua license</a>.
|
||||||
</SMALL>
|
</SMALL>
|
||||||
@ -961,11 +961,8 @@ these marks have no effect.
|
|||||||
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Finalizers cannot yield.
|
Finalizers cannot yield nor run the garbage collector.
|
||||||
Except for that, they can do anything,
|
Because they can run in unpredictable times,
|
||||||
such as raise errors, create new objects,
|
|
||||||
or even run the garbage collector.
|
|
||||||
However, because they can run in unpredictable times,
|
|
||||||
it is good practice to restrict each finalizer
|
it is good practice to restrict each finalizer
|
||||||
to the minimum necessary to properly release
|
to the minimum necessary to properly release
|
||||||
its associated resource.
|
its associated resource.
|
||||||
@ -1636,8 +1633,10 @@ before the adjustment
|
|||||||
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The assignment statement first evaluates all its expressions
|
If a variable is both assigned and read
|
||||||
and only then the assignments are performed.
|
inside a multiple assignment,
|
||||||
|
Lua ensures all reads get the value of the variable
|
||||||
|
before the assignment.
|
||||||
Thus the code
|
Thus the code
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
@ -1661,6 +1660,14 @@ and
|
|||||||
cyclically permutes the values of <code>x</code>, <code>y</code>, and <code>z</code>.
|
cyclically permutes the values of <code>x</code>, <code>y</code>, and <code>z</code>.
|
||||||
|
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Note that this guarantee covers only accesses
|
||||||
|
syntactically inside the assignment statement.
|
||||||
|
If a function or a metamethod called during the assignment
|
||||||
|
changes the value of a variable,
|
||||||
|
Lua gives no guarantees about the order of that access.
|
||||||
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
An assignment to a global name <code>x = val</code>
|
An assignment to a global name <code>x = val</code>
|
||||||
is equivalent to the assignment
|
is equivalent to the assignment
|
||||||
@ -2416,16 +2423,21 @@ character is one byte.)
|
|||||||
<p>
|
<p>
|
||||||
The length operator applied on a table
|
The length operator applied on a table
|
||||||
returns a border in that table.
|
returns a border in that table.
|
||||||
A <em>border</em> in a table <code>t</code> is any natural number
|
A <em>border</em> in a table <code>t</code> is any non-negative integer
|
||||||
that satisfies the following condition:
|
that satisfies the following condition:
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
(border == 0 or t[border] ~= nil) and t[border + 1] == nil
|
(border == 0 or t[border] ~= nil) and
|
||||||
|
(t[border + 1] == nil or border == math.maxinteger)
|
||||||
</pre><p>
|
</pre><p>
|
||||||
In words,
|
In words,
|
||||||
a border is any (natural) index present in the table
|
a border is any positive integer index present in the table
|
||||||
that is followed by an absent index
|
that is followed by an absent index,
|
||||||
(or zero, when index 1 is absent).
|
plus two limit cases:
|
||||||
|
zero, when index 1 is absent;
|
||||||
|
and the maximum value for an integer, when that index is present.
|
||||||
|
Note that keys that are not positive integers
|
||||||
|
do not interfere with borders.
|
||||||
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@ -2436,12 +2448,9 @@ The table <code>{10, 20, 30, nil, 50}</code> has two borders (3 and 5),
|
|||||||
and therefore it is not a sequence.
|
and therefore it is not a sequence.
|
||||||
(The <b>nil</b> at index 4 is called a <em>hole</em>.)
|
(The <b>nil</b> at index 4 is called a <em>hole</em>.)
|
||||||
The table <code>{nil, 20, 30, nil, nil, 60, nil}</code>
|
The table <code>{nil, 20, 30, nil, nil, 60, nil}</code>
|
||||||
has three borders (0, 3, and 6) and three holes
|
has three borders (0, 3, and 6),
|
||||||
(at indices 1, 4, and 5),
|
|
||||||
so it is not a sequence, too.
|
so it is not a sequence, too.
|
||||||
The table <code>{}</code> is a sequence with border 0.
|
The table <code>{}</code> is a sequence with border 0.
|
||||||
Note that non-natural keys do not interfere
|
|
||||||
with whether a table is a sequence.
|
|
||||||
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@ -2459,7 +2468,7 @@ the memory addresses of its non-numeric keys.)
|
|||||||
<p>
|
<p>
|
||||||
The computation of the length of a table
|
The computation of the length of a table
|
||||||
has a guaranteed worst time of <em>O(log n)</em>,
|
has a guaranteed worst time of <em>O(log n)</em>,
|
||||||
where <em>n</em> is the largest natural key in the table.
|
where <em>n</em> is the largest integer key in the table.
|
||||||
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@ -3979,6 +3988,10 @@ For more details about these options,
|
|||||||
see <a href="#pdf-collectgarbage"><code>collectgarbage</code></a>.
|
see <a href="#pdf-collectgarbage"><code>collectgarbage</code></a>.
|
||||||
|
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This function should not be called by a finalizer.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -5933,7 +5946,10 @@ information about a function or an activation record.
|
|||||||
<a href="#lua_getstack"><code>lua_getstack</code></a> fills only the private part
|
<a href="#lua_getstack"><code>lua_getstack</code></a> fills only the private part
|
||||||
of this structure, for later use.
|
of this structure, for later use.
|
||||||
To fill the other fields of <a href="#lua_Debug"><code>lua_Debug</code></a> with useful information,
|
To fill the other fields of <a href="#lua_Debug"><code>lua_Debug</code></a> with useful information,
|
||||||
you must call <a href="#lua_getinfo"><code>lua_getinfo</code></a>.
|
you must call <a href="#lua_getinfo"><code>lua_getinfo</code></a> with an appropriate parameter.
|
||||||
|
(Specifically, to get a field,
|
||||||
|
you must add the letter between parentheses in the field's comment
|
||||||
|
to the parameter <code>what</code> of <a href="#lua_getinfo"><code>lua_getinfo</code></a>.)
|
||||||
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@ -6110,11 +6126,25 @@ you can write the following code:
|
|||||||
<p>
|
<p>
|
||||||
Each character in the string <code>what</code>
|
Each character in the string <code>what</code>
|
||||||
selects some fields of the structure <code>ar</code> to be filled or
|
selects some fields of the structure <code>ar</code> to be filled or
|
||||||
a value to be pushed on the stack:
|
a value to be pushed on the stack.
|
||||||
|
(These characters are also documented in the declaration of
|
||||||
|
the structure <a href="#lua_Debug"><code>lua_Debug</code></a>,
|
||||||
|
between parentheses in the comments following each field.)
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
<li><b>'<code>n</code>': </b> fills in the field <code>name</code> and <code>namewhat</code>;
|
<li><b>'<code>f</code>': </b>
|
||||||
|
pushes onto the stack the function that is
|
||||||
|
running at the given level;
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li><b>'<code>l</code>': </b> fills in the field <code>currentline</code>;
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li><b>'<code>n</code>': </b> fills in the fields <code>name</code> and <code>namewhat</code>;
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li><b>'<code>r</code>': </b> fills in the fields <code>ftransfer</code> and <code>ntransfer</code>;
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li><b>'<code>S</code>': </b>
|
<li><b>'<code>S</code>': </b>
|
||||||
@ -6122,9 +6152,6 @@ fills in the fields <code>source</code>, <code>short_src</code>,
|
|||||||
<code>linedefined</code>, <code>lastlinedefined</code>, and <code>what</code>;
|
<code>linedefined</code>, <code>lastlinedefined</code>, and <code>what</code>;
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li><b>'<code>l</code>': </b> fills in the field <code>currentline</code>;
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li><b>'<code>t</code>': </b> fills in the field <code>istailcall</code>;
|
<li><b>'<code>t</code>': </b> fills in the field <code>istailcall</code>;
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
@ -6132,25 +6159,13 @@ fills in the fields <code>source</code>, <code>short_src</code>,
|
|||||||
<code>nups</code>, <code>nparams</code>, and <code>isvararg</code>;
|
<code>nups</code>, <code>nparams</code>, and <code>isvararg</code>;
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li><b>'<code>f</code>': </b>
|
|
||||||
pushes onto the stack the function that is
|
|
||||||
running at the given level;
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li><b>'<code>L</code>': </b>
|
<li><b>'<code>L</code>': </b>
|
||||||
pushes onto the stack a table whose indices are the
|
pushes onto the stack a table whose indices are
|
||||||
numbers of the lines that are valid on the function.
|
the lines on the function with some associated code,
|
||||||
(A <em>valid line</em> is a line with some associated code,
|
that is, the lines where you can put a break point.
|
||||||
that is, a line where you can put a break point.
|
(Lines with no code include empty lines and comments.)
|
||||||
Non-valid lines include empty lines and comments.)
|
|
||||||
|
|
||||||
|
|
||||||
<p>
|
|
||||||
If this option is given together with option '<code>f</code>',
|
If this option is given together with option '<code>f</code>',
|
||||||
its table is pushed after the function.
|
its table is pushed after the function.
|
||||||
|
|
||||||
|
|
||||||
<p>
|
|
||||||
This is the only option that can raise a memory error.
|
This is the only option that can raise a memory error.
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
@ -6508,7 +6523,7 @@ Adds the byte <code>c</code> to the buffer <code>B</code>
|
|||||||
|
|
||||||
|
|
||||||
<hr><h3><a name="luaL_addgsub"><code>luaL_addgsub</code></a></h3><p>
|
<hr><h3><a name="luaL_addgsub"><code>luaL_addgsub</code></a></h3><p>
|
||||||
<span class="apii">[-0, +0, <em>m</em>]</span>
|
<span class="apii">[-?, +?, <em>m</em>]</span>
|
||||||
<pre>const void luaL_addgsub (luaL_Buffer *B, const char *s,
|
<pre>const void luaL_addgsub (luaL_Buffer *B, const char *s,
|
||||||
const char *p, const char *r);</pre>
|
const char *p, const char *r);</pre>
|
||||||
|
|
||||||
@ -6562,7 +6577,7 @@ to the buffer <code>B</code>
|
|||||||
|
|
||||||
|
|
||||||
<hr><h3><a name="luaL_addvalue"><code>luaL_addvalue</code></a></h3><p>
|
<hr><h3><a name="luaL_addvalue"><code>luaL_addvalue</code></a></h3><p>
|
||||||
<span class="apii">[-1, +?, <em>m</em>]</span>
|
<span class="apii">[-?, +?, <em>m</em>]</span>
|
||||||
<pre>void luaL_addvalue (luaL_Buffer *B);</pre>
|
<pre>void luaL_addvalue (luaL_Buffer *B);</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@ -6716,7 +6731,7 @@ Note that any addition to the buffer may invalidate this address.
|
|||||||
|
|
||||||
|
|
||||||
<hr><h3><a name="luaL_buffinit"><code>luaL_buffinit</code></a></h3><p>
|
<hr><h3><a name="luaL_buffinit"><code>luaL_buffinit</code></a></h3><p>
|
||||||
<span class="apii">[-0, +0, –]</span>
|
<span class="apii">[-0, +?, –]</span>
|
||||||
<pre>void luaL_buffinit (lua_State *L, luaL_Buffer *B);</pre>
|
<pre>void luaL_buffinit (lua_State *L, luaL_Buffer *B);</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@ -6754,7 +6769,7 @@ Equivalent to the sequence
|
|||||||
|
|
||||||
|
|
||||||
<hr><h3><a name="luaL_buffsub"><code>luaL_buffsub</code></a></h3><p>
|
<hr><h3><a name="luaL_buffsub"><code>luaL_buffsub</code></a></h3><p>
|
||||||
<span class="apii">[-0, +0, –]</span>
|
<span class="apii">[-?, +?, –]</span>
|
||||||
<pre>void luaL_buffsub (luaL_Buffer *B, int n);</pre>
|
<pre>void luaL_buffsub (luaL_Buffer *B, int n);</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@ -7557,6 +7572,11 @@ on top of the library table.
|
|||||||
These values are popped from the stack after the registration.
|
These values are popped from the stack after the registration.
|
||||||
|
|
||||||
|
|
||||||
|
<p>
|
||||||
|
A function with a <code>NULL</code> value represents a placeholder,
|
||||||
|
which is filled with <b>false</b>.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -7919,6 +7939,10 @@ See <a href="#2.5">§2.5</a> for more details about garbage collection
|
|||||||
and some of these options.
|
and some of these options.
|
||||||
|
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This function should not be called by a finalizer.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@ -7936,7 +7960,7 @@ to its caller.
|
|||||||
|
|
||||||
<p>
|
<p>
|
||||||
<hr><h3><a name="pdf-error"><code>error (message [, level])</code></a></h3>
|
<hr><h3><a name="pdf-error"><code>error (message [, level])</code></a></h3>
|
||||||
Raises an error (see <a href="#2.3">§2.3</a>) with @{message} as the error object.
|
Raises an error (see <a href="#2.3">§2.3</a>) with <code>message</code> as the error object.
|
||||||
This function never returns.
|
This function never returns.
|
||||||
|
|
||||||
|
|
||||||
@ -8111,9 +8135,8 @@ use a numerical <b>for</b>.)
|
|||||||
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The behavior of <code>next</code> is undefined if,
|
You should not assign any value to a non-existent field in a table
|
||||||
during the traversal,
|
during its traversal.
|
||||||
you assign any value to a non-existent field in the table.
|
|
||||||
You may however modify existing fields.
|
You may however modify existing fields.
|
||||||
In particular, you may set existing fields to nil.
|
In particular, you may set existing fields to nil.
|
||||||
|
|
||||||
@ -8159,7 +8182,7 @@ This means that any error inside <code>f</code> is not propagated;
|
|||||||
instead, <code>pcall</code> catches the error
|
instead, <code>pcall</code> catches the error
|
||||||
and returns a status code.
|
and returns a status code.
|
||||||
Its first result is the status code (a boolean),
|
Its first result is the status code (a boolean),
|
||||||
which is true if the call succeeds without errors.
|
which is <b>true</b> if the call succeeds without errors.
|
||||||
In such case, <code>pcall</code> also returns all results from the call,
|
In such case, <code>pcall</code> also returns all results from the call,
|
||||||
after this first result.
|
after this first result.
|
||||||
In case of any error, <code>pcall</code> returns <b>false</b> plus the error object.
|
In case of any error, <code>pcall</code> returns <b>false</b> plus the error object.
|
||||||
@ -8439,7 +8462,7 @@ an object with type <code>"thread"</code>.
|
|||||||
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Returns true when the coroutine <code>co</code> can yield.
|
Returns <b>true</b> when the coroutine <code>co</code> can yield.
|
||||||
The default for <code>co</code> is the running coroutine.
|
The default for <code>co</code> is the running coroutine.
|
||||||
|
|
||||||
|
|
||||||
@ -8483,7 +8506,7 @@ If there is any error,
|
|||||||
|
|
||||||
<p>
|
<p>
|
||||||
Returns the running coroutine plus a boolean,
|
Returns the running coroutine plus a boolean,
|
||||||
true when the running coroutine is the main one.
|
<b>true</b> when the running coroutine is the main one.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -9021,7 +9044,7 @@ otherwise, it returns <b>fail</b>.
|
|||||||
A third, optional numeric argument <code>init</code> specifies
|
A third, optional numeric argument <code>init</code> specifies
|
||||||
where to start the search;
|
where to start the search;
|
||||||
its default value is 1 and can be negative.
|
its default value is 1 and can be negative.
|
||||||
A value of <b>true</b> as a fourth, optional argument <code>plain</code>
|
A <b>true</b> as a fourth, optional argument <code>plain</code>
|
||||||
turns off the pattern matching facilities,
|
turns off the pattern matching facilities,
|
||||||
so the function does a plain "find substring" operation,
|
so the function does a plain "find substring" operation,
|
||||||
with no characters in <code>pattern</code> being considered magic.
|
with no characters in <code>pattern</code> being considered magic.
|
||||||
@ -9046,8 +9069,10 @@ following the description given in its first argument,
|
|||||||
which must be a string.
|
which must be a string.
|
||||||
The format string follows the same rules as the ISO C function <code>sprintf</code>.
|
The format string follows the same rules as the ISO C function <code>sprintf</code>.
|
||||||
The only differences are that the conversion specifiers and modifiers
|
The only differences are that the conversion specifiers and modifiers
|
||||||
<code>*</code>, <code>h</code>, <code>L</code>, <code>l</code>, and <code>n</code> are not supported
|
<code>F</code>, <code>n</code>, <code>*</code>, <code>h</code>, <code>L</code>, and <code>l</code> are not supported
|
||||||
and that there is an extra specifier, <code>q</code>.
|
and that there is an extra specifier, <code>q</code>.
|
||||||
|
Both width and precision, when present,
|
||||||
|
are limited to two digits.
|
||||||
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@ -9071,7 +9096,7 @@ may produce the string:
|
|||||||
"a string with \"quotes\" and \
|
"a string with \"quotes\" and \
|
||||||
new line"
|
new line"
|
||||||
</pre><p>
|
</pre><p>
|
||||||
This specifier does not support modifiers (flags, width, length).
|
This specifier does not support modifiers (flags, width, precision).
|
||||||
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@ -10362,7 +10387,7 @@ or <b>fail</b> if <code>x</code> is not a number.
|
|||||||
|
|
||||||
<p>
|
<p>
|
||||||
Returns a boolean,
|
Returns a boolean,
|
||||||
true if and only if integer <code>m</code> is below integer <code>n</code> when
|
<b>true</b> if and only if integer <code>m</code> is below integer <code>n</code> when
|
||||||
they are compared as unsigned integers.
|
they are compared as unsigned integers.
|
||||||
|
|
||||||
|
|
||||||
@ -11924,10 +11949,10 @@ and LiteralString, see <a href="#3.1">§3.1</a>.)
|
|||||||
|
|
||||||
<P CLASS="footer">
|
<P CLASS="footer">
|
||||||
Last update:
|
Last update:
|
||||||
Mon Mar 15 13:39:42 UTC 2021
|
Thu Jan 13 11:33:16 UTC 2022
|
||||||
</P>
|
</P>
|
||||||
<!--
|
<!--
|
||||||
Last change: revised for Lua 5.4.3
|
Last change: revised for Lua 5.4.4
|
||||||
-->
|
-->
|
||||||
|
|
||||||
</body></html>
|
</body></html>
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
@ -110,7 +110,7 @@ Here are the details.
|
|||||||
<OL>
|
<OL>
|
||||||
<LI>
|
<LI>
|
||||||
Open a terminal window and move to
|
Open a terminal window and move to
|
||||||
the top-level directory, which is named <TT>lua-5.4.3</TT>.
|
the top-level directory, which is named <TT>lua-5.4.4</TT>.
|
||||||
The <TT>Makefile</TT> there controls both the build process and the installation process.
|
The <TT>Makefile</TT> there controls both the build process and the installation process.
|
||||||
<P>
|
<P>
|
||||||
<LI>
|
<LI>
|
||||||
@ -303,7 +303,7 @@ For details, see
|
|||||||
<A HREF="http://www.lua.org/license.html">this</A>.
|
<A HREF="http://www.lua.org/license.html">this</A>.
|
||||||
|
|
||||||
<BLOCKQUOTE STYLE="padding-bottom: 0em">
|
<BLOCKQUOTE STYLE="padding-bottom: 0em">
|
||||||
Copyright © 1994–2021 Lua.org, PUC-Rio.
|
Copyright © 1994–2022 Lua.org, PUC-Rio.
|
||||||
|
|
||||||
<P>
|
<P>
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
@ -330,10 +330,10 @@ THE SOFTWARE.
|
|||||||
|
|
||||||
<P CLASS="footer">
|
<P CLASS="footer">
|
||||||
Last update:
|
Last update:
|
||||||
Wed Mar 3 10:16:26 UTC 2021
|
Mon Jan 3 09:54:18 UTC 2022
|
||||||
</P>
|
</P>
|
||||||
<!--
|
<!--
|
||||||
Last change: revised for Lua 5.4.3
|
Last change: revised for Lua 5.4.4
|
||||||
-->
|
-->
|
||||||
|
|
||||||
</BODY>
|
</BODY>
|
@ -102,7 +102,7 @@ LUALIB_API lua_State *(luaL_newstate) (void);
|
|||||||
|
|
||||||
LUALIB_API lua_Integer (luaL_len) (lua_State *L, int idx);
|
LUALIB_API lua_Integer (luaL_len) (lua_State *L, int idx);
|
||||||
|
|
||||||
LUALIB_API void luaL_addgsub (luaL_Buffer *b, const char *s,
|
LUALIB_API void (luaL_addgsub) (luaL_Buffer *b, const char *s,
|
||||||
const char *p, const char *r);
|
const char *p, const char *r);
|
||||||
LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s,
|
LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s,
|
||||||
const char *p, const char *r);
|
const char *p, const char *r);
|
||||||
@ -154,6 +154,14 @@ LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname,
|
|||||||
#define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL)
|
#define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Perform arithmetic operations on lua_Integer values with wrap-around
|
||||||
|
** semantics, as the Lua core does.
|
||||||
|
*/
|
||||||
|
#define luaL_intop(op,v1,v2) \
|
||||||
|
((lua_Integer)((lua_Unsigned)(v1) op (lua_Unsigned)(v2)))
|
||||||
|
|
||||||
|
|
||||||
/* push the value used to represent failure/error */
|
/* push the value used to represent failure/error */
|
||||||
#define luaL_pushfail(L) lua_pushnil(L)
|
#define luaL_pushfail(L) lua_pushnil(L)
|
||||||
|
|
@ -18,14 +18,14 @@
|
|||||||
|
|
||||||
#define LUA_VERSION_MAJOR "5"
|
#define LUA_VERSION_MAJOR "5"
|
||||||
#define LUA_VERSION_MINOR "4"
|
#define LUA_VERSION_MINOR "4"
|
||||||
#define LUA_VERSION_RELEASE "3"
|
#define LUA_VERSION_RELEASE "4"
|
||||||
|
|
||||||
#define LUA_VERSION_NUM 504
|
#define LUA_VERSION_NUM 504
|
||||||
#define LUA_VERSION_RELEASE_NUM (LUA_VERSION_NUM * 100 + 0)
|
#define LUA_VERSION_RELEASE_NUM (LUA_VERSION_NUM * 100 + 4)
|
||||||
|
|
||||||
#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
|
#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
|
||||||
#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE
|
#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE
|
||||||
#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2021 Lua.org, PUC-Rio"
|
#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2022 Lua.org, PUC-Rio"
|
||||||
#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes"
|
#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes"
|
||||||
|
|
||||||
|
|
||||||
@ -492,7 +492,7 @@ struct lua_Debug {
|
|||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* Copyright (C) 1994-2021 Lua.org, PUC-Rio.
|
* Copyright (C) 1994-2022 Lua.org, PUC-Rio.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
* a copy of this software and associated documentation files (the
|
* a copy of this software and associated documentation files (the
|
@ -485,7 +485,6 @@
|
|||||||
@@ LUA_MAXINTEGER is the maximum value for a LUA_INTEGER.
|
@@ LUA_MAXINTEGER is the maximum value for a LUA_INTEGER.
|
||||||
@@ LUA_MININTEGER is the minimum value for a LUA_INTEGER.
|
@@ LUA_MININTEGER is the minimum value for a LUA_INTEGER.
|
||||||
@@ LUA_MAXUNSIGNED is the maximum value for a LUA_UNSIGNED.
|
@@ LUA_MAXUNSIGNED is the maximum value for a LUA_UNSIGNED.
|
||||||
@@ LUA_UNSIGNEDBITS is the number of bits in a LUA_UNSIGNED.
|
|
||||||
@@ lua_integer2str converts an integer to a string.
|
@@ lua_integer2str converts an integer to a string.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -506,9 +505,6 @@
|
|||||||
#define LUA_UNSIGNED unsigned LUAI_UACINT
|
#define LUA_UNSIGNED unsigned LUAI_UACINT
|
||||||
|
|
||||||
|
|
||||||
#define LUA_UNSIGNEDBITS (sizeof(LUA_UNSIGNED) * CHAR_BIT)
|
|
||||||
|
|
||||||
|
|
||||||
/* now the variable definitions */
|
/* now the variable definitions */
|
||||||
|
|
||||||
#if LUA_INT_TYPE == LUA_INT_INT /* { int */
|
#if LUA_INT_TYPE == LUA_INT_INT /* { int */
|
@ -79,7 +79,7 @@ echo:
|
|||||||
@echo "PLAT= $(PLAT)"
|
@echo "PLAT= $(PLAT)"
|
||||||
@echo "CC= $(CC)"
|
@echo "CC= $(CC)"
|
||||||
@echo "CFLAGS= $(CFLAGS)"
|
@echo "CFLAGS= $(CFLAGS)"
|
||||||
@echo "LDFLAGS= $(SYSLDFLAGS)"
|
@echo "LDFLAGS= $(LDFLAGS)"
|
||||||
@echo "LIBS= $(LIBS)"
|
@echo "LIBS= $(LIBS)"
|
||||||
@echo "AR= $(AR)"
|
@echo "AR= $(AR)"
|
||||||
@echo "RANLIB= $(RANLIB)"
|
@echo "RANLIB= $(RANLIB)"
|
@ -53,6 +53,10 @@ const char lua_ident[] =
|
|||||||
#define isupvalue(i) ((i) < LUA_REGISTRYINDEX)
|
#define isupvalue(i) ((i) < LUA_REGISTRYINDEX)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Convert an acceptable index to a pointer to its respective value.
|
||||||
|
** Non-valid indices return the special nil value 'G(L)->nilvalue'.
|
||||||
|
*/
|
||||||
static TValue *index2value (lua_State *L, int idx) {
|
static TValue *index2value (lua_State *L, int idx) {
|
||||||
CallInfo *ci = L->ci;
|
CallInfo *ci = L->ci;
|
||||||
if (idx > 0) {
|
if (idx > 0) {
|
||||||
@ -70,22 +74,28 @@ static TValue *index2value (lua_State *L, int idx) {
|
|||||||
else { /* upvalues */
|
else { /* upvalues */
|
||||||
idx = LUA_REGISTRYINDEX - idx;
|
idx = LUA_REGISTRYINDEX - idx;
|
||||||
api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large");
|
api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large");
|
||||||
if (ttislcf(s2v(ci->func))) /* light C function? */
|
if (ttisCclosure(s2v(ci->func))) { /* C closure? */
|
||||||
return &G(L)->nilvalue; /* it has no upvalues */
|
|
||||||
else {
|
|
||||||
CClosure *func = clCvalue(s2v(ci->func));
|
CClosure *func = clCvalue(s2v(ci->func));
|
||||||
return (idx <= func->nupvalues) ? &func->upvalue[idx-1]
|
return (idx <= func->nupvalues) ? &func->upvalue[idx-1]
|
||||||
: &G(L)->nilvalue;
|
: &G(L)->nilvalue;
|
||||||
}
|
}
|
||||||
|
else { /* light C function or Lua function (through a hook)?) */
|
||||||
|
api_check(L, ttislcf(s2v(ci->func)), "caller not a C function");
|
||||||
|
return &G(L)->nilvalue; /* no upvalues */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static StkId index2stack (lua_State *L, int idx) {
|
|
||||||
|
/*
|
||||||
|
** Convert a valid actual index (not a pseudo-index) to its address.
|
||||||
|
*/
|
||||||
|
l_sinline StkId index2stack (lua_State *L, int idx) {
|
||||||
CallInfo *ci = L->ci;
|
CallInfo *ci = L->ci;
|
||||||
if (idx > 0) {
|
if (idx > 0) {
|
||||||
StkId o = ci->func + idx;
|
StkId o = ci->func + idx;
|
||||||
api_check(L, o < L->top, "unacceptable index");
|
api_check(L, o < L->top, "invalid index");
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
else { /* non-positive index */
|
else { /* non-positive index */
|
||||||
@ -218,7 +228,7 @@ LUA_API void lua_closeslot (lua_State *L, int idx) {
|
|||||||
** Note that we move(copy) only the value inside the stack.
|
** Note that we move(copy) only the value inside the stack.
|
||||||
** (We do not move additional fields that may exist.)
|
** (We do not move additional fields that may exist.)
|
||||||
*/
|
*/
|
||||||
static void reverse (lua_State *L, StkId from, StkId to) {
|
l_sinline void reverse (lua_State *L, StkId from, StkId to) {
|
||||||
for (; from < to; from++, to--) {
|
for (; from < to; from++, to--) {
|
||||||
TValue temp;
|
TValue temp;
|
||||||
setobj(L, &temp, s2v(from));
|
setobj(L, &temp, s2v(from));
|
||||||
@ -438,7 +448,7 @@ LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void *touserdata (const TValue *o) {
|
l_sinline void *touserdata (const TValue *o) {
|
||||||
switch (ttype(o)) {
|
switch (ttype(o)) {
|
||||||
case LUA_TUSERDATA: return getudatamem(uvalue(o));
|
case LUA_TUSERDATA: return getudatamem(uvalue(o));
|
||||||
case LUA_TLIGHTUSERDATA: return pvalue(o);
|
case LUA_TLIGHTUSERDATA: return pvalue(o);
|
||||||
@ -630,7 +640,7 @@ LUA_API int lua_pushthread (lua_State *L) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
static int auxgetstr (lua_State *L, const TValue *t, const char *k) {
|
l_sinline int auxgetstr (lua_State *L, const TValue *t, const char *k) {
|
||||||
const TValue *slot;
|
const TValue *slot;
|
||||||
TString *str = luaS_new(L, k);
|
TString *str = luaS_new(L, k);
|
||||||
if (luaV_fastget(L, t, str, slot, luaH_getstr)) {
|
if (luaV_fastget(L, t, str, slot, luaH_getstr)) {
|
||||||
@ -705,7 +715,7 @@ LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int finishrawget (lua_State *L, const TValue *val) {
|
l_sinline int finishrawget (lua_State *L, const TValue *val) {
|
||||||
if (isempty(val)) /* avoid copying empty items to the stack */
|
if (isempty(val)) /* avoid copying empty items to the stack */
|
||||||
setnilvalue(s2v(L->top));
|
setnilvalue(s2v(L->top));
|
||||||
else
|
else
|
||||||
@ -1126,18 +1136,19 @@ LUA_API int lua_status (lua_State *L) {
|
|||||||
LUA_API int lua_gc (lua_State *L, int what, ...) {
|
LUA_API int lua_gc (lua_State *L, int what, ...) {
|
||||||
va_list argp;
|
va_list argp;
|
||||||
int res = 0;
|
int res = 0;
|
||||||
global_State *g;
|
global_State *g = G(L);
|
||||||
|
if (g->gcstp & GCSTPGC) /* internal stop? */
|
||||||
|
return -1; /* all options are invalid when stopped */
|
||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
g = G(L);
|
|
||||||
va_start(argp, what);
|
va_start(argp, what);
|
||||||
switch (what) {
|
switch (what) {
|
||||||
case LUA_GCSTOP: {
|
case LUA_GCSTOP: {
|
||||||
g->gcrunning = 0;
|
g->gcstp = GCSTPUSR; /* stopped by the user */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LUA_GCRESTART: {
|
case LUA_GCRESTART: {
|
||||||
luaE_setdebt(g, 0);
|
luaE_setdebt(g, 0);
|
||||||
g->gcrunning = 1;
|
g->gcstp = 0; /* (GCSTPGC must be already zero here) */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LUA_GCCOLLECT: {
|
case LUA_GCCOLLECT: {
|
||||||
@ -1156,8 +1167,8 @@ LUA_API int lua_gc (lua_State *L, int what, ...) {
|
|||||||
case LUA_GCSTEP: {
|
case LUA_GCSTEP: {
|
||||||
int data = va_arg(argp, int);
|
int data = va_arg(argp, int);
|
||||||
l_mem debt = 1; /* =1 to signal that it did an actual step */
|
l_mem debt = 1; /* =1 to signal that it did an actual step */
|
||||||
lu_byte oldrunning = g->gcrunning;
|
lu_byte oldstp = g->gcstp;
|
||||||
g->gcrunning = 1; /* allow GC to run */
|
g->gcstp = 0; /* allow GC to run (GCSTPGC must be zero here) */
|
||||||
if (data == 0) {
|
if (data == 0) {
|
||||||
luaE_setdebt(g, 0); /* do a basic step */
|
luaE_setdebt(g, 0); /* do a basic step */
|
||||||
luaC_step(L);
|
luaC_step(L);
|
||||||
@ -1167,7 +1178,7 @@ LUA_API int lua_gc (lua_State *L, int what, ...) {
|
|||||||
luaE_setdebt(g, debt);
|
luaE_setdebt(g, debt);
|
||||||
luaC_checkGC(L);
|
luaC_checkGC(L);
|
||||||
}
|
}
|
||||||
g->gcrunning = oldrunning; /* restore previous state */
|
g->gcstp = oldstp; /* restore previous state */
|
||||||
if (debt > 0 && g->gcstate == GCSpause) /* end of cycle? */
|
if (debt > 0 && g->gcstate == GCSpause) /* end of cycle? */
|
||||||
res = 1; /* signal it */
|
res = 1; /* signal it */
|
||||||
break;
|
break;
|
||||||
@ -1185,7 +1196,7 @@ LUA_API int lua_gc (lua_State *L, int what, ...) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LUA_GCISRUNNING: {
|
case LUA_GCISRUNNING: {
|
||||||
res = g->gcrunning;
|
res = gcrunning(g);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LUA_GCGEN: {
|
case LUA_GCGEN: {
|
@ -881,6 +881,7 @@ LUALIB_API lua_Integer luaL_len (lua_State *L, int idx) {
|
|||||||
|
|
||||||
|
|
||||||
LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) {
|
LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) {
|
||||||
|
idx = lua_absindex(L,idx);
|
||||||
if (luaL_callmeta(L, idx, "__tostring")) { /* metafield? */
|
if (luaL_callmeta(L, idx, "__tostring")) { /* metafield? */
|
||||||
if (!lua_isstring(L, -1))
|
if (!lua_isstring(L, -1))
|
||||||
luaL_error(L, "'__tostring' must return a string");
|
luaL_error(L, "'__tostring' must return a string");
|
@ -182,12 +182,20 @@ static int luaB_rawset (lua_State *L) {
|
|||||||
|
|
||||||
|
|
||||||
static int pushmode (lua_State *L, int oldmode) {
|
static int pushmode (lua_State *L, int oldmode) {
|
||||||
lua_pushstring(L, (oldmode == LUA_GCINC) ? "incremental"
|
if (oldmode == -1)
|
||||||
: "generational");
|
luaL_pushfail(L); /* invalid call to 'lua_gc' */
|
||||||
|
else
|
||||||
|
lua_pushstring(L, (oldmode == LUA_GCINC) ? "incremental"
|
||||||
|
: "generational");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** check whether call to 'lua_gc' was valid (not inside a finalizer)
|
||||||
|
*/
|
||||||
|
#define checkvalres(res) { if (res == -1) break; }
|
||||||
|
|
||||||
static int luaB_collectgarbage (lua_State *L) {
|
static int luaB_collectgarbage (lua_State *L) {
|
||||||
static const char *const opts[] = {"stop", "restart", "collect",
|
static const char *const opts[] = {"stop", "restart", "collect",
|
||||||
"count", "step", "setpause", "setstepmul",
|
"count", "step", "setpause", "setstepmul",
|
||||||
@ -200,12 +208,14 @@ static int luaB_collectgarbage (lua_State *L) {
|
|||||||
case LUA_GCCOUNT: {
|
case LUA_GCCOUNT: {
|
||||||
int k = lua_gc(L, o);
|
int k = lua_gc(L, o);
|
||||||
int b = lua_gc(L, LUA_GCCOUNTB);
|
int b = lua_gc(L, LUA_GCCOUNTB);
|
||||||
|
checkvalres(k);
|
||||||
lua_pushnumber(L, (lua_Number)k + ((lua_Number)b/1024));
|
lua_pushnumber(L, (lua_Number)k + ((lua_Number)b/1024));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
case LUA_GCSTEP: {
|
case LUA_GCSTEP: {
|
||||||
int step = (int)luaL_optinteger(L, 2, 0);
|
int step = (int)luaL_optinteger(L, 2, 0);
|
||||||
int res = lua_gc(L, o, step);
|
int res = lua_gc(L, o, step);
|
||||||
|
checkvalres(res);
|
||||||
lua_pushboolean(L, res);
|
lua_pushboolean(L, res);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -213,11 +223,13 @@ static int luaB_collectgarbage (lua_State *L) {
|
|||||||
case LUA_GCSETSTEPMUL: {
|
case LUA_GCSETSTEPMUL: {
|
||||||
int p = (int)luaL_optinteger(L, 2, 0);
|
int p = (int)luaL_optinteger(L, 2, 0);
|
||||||
int previous = lua_gc(L, o, p);
|
int previous = lua_gc(L, o, p);
|
||||||
|
checkvalres(previous);
|
||||||
lua_pushinteger(L, previous);
|
lua_pushinteger(L, previous);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
case LUA_GCISRUNNING: {
|
case LUA_GCISRUNNING: {
|
||||||
int res = lua_gc(L, o);
|
int res = lua_gc(L, o);
|
||||||
|
checkvalres(res);
|
||||||
lua_pushboolean(L, res);
|
lua_pushboolean(L, res);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -234,10 +246,13 @@ static int luaB_collectgarbage (lua_State *L) {
|
|||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
int res = lua_gc(L, o);
|
int res = lua_gc(L, o);
|
||||||
|
checkvalres(res);
|
||||||
lua_pushinteger(L, res);
|
lua_pushinteger(L, res);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
luaL_pushfail(L); /* invalid call (inside a finalizer) */
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -261,6 +276,11 @@ static int luaB_next (lua_State *L) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int pairscont (lua_State *L, int status, lua_KContext k) {
|
||||||
|
(void)L; (void)status; (void)k; /* unused */
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
static int luaB_pairs (lua_State *L) {
|
static int luaB_pairs (lua_State *L) {
|
||||||
luaL_checkany(L, 1);
|
luaL_checkany(L, 1);
|
||||||
if (luaL_getmetafield(L, 1, "__pairs") == LUA_TNIL) { /* no metamethod? */
|
if (luaL_getmetafield(L, 1, "__pairs") == LUA_TNIL) { /* no metamethod? */
|
||||||
@ -270,7 +290,7 @@ static int luaB_pairs (lua_State *L) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
lua_pushvalue(L, 1); /* argument 'self' to metamethod */
|
lua_pushvalue(L, 1); /* argument 'self' to metamethod */
|
||||||
lua_call(L, 1, 3); /* get 3 values from metamethod */
|
lua_callk(L, 1, 3, 0, pairscont); /* get 3 values from metamethod */
|
||||||
}
|
}
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
@ -280,7 +300,8 @@ static int luaB_pairs (lua_State *L) {
|
|||||||
** Traversal function for 'ipairs'
|
** Traversal function for 'ipairs'
|
||||||
*/
|
*/
|
||||||
static int ipairsaux (lua_State *L) {
|
static int ipairsaux (lua_State *L) {
|
||||||
lua_Integer i = luaL_checkinteger(L, 2) + 1;
|
lua_Integer i = luaL_checkinteger(L, 2);
|
||||||
|
i = luaL_intop(+, i, 1);
|
||||||
lua_pushinteger(L, i);
|
lua_pushinteger(L, i);
|
||||||
return (lua_geti(L, 1, i) == LUA_TNIL) ? 1 : 2;
|
return (lua_geti(L, 1, i) == LUA_TNIL) ? 1 : 2;
|
||||||
}
|
}
|
@ -10,6 +10,7 @@
|
|||||||
#include "lprefix.h"
|
#include "lprefix.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include <float.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -580,24 +581,41 @@ static int stringK (FuncState *fs, TString *s) {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
** Add an integer to list of constants and return its index.
|
** Add an integer to list of constants and return its index.
|
||||||
** Integers use userdata as keys to avoid collision with floats with
|
|
||||||
** same value; conversion to 'void*' is used only for hashing, so there
|
|
||||||
** are no "precision" problems.
|
|
||||||
*/
|
*/
|
||||||
static int luaK_intK (FuncState *fs, lua_Integer n) {
|
static int luaK_intK (FuncState *fs, lua_Integer n) {
|
||||||
TValue k, o;
|
TValue o;
|
||||||
setpvalue(&k, cast_voidp(cast_sizet(n)));
|
|
||||||
setivalue(&o, n);
|
setivalue(&o, n);
|
||||||
return addk(fs, &k, &o);
|
return addk(fs, &o, &o); /* use integer itself as key */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Add a float to list of constants and return its index.
|
** 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
|
||||||
|
** power-of-two fraction that is still significant in its scale.
|
||||||
|
** For doubles, that would be 1/2^52.
|
||||||
|
** (This method is not bulletproof: there may be another float
|
||||||
|
** with that value, and for floats larger than 2^53 the result is
|
||||||
|
** still an integer. At worst, this only wastes an entry with
|
||||||
|
** a duplicate.)
|
||||||
*/
|
*/
|
||||||
static int luaK_numberK (FuncState *fs, lua_Number r) {
|
static int luaK_numberK (FuncState *fs, lua_Number r) {
|
||||||
TValue o;
|
TValue o;
|
||||||
|
lua_Integer ik;
|
||||||
setfltvalue(&o, r);
|
setfltvalue(&o, r);
|
||||||
return addk(fs, &o, &o); /* use number itself as key */
|
if (!luaV_flttointeger(r, &ik, F2Ieq)) /* not an integral value? */
|
||||||
|
return addk(fs, &o, &o); /* use number itself as key */
|
||||||
|
else { /* must build an alternative key */
|
||||||
|
const int nbm = l_floatatt(MANT_DIG);
|
||||||
|
const lua_Number q = l_mathop(ldexp)(l_mathop(1.0), -nbm + 1);
|
||||||
|
const lua_Number k = (ik == 0) ? q : r + r*q; /* new key */
|
||||||
|
TValue kv;
|
||||||
|
setfltvalue(&kv, k);
|
||||||
|
/* result is not an integral value, unless value is too large */
|
||||||
|
lua_assert(!luaV_flttointeger(k, &ik, F2Ieq) ||
|
||||||
|
l_mathop(fabs)(r) >= l_mathop(1e6));
|
||||||
|
return addk(fs, &kv, &o);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -78,7 +78,7 @@ static int luaB_auxwrap (lua_State *L) {
|
|||||||
if (stat != LUA_OK && stat != LUA_YIELD) { /* error in the coroutine? */
|
if (stat != LUA_OK && stat != LUA_YIELD) { /* error in the coroutine? */
|
||||||
stat = lua_resetthread(co); /* close its tbc variables */
|
stat = lua_resetthread(co); /* close its tbc variables */
|
||||||
lua_assert(stat != LUA_OK);
|
lua_assert(stat != LUA_OK);
|
||||||
lua_xmove(co, L, 1); /* copy error message */
|
lua_xmove(co, L, 1); /* move error message to the caller */
|
||||||
}
|
}
|
||||||
if (stat != LUA_ERRMEM && /* not a memory error and ... */
|
if (stat != LUA_ERRMEM && /* not a memory error and ... */
|
||||||
lua_type(L, -1) == LUA_TSTRING) { /* ... error object is a string? */
|
lua_type(L, -1) == LUA_TSTRING) { /* ... error object is a string? */
|
||||||
@ -179,7 +179,7 @@ static int luaB_close (lua_State *L) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
lua_pushboolean(L, 0);
|
lua_pushboolean(L, 0);
|
||||||
lua_xmove(co, L, 1); /* copy error message */
|
lua_xmove(co, L, 1); /* move error message */
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -34,8 +34,8 @@
|
|||||||
#define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_VCCL)
|
#define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_VCCL)
|
||||||
|
|
||||||
|
|
||||||
static const char *funcnamefromcode (lua_State *L, CallInfo *ci,
|
static const char *funcnamefromcall (lua_State *L, CallInfo *ci,
|
||||||
const char **name);
|
const char **name);
|
||||||
|
|
||||||
|
|
||||||
static int currentpc (CallInfo *ci) {
|
static int currentpc (CallInfo *ci) {
|
||||||
@ -64,7 +64,7 @@ static int getbaseline (const Proto *f, int pc, int *basepc) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int i = cast_uint(pc) / MAXIWTHABS - 1; /* get an estimate */
|
int i = cast_uint(pc) / MAXIWTHABS - 1; /* get an estimate */
|
||||||
/* estimate must be a lower bond of the correct base */
|
/* estimate must be a lower bound of the correct base */
|
||||||
lua_assert(i < 0 ||
|
lua_assert(i < 0 ||
|
||||||
(i < f->sizeabslineinfo && f->abslineinfo[i].pc <= pc));
|
(i < f->sizeabslineinfo && f->abslineinfo[i].pc <= pc));
|
||||||
while (i + 1 < f->sizeabslineinfo && pc >= f->abslineinfo[i + 1].pc)
|
while (i + 1 < f->sizeabslineinfo && pc >= f->abslineinfo[i + 1].pc)
|
||||||
@ -301,7 +301,14 @@ static void collectvalidlines (lua_State *L, Closure *f) {
|
|||||||
sethvalue2s(L, L->top, t); /* push it on stack */
|
sethvalue2s(L, L->top, t); /* push it on stack */
|
||||||
api_incr_top(L);
|
api_incr_top(L);
|
||||||
setbtvalue(&v); /* boolean 'true' to be the value of all indices */
|
setbtvalue(&v); /* boolean 'true' to be the value of all indices */
|
||||||
for (i = 0; i < p->sizelineinfo; i++) { /* for all instructions */
|
if (!p->is_vararg) /* regular function? */
|
||||||
|
i = 0; /* consider all instructions */
|
||||||
|
else { /* vararg function */
|
||||||
|
lua_assert(GET_OPCODE(p->code[0]) == OP_VARARGPREP);
|
||||||
|
currentline = nextline(p, currentline, 0);
|
||||||
|
i = 1; /* skip first instruction (OP_VARARGPREP) */
|
||||||
|
}
|
||||||
|
for (; i < p->sizelineinfo; i++) { /* for each instruction */
|
||||||
currentline = nextline(p, currentline, i); /* get its line */
|
currentline = nextline(p, currentline, i); /* get its line */
|
||||||
luaH_setint(L, t, currentline, &v); /* table[line] = true */
|
luaH_setint(L, t, currentline, &v); /* table[line] = true */
|
||||||
}
|
}
|
||||||
@ -310,15 +317,9 @@ static void collectvalidlines (lua_State *L, Closure *f) {
|
|||||||
|
|
||||||
|
|
||||||
static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {
|
static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {
|
||||||
if (ci == NULL) /* no 'ci'? */
|
/* calling function is a known function? */
|
||||||
return NULL; /* no info */
|
if (ci != NULL && !(ci->callstatus & CIST_TAIL))
|
||||||
else if (ci->callstatus & CIST_FIN) { /* is this a finalizer? */
|
return funcnamefromcall(L, ci->previous, name);
|
||||||
*name = "__gc";
|
|
||||||
return "metamethod"; /* report it as such */
|
|
||||||
}
|
|
||||||
/* calling function is a known Lua function? */
|
|
||||||
else if (!(ci->callstatus & CIST_TAIL) && isLua(ci->previous))
|
|
||||||
return funcnamefromcode(L, ci->previous, name);
|
|
||||||
else return NULL; /* no way to find a name */
|
else return NULL; /* no way to find a name */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -590,16 +591,10 @@ static const char *getobjname (const Proto *p, int lastpc, int reg,
|
|||||||
** Returns what the name is (e.g., "for iterator", "method",
|
** Returns what the name is (e.g., "for iterator", "method",
|
||||||
** "metamethod") and sets '*name' to point to the name.
|
** "metamethod") and sets '*name' to point to the name.
|
||||||
*/
|
*/
|
||||||
static const char *funcnamefromcode (lua_State *L, CallInfo *ci,
|
static const char *funcnamefromcode (lua_State *L, const Proto *p,
|
||||||
const char **name) {
|
int pc, const char **name) {
|
||||||
TMS tm = (TMS)0; /* (initial value avoids warnings) */
|
TMS tm = (TMS)0; /* (initial value avoids warnings) */
|
||||||
const Proto *p = ci_func(ci)->p; /* calling function */
|
|
||||||
int pc = currentpc(ci); /* calling instruction index */
|
|
||||||
Instruction i = p->code[pc]; /* calling instruction */
|
Instruction i = p->code[pc]; /* calling instruction */
|
||||||
if (ci->callstatus & CIST_HOOKED) { /* was it called inside a hook? */
|
|
||||||
*name = "?";
|
|
||||||
return "hook";
|
|
||||||
}
|
|
||||||
switch (GET_OPCODE(i)) {
|
switch (GET_OPCODE(i)) {
|
||||||
case OP_CALL:
|
case OP_CALL:
|
||||||
case OP_TAILCALL:
|
case OP_TAILCALL:
|
||||||
@ -636,6 +631,26 @@ static const char *funcnamefromcode (lua_State *L, CallInfo *ci,
|
|||||||
return "metamethod";
|
return "metamethod";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Try to find a name for a function based on how it was called.
|
||||||
|
*/
|
||||||
|
static const char *funcnamefromcall (lua_State *L, CallInfo *ci,
|
||||||
|
const char **name) {
|
||||||
|
if (ci->callstatus & CIST_HOOKED) { /* was it called inside a hook? */
|
||||||
|
*name = "?";
|
||||||
|
return "hook";
|
||||||
|
}
|
||||||
|
else if (ci->callstatus & CIST_FIN) { /* was it called as a finalizer? */
|
||||||
|
*name = "__gc";
|
||||||
|
return "metamethod"; /* report it as such */
|
||||||
|
}
|
||||||
|
else if (isLua(ci))
|
||||||
|
return funcnamefromcode(L, ci_func(ci)->p, currentpc(ci), name);
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* }====================================================== */
|
/* }====================================================== */
|
||||||
|
|
||||||
|
|
||||||
@ -675,9 +690,21 @@ static const char *getupvalname (CallInfo *ci, const TValue *o,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const char *formatvarinfo (lua_State *L, const char *kind,
|
||||||
|
const char *name) {
|
||||||
|
if (kind == NULL)
|
||||||
|
return ""; /* no information */
|
||||||
|
else
|
||||||
|
return luaO_pushfstring(L, " (%s '%s')", kind, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Build a string with a "description" for the value 'o', such as
|
||||||
|
** "variable 'x'" or "upvalue 'y'".
|
||||||
|
*/
|
||||||
static const char *varinfo (lua_State *L, const TValue *o) {
|
static const char *varinfo (lua_State *L, const TValue *o) {
|
||||||
const char *name = NULL; /* to avoid warnings */
|
|
||||||
CallInfo *ci = L->ci;
|
CallInfo *ci = L->ci;
|
||||||
|
const char *name = NULL; /* to avoid warnings */
|
||||||
const char *kind = NULL;
|
const char *kind = NULL;
|
||||||
if (isLua(ci)) {
|
if (isLua(ci)) {
|
||||||
kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */
|
kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */
|
||||||
@ -685,26 +712,40 @@ static const char *varinfo (lua_State *L, const TValue *o) {
|
|||||||
kind = getobjname(ci_func(ci)->p, currentpc(ci),
|
kind = getobjname(ci_func(ci)->p, currentpc(ci),
|
||||||
cast_int(cast(StkId, o) - (ci->func + 1)), &name);
|
cast_int(cast(StkId, o) - (ci->func + 1)), &name);
|
||||||
}
|
}
|
||||||
return (kind) ? luaO_pushfstring(L, " (%s '%s')", kind, name) : "";
|
return formatvarinfo(L, kind, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
|
/*
|
||||||
|
** Raise a type error
|
||||||
|
*/
|
||||||
|
static l_noret typeerror (lua_State *L, const TValue *o, const char *op,
|
||||||
|
const char *extra) {
|
||||||
const char *t = luaT_objtypename(L, o);
|
const char *t = luaT_objtypename(L, o);
|
||||||
luaG_runerror(L, "attempt to %s a %s value%s", op, t, varinfo(L, o));
|
luaG_runerror(L, "attempt to %s a %s value%s", op, t, extra);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Raise a type error with "standard" information about the faulty
|
||||||
|
** object 'o' (using 'varinfo').
|
||||||
|
*/
|
||||||
|
l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
|
||||||
|
typeerror(L, o, op, varinfo(L, o));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Raise an error for calling a non-callable object. Try to find a name
|
||||||
|
** for the object based on how it was called ('funcnamefromcall'); if it
|
||||||
|
** cannot get a name there, try 'varinfo'.
|
||||||
|
*/
|
||||||
l_noret luaG_callerror (lua_State *L, const TValue *o) {
|
l_noret luaG_callerror (lua_State *L, const TValue *o) {
|
||||||
CallInfo *ci = L->ci;
|
CallInfo *ci = L->ci;
|
||||||
const char *name = NULL; /* to avoid warnings */
|
const char *name = NULL; /* to avoid warnings */
|
||||||
const char *what = (isLua(ci)) ? funcnamefromcode(L, ci, &name) : NULL;
|
const char *kind = funcnamefromcall(L, ci, &name);
|
||||||
if (what != NULL) {
|
const char *extra = kind ? formatvarinfo(L, kind, name) : varinfo(L, o);
|
||||||
const char *t = luaT_objtypename(L, o);
|
typeerror(L, o, "call", extra);
|
||||||
luaG_runerror(L, "%s '%s' is not callable (a %s value)", what, name, t);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
luaG_typeerror(L, o, "call");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -387,15 +387,18 @@ static void rethook (lua_State *L, CallInfo *ci, int nres) {
|
|||||||
** stack, below original 'func', so that 'luaD_precall' can call it. Raise
|
** stack, below original 'func', so that 'luaD_precall' can call it. Raise
|
||||||
** an error if there is no '__call' metafield.
|
** an error if there is no '__call' metafield.
|
||||||
*/
|
*/
|
||||||
void luaD_tryfuncTM (lua_State *L, StkId func) {
|
StkId luaD_tryfuncTM (lua_State *L, StkId func) {
|
||||||
const TValue *tm = luaT_gettmbyobj(L, s2v(func), TM_CALL);
|
const TValue *tm;
|
||||||
StkId p;
|
StkId p;
|
||||||
|
checkstackGCp(L, 1, func); /* space for metamethod */
|
||||||
|
tm = luaT_gettmbyobj(L, s2v(func), TM_CALL); /* (after previous GC) */
|
||||||
if (l_unlikely(ttisnil(tm)))
|
if (l_unlikely(ttisnil(tm)))
|
||||||
luaG_callerror(L, s2v(func)); /* nothing to call */
|
luaG_callerror(L, s2v(func)); /* nothing to call */
|
||||||
for (p = L->top; p > func; p--) /* open space for metamethod */
|
for (p = L->top; p > func; p--) /* open space for metamethod */
|
||||||
setobjs2s(L, p, p-1);
|
setobjs2s(L, p, p-1);
|
||||||
L->top++; /* stack space pre-allocated by the caller */
|
L->top++; /* stack space pre-allocated by the caller */
|
||||||
setobj2s(L, func, tm); /* metamethod is the new function to be called */
|
setobj2s(L, func, tm); /* metamethod is the new function to be called */
|
||||||
|
return func;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -405,7 +408,7 @@ void luaD_tryfuncTM (lua_State *L, StkId func) {
|
|||||||
** expressions, multiple results for tail calls/single parameters)
|
** expressions, multiple results for tail calls/single parameters)
|
||||||
** separated.
|
** separated.
|
||||||
*/
|
*/
|
||||||
static void moveresults (lua_State *L, StkId res, int nres, int wanted) {
|
l_sinline void moveresults (lua_State *L, StkId res, int nres, int wanted) {
|
||||||
StkId firstresult;
|
StkId firstresult;
|
||||||
int i;
|
int i;
|
||||||
switch (wanted) { /* handle typical cases separately */
|
switch (wanted) { /* handle typical cases separately */
|
||||||
@ -473,27 +476,81 @@ void luaD_poscall (lua_State *L, CallInfo *ci, int nres) {
|
|||||||
#define next_ci(L) (L->ci->next ? L->ci->next : luaE_extendCI(L))
|
#define next_ci(L) (L->ci->next ? L->ci->next : luaE_extendCI(L))
|
||||||
|
|
||||||
|
|
||||||
|
l_sinline CallInfo *prepCallInfo (lua_State *L, StkId func, int nret,
|
||||||
|
int mask, StkId top) {
|
||||||
|
CallInfo *ci = L->ci = next_ci(L); /* new frame */
|
||||||
|
ci->func = func;
|
||||||
|
ci->nresults = nret;
|
||||||
|
ci->callstatus = mask;
|
||||||
|
ci->top = top;
|
||||||
|
return ci;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** precall for C functions
|
||||||
|
*/
|
||||||
|
l_sinline int precallC (lua_State *L, StkId func, int nresults,
|
||||||
|
lua_CFunction f) {
|
||||||
|
int n; /* number of returns */
|
||||||
|
CallInfo *ci;
|
||||||
|
checkstackGCp(L, LUA_MINSTACK, func); /* ensure minimum stack size */
|
||||||
|
L->ci = ci = prepCallInfo(L, func, nresults, CIST_C,
|
||||||
|
L->top + LUA_MINSTACK);
|
||||||
|
lua_assert(ci->top <= L->stack_last);
|
||||||
|
if (l_unlikely(L->hookmask & LUA_MASKCALL)) {
|
||||||
|
int narg = cast_int(L->top - func) - 1;
|
||||||
|
luaD_hook(L, LUA_HOOKCALL, -1, 1, narg);
|
||||||
|
}
|
||||||
|
lua_unlock(L);
|
||||||
|
n = (*f)(L); /* do the actual call */
|
||||||
|
lua_lock(L);
|
||||||
|
api_checknelems(L, n);
|
||||||
|
luaD_poscall(L, ci, n);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Prepare a function for a tail call, building its call info on top
|
** Prepare a function for a tail call, building its call info on top
|
||||||
** of the current call info. 'narg1' is the number of arguments plus 1
|
** of the current call info. 'narg1' is the number of arguments plus 1
|
||||||
** (so that it includes the function itself).
|
** (so that it includes the function itself). Return the number of
|
||||||
|
** results, if it was a C function, or -1 for a Lua function.
|
||||||
*/
|
*/
|
||||||
void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1) {
|
int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func,
|
||||||
Proto *p = clLvalue(s2v(func))->p;
|
int narg1, int delta) {
|
||||||
int fsize = p->maxstacksize; /* frame size */
|
retry:
|
||||||
int nfixparams = p->numparams;
|
switch (ttypetag(s2v(func))) {
|
||||||
int i;
|
case LUA_VCCL: /* C closure */
|
||||||
for (i = 0; i < narg1; i++) /* move down function and arguments */
|
return precallC(L, func, LUA_MULTRET, clCvalue(s2v(func))->f);
|
||||||
setobjs2s(L, ci->func + i, func + i);
|
case LUA_VLCF: /* light C function */
|
||||||
checkstackGC(L, fsize);
|
return precallC(L, func, LUA_MULTRET, fvalue(s2v(func)));
|
||||||
func = ci->func; /* moved-down function */
|
case LUA_VLCL: { /* Lua function */
|
||||||
for (; narg1 <= nfixparams; narg1++)
|
Proto *p = clLvalue(s2v(func))->p;
|
||||||
setnilvalue(s2v(func + narg1)); /* complete missing arguments */
|
int fsize = p->maxstacksize; /* frame size */
|
||||||
ci->top = func + 1 + fsize; /* top for new function */
|
int nfixparams = p->numparams;
|
||||||
lua_assert(ci->top <= L->stack_last);
|
int i;
|
||||||
ci->u.l.savedpc = p->code; /* starting point */
|
checkstackGCp(L, fsize - delta, func);
|
||||||
ci->callstatus |= CIST_TAIL;
|
ci->func -= delta; /* restore 'func' (if vararg) */
|
||||||
L->top = func + narg1; /* set top */
|
for (i = 0; i < narg1; i++) /* move down function and arguments */
|
||||||
|
setobjs2s(L, ci->func + i, func + i);
|
||||||
|
func = ci->func; /* moved-down function */
|
||||||
|
for (; narg1 <= nfixparams; narg1++)
|
||||||
|
setnilvalue(s2v(func + narg1)); /* complete missing arguments */
|
||||||
|
ci->top = func + 1 + fsize; /* top for new function */
|
||||||
|
lua_assert(ci->top <= L->stack_last);
|
||||||
|
ci->u.l.savedpc = p->code; /* starting point */
|
||||||
|
ci->callstatus |= CIST_TAIL;
|
||||||
|
L->top = func + narg1; /* set top */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
default: { /* not a function */
|
||||||
|
func = luaD_tryfuncTM(L, func); /* try to get '__call' metamethod */
|
||||||
|
/* return luaD_pretailcall(L, ci, func, narg1 + 1, delta); */
|
||||||
|
narg1++;
|
||||||
|
goto retry; /* try again */
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -506,35 +563,14 @@ void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1) {
|
|||||||
** original function position.
|
** original function position.
|
||||||
*/
|
*/
|
||||||
CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) {
|
CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) {
|
||||||
lua_CFunction f;
|
|
||||||
retry:
|
retry:
|
||||||
switch (ttypetag(s2v(func))) {
|
switch (ttypetag(s2v(func))) {
|
||||||
case LUA_VCCL: /* C closure */
|
case LUA_VCCL: /* C closure */
|
||||||
f = clCvalue(s2v(func))->f;
|
precallC(L, func, nresults, clCvalue(s2v(func))->f);
|
||||||
goto Cfunc;
|
return NULL;
|
||||||
case LUA_VLCF: /* light C function */
|
case LUA_VLCF: /* light C function */
|
||||||
f = fvalue(s2v(func));
|
precallC(L, func, nresults, fvalue(s2v(func)));
|
||||||
Cfunc: {
|
|
||||||
int n; /* number of returns */
|
|
||||||
CallInfo *ci;
|
|
||||||
checkstackGCp(L, LUA_MINSTACK, func); /* ensure minimum stack size */
|
|
||||||
L->ci = ci = next_ci(L);
|
|
||||||
ci->nresults = nresults;
|
|
||||||
ci->callstatus = CIST_C;
|
|
||||||
ci->top = L->top + LUA_MINSTACK;
|
|
||||||
ci->func = func;
|
|
||||||
lua_assert(ci->top <= L->stack_last);
|
|
||||||
if (l_unlikely(L->hookmask & LUA_MASKCALL)) {
|
|
||||||
int narg = cast_int(L->top - func) - 1;
|
|
||||||
luaD_hook(L, LUA_HOOKCALL, -1, 1, narg);
|
|
||||||
}
|
|
||||||
lua_unlock(L);
|
|
||||||
n = (*f)(L); /* do the actual call */
|
|
||||||
lua_lock(L);
|
|
||||||
api_checknelems(L, n);
|
|
||||||
luaD_poscall(L, ci, n);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
case LUA_VLCL: { /* Lua function */
|
case LUA_VLCL: { /* Lua function */
|
||||||
CallInfo *ci;
|
CallInfo *ci;
|
||||||
Proto *p = clLvalue(s2v(func))->p;
|
Proto *p = clLvalue(s2v(func))->p;
|
||||||
@ -542,20 +578,16 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) {
|
|||||||
int nfixparams = p->numparams;
|
int nfixparams = p->numparams;
|
||||||
int fsize = p->maxstacksize; /* frame size */
|
int fsize = p->maxstacksize; /* frame size */
|
||||||
checkstackGCp(L, fsize, func);
|
checkstackGCp(L, fsize, func);
|
||||||
L->ci = ci = next_ci(L);
|
L->ci = ci = prepCallInfo(L, func, nresults, 0, func + 1 + fsize);
|
||||||
ci->nresults = nresults;
|
|
||||||
ci->u.l.savedpc = p->code; /* starting point */
|
ci->u.l.savedpc = p->code; /* starting point */
|
||||||
ci->top = func + 1 + fsize;
|
|
||||||
ci->func = func;
|
|
||||||
L->ci = ci;
|
|
||||||
for (; narg < nfixparams; narg++)
|
for (; narg < nfixparams; narg++)
|
||||||
setnilvalue(s2v(L->top++)); /* complete missing arguments */
|
setnilvalue(s2v(L->top++)); /* complete missing arguments */
|
||||||
lua_assert(ci->top <= L->stack_last);
|
lua_assert(ci->top <= L->stack_last);
|
||||||
return ci;
|
return ci;
|
||||||
}
|
}
|
||||||
default: { /* not a function */
|
default: { /* not a function */
|
||||||
checkstackGCp(L, 1, func); /* space for metamethod */
|
func = luaD_tryfuncTM(L, func); /* try to get '__call' metamethod */
|
||||||
luaD_tryfuncTM(L, func); /* try to get '__call' metamethod */
|
/* return luaD_precall(L, func, nresults); */
|
||||||
goto retry; /* try again with metamethod */
|
goto retry; /* try again with metamethod */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -567,7 +599,7 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) {
|
|||||||
** number of recursive invocations in the C stack) or nyci (the same
|
** number of recursive invocations in the C stack) or nyci (the same
|
||||||
** plus increment number of non-yieldable calls).
|
** plus increment number of non-yieldable calls).
|
||||||
*/
|
*/
|
||||||
static void ccall (lua_State *L, StkId func, int nResults, int inc) {
|
l_sinline void ccall (lua_State *L, StkId func, int nResults, int inc) {
|
||||||
CallInfo *ci;
|
CallInfo *ci;
|
||||||
L->nCcalls += inc;
|
L->nCcalls += inc;
|
||||||
if (l_unlikely(getCcalls(L) >= LUAI_MAXCCALLS))
|
if (l_unlikely(getCcalls(L) >= LUAI_MAXCCALLS))
|
||||||
@ -728,11 +760,10 @@ static void resume (lua_State *L, void *ud) {
|
|||||||
StkId firstArg = L->top - n; /* first argument */
|
StkId firstArg = L->top - n; /* first argument */
|
||||||
CallInfo *ci = L->ci;
|
CallInfo *ci = L->ci;
|
||||||
if (L->status == LUA_OK) /* starting a coroutine? */
|
if (L->status == LUA_OK) /* starting a coroutine? */
|
||||||
ccall(L, firstArg - 1, LUA_MULTRET, 1); /* just call its body */
|
ccall(L, firstArg - 1, LUA_MULTRET, 0); /* just call its body */
|
||||||
else { /* resuming from previous yield */
|
else { /* resuming from previous yield */
|
||||||
lua_assert(L->status == LUA_YIELD);
|
lua_assert(L->status == LUA_YIELD);
|
||||||
L->status = LUA_OK; /* mark that it is running (again) */
|
L->status = LUA_OK; /* mark that it is running (again) */
|
||||||
luaE_incCstack(L); /* control the C stack */
|
|
||||||
if (isLua(ci)) { /* yielded inside a hook? */
|
if (isLua(ci)) { /* yielded inside a hook? */
|
||||||
L->top = firstArg; /* discard arguments */
|
L->top = firstArg; /* discard arguments */
|
||||||
luaV_execute(L, ci); /* just continue running Lua code */
|
luaV_execute(L, ci); /* just continue running Lua code */
|
||||||
@ -783,6 +814,9 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs,
|
|||||||
else if (L->status != LUA_YIELD) /* ended with errors? */
|
else if (L->status != LUA_YIELD) /* ended with errors? */
|
||||||
return resume_error(L, "cannot resume dead coroutine", nargs);
|
return resume_error(L, "cannot resume dead coroutine", nargs);
|
||||||
L->nCcalls = (from) ? getCcalls(from) : 0;
|
L->nCcalls = (from) ? getCcalls(from) : 0;
|
||||||
|
if (getCcalls(L) >= LUAI_MAXCCALLS)
|
||||||
|
return resume_error(L, "C stack overflow", nargs);
|
||||||
|
L->nCcalls++;
|
||||||
luai_userstateresume(L, nargs);
|
luai_userstateresume(L, nargs);
|
||||||
api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs);
|
api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs);
|
||||||
status = luaD_rawrunprotected(L, resume, &nargs);
|
status = luaD_rawrunprotected(L, resume, &nargs);
|
@ -58,11 +58,11 @@ LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name,
|
|||||||
LUAI_FUNC void luaD_hook (lua_State *L, int event, int line,
|
LUAI_FUNC void luaD_hook (lua_State *L, int event, int line,
|
||||||
int fTransfer, int nTransfer);
|
int fTransfer, int nTransfer);
|
||||||
LUAI_FUNC void luaD_hookcall (lua_State *L, CallInfo *ci);
|
LUAI_FUNC void luaD_hookcall (lua_State *L, CallInfo *ci);
|
||||||
LUAI_FUNC void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int n);
|
LUAI_FUNC int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1, int delta);
|
||||||
LUAI_FUNC CallInfo *luaD_precall (lua_State *L, StkId func, int nResults);
|
LUAI_FUNC CallInfo *luaD_precall (lua_State *L, StkId func, int nResults);
|
||||||
LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults);
|
LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults);
|
||||||
LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults);
|
LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults);
|
||||||
LUAI_FUNC void luaD_tryfuncTM (lua_State *L, StkId func);
|
LUAI_FUNC StkId luaD_tryfuncTM (lua_State *L, StkId func);
|
||||||
LUAI_FUNC int luaD_closeprotected (lua_State *L, ptrdiff_t level, int status);
|
LUAI_FUNC int luaD_closeprotected (lua_State *L, ptrdiff_t level, int status);
|
||||||
LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u,
|
LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u,
|
||||||
ptrdiff_t oldtop, ptrdiff_t ef);
|
ptrdiff_t oldtop, ptrdiff_t ef);
|
@ -906,18 +906,18 @@ static void GCTM (lua_State *L) {
|
|||||||
if (!notm(tm)) { /* is there a finalizer? */
|
if (!notm(tm)) { /* is there a finalizer? */
|
||||||
int status;
|
int status;
|
||||||
lu_byte oldah = L->allowhook;
|
lu_byte oldah = L->allowhook;
|
||||||
int running = g->gcrunning;
|
int oldgcstp = g->gcstp;
|
||||||
|
g->gcstp |= GCSTPGC; /* avoid GC steps */
|
||||||
L->allowhook = 0; /* stop debug hooks during GC metamethod */
|
L->allowhook = 0; /* stop debug hooks during GC metamethod */
|
||||||
g->gcrunning = 0; /* avoid GC steps */
|
|
||||||
setobj2s(L, L->top++, tm); /* push finalizer... */
|
setobj2s(L, L->top++, tm); /* push finalizer... */
|
||||||
setobj2s(L, L->top++, &v); /* ... and its argument */
|
setobj2s(L, L->top++, &v); /* ... and its argument */
|
||||||
L->ci->callstatus |= CIST_FIN; /* will run a finalizer */
|
L->ci->callstatus |= CIST_FIN; /* will run a finalizer */
|
||||||
status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0);
|
status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0);
|
||||||
L->ci->callstatus &= ~CIST_FIN; /* not running a finalizer anymore */
|
L->ci->callstatus &= ~CIST_FIN; /* not running a finalizer anymore */
|
||||||
L->allowhook = oldah; /* restore hooks */
|
L->allowhook = oldah; /* restore hooks */
|
||||||
g->gcrunning = running; /* restore state */
|
g->gcstp = oldgcstp; /* restore state */
|
||||||
if (l_unlikely(status != LUA_OK)) { /* error while running __gc? */
|
if (l_unlikely(status != LUA_OK)) { /* error while running __gc? */
|
||||||
luaE_warnerror(L, "__gc metamethod");
|
luaE_warnerror(L, "__gc");
|
||||||
L->top--; /* pops error object */
|
L->top--; /* pops error object */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1011,7 +1011,8 @@ static void correctpointers (global_State *g, GCObject *o) {
|
|||||||
void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
|
void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
|
||||||
global_State *g = G(L);
|
global_State *g = G(L);
|
||||||
if (tofinalize(o) || /* obj. is already marked... */
|
if (tofinalize(o) || /* obj. is already marked... */
|
||||||
gfasttm(g, mt, TM_GC) == NULL) /* or has no finalizer? */
|
gfasttm(g, mt, TM_GC) == NULL || /* or has no finalizer... */
|
||||||
|
(g->gcstp & GCSTPCLS)) /* or closing state? */
|
||||||
return; /* nothing to be done */
|
return; /* nothing to be done */
|
||||||
else { /* move 'o' to 'finobj' list */
|
else { /* move 'o' to 'finobj' list */
|
||||||
GCObject **p;
|
GCObject **p;
|
||||||
@ -1502,12 +1503,13 @@ static void deletelist (lua_State *L, GCObject *p, GCObject *limit) {
|
|||||||
*/
|
*/
|
||||||
void luaC_freeallobjects (lua_State *L) {
|
void luaC_freeallobjects (lua_State *L) {
|
||||||
global_State *g = G(L);
|
global_State *g = G(L);
|
||||||
|
g->gcstp = GCSTPCLS; /* no extra finalizers after here */
|
||||||
luaC_changemode(L, KGC_INC);
|
luaC_changemode(L, KGC_INC);
|
||||||
separatetobefnz(g, 1); /* separate all objects with finalizers */
|
separatetobefnz(g, 1); /* separate all objects with finalizers */
|
||||||
lua_assert(g->finobj == NULL);
|
lua_assert(g->finobj == NULL);
|
||||||
callallpendingfinalizers(L);
|
callallpendingfinalizers(L);
|
||||||
deletelist(L, g->allgc, obj2gco(g->mainthread));
|
deletelist(L, g->allgc, obj2gco(g->mainthread));
|
||||||
deletelist(L, g->finobj, NULL);
|
lua_assert(g->finobj == NULL); /* no new finalizers */
|
||||||
deletelist(L, g->fixedgc, NULL); /* collect fixed objects */
|
deletelist(L, g->fixedgc, NULL); /* collect fixed objects */
|
||||||
lua_assert(g->strt.nuse == 0);
|
lua_assert(g->strt.nuse == 0);
|
||||||
}
|
}
|
||||||
@ -1647,6 +1649,7 @@ void luaC_runtilstate (lua_State *L, int statesmask) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Performs a basic incremental step. The debt and step size are
|
** Performs a basic incremental step. The debt and step size are
|
||||||
** converted from bytes to "units of work"; then the function loops
|
** converted from bytes to "units of work"; then the function loops
|
||||||
@ -1678,7 +1681,7 @@ static void incstep (lua_State *L, global_State *g) {
|
|||||||
void luaC_step (lua_State *L) {
|
void luaC_step (lua_State *L) {
|
||||||
global_State *g = G(L);
|
global_State *g = G(L);
|
||||||
lua_assert(!g->gcemergency);
|
lua_assert(!g->gcemergency);
|
||||||
if (g->gcrunning) { /* running? */
|
if (gcrunning(g)) { /* running? */
|
||||||
if(isdecGCmodegen(g))
|
if(isdecGCmodegen(g))
|
||||||
genstep(L, g);
|
genstep(L, g);
|
||||||
else
|
else
|
@ -148,6 +148,16 @@
|
|||||||
*/
|
*/
|
||||||
#define isdecGCmodegen(g) (g->gckind == KGC_GEN || g->lastatomic != 0)
|
#define isdecGCmodegen(g) (g->gckind == KGC_GEN || g->lastatomic != 0)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Control when GC is running:
|
||||||
|
*/
|
||||||
|
#define GCSTPUSR 1 /* bit true when GC stopped by user */
|
||||||
|
#define GCSTPGC 2 /* bit true when GC stopped by itself */
|
||||||
|
#define GCSTPCLS 4 /* bit true when closing Lua state */
|
||||||
|
#define gcrunning(g) ((g)->gcstp == 0)
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Does one step of collection when debt becomes positive. 'pre'/'pos'
|
** Does one step of collection when debt becomes positive. 'pre'/'pos'
|
||||||
** allows some adjustments to be done only when needed. macro
|
** allows some adjustments to be done only when needed. macro
|
@ -165,6 +165,20 @@ typedef LUAI_UACINT l_uacInt;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Inline functions
|
||||||
|
*/
|
||||||
|
#if !defined(LUA_USE_C89)
|
||||||
|
#define l_inline inline
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
#define l_inline __inline__
|
||||||
|
#else
|
||||||
|
#define l_inline /* empty */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define l_sinline static l_inline
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** type for virtual-machine instructions;
|
** type for virtual-machine instructions;
|
||||||
** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h)
|
** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h)
|
||||||
@ -347,7 +361,7 @@ typedef l_uint32 Instruction;
|
|||||||
#define condchangemem(L,pre,pos) ((void)0)
|
#define condchangemem(L,pre,pos) ((void)0)
|
||||||
#else
|
#else
|
||||||
#define condchangemem(L,pre,pos) \
|
#define condchangemem(L,pre,pos) \
|
||||||
{ if (G(L)->gcrunning) { pre; luaC_fullgc(L, 0); pos; } }
|
{ if (gcrunning(G(L))) { pre; luaC_fullgc(L, 0); pos; } }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -475,7 +475,7 @@ static lua_Number I2d (Rand64 x) {
|
|||||||
|
|
||||||
/* 2^(-FIGS) = 1.0 / 2^30 / 2^3 / 2^(FIGS-33) */
|
/* 2^(-FIGS) = 1.0 / 2^30 / 2^3 / 2^(FIGS-33) */
|
||||||
#define scaleFIG \
|
#define scaleFIG \
|
||||||
((lua_Number)1.0 / (UONE << 30) / 8.0 / (UONE << (FIGS - 33)))
|
(l_mathop(1.0) / (UONE << 30) / l_mathop(8.0) / (UONE << (FIGS - 33)))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** use FIGS - 32 bits from lower half, throwing out the other
|
** use FIGS - 32 bits from lower half, throwing out the other
|
||||||
@ -486,7 +486,7 @@ static lua_Number I2d (Rand64 x) {
|
|||||||
/*
|
/*
|
||||||
** higher 32 bits go after those (FIGS - 32) bits: shiftHI = 2^(FIGS - 32)
|
** higher 32 bits go after those (FIGS - 32) bits: shiftHI = 2^(FIGS - 32)
|
||||||
*/
|
*/
|
||||||
#define shiftHI ((lua_Number)(UONE << (FIGS - 33)) * 2.0)
|
#define shiftHI ((lua_Number)(UONE << (FIGS - 33)) * l_mathop(2.0))
|
||||||
|
|
||||||
|
|
||||||
static lua_Number I2d (Rand64 x) {
|
static lua_Number I2d (Rand64 x) {
|
@ -164,7 +164,7 @@ static int isneg (const char **s) {
|
|||||||
*/
|
*/
|
||||||
static lua_Number lua_strx2number (const char *s, char **endptr) {
|
static lua_Number lua_strx2number (const char *s, char **endptr) {
|
||||||
int dot = lua_getlocaledecpoint();
|
int dot = lua_getlocaledecpoint();
|
||||||
lua_Number r = 0.0; /* result (accumulator) */
|
lua_Number r = l_mathop(0.0); /* result (accumulator) */
|
||||||
int sigdig = 0; /* number of significant digits */
|
int sigdig = 0; /* number of significant digits */
|
||||||
int nosigdig = 0; /* number of non-significant digits */
|
int nosigdig = 0; /* number of non-significant digits */
|
||||||
int e = 0; /* exponent correction */
|
int e = 0; /* exponent correction */
|
||||||
@ -174,7 +174,7 @@ static lua_Number lua_strx2number (const char *s, char **endptr) {
|
|||||||
while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */
|
while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */
|
||||||
neg = isneg(&s); /* check sign */
|
neg = isneg(&s); /* check sign */
|
||||||
if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */
|
if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */
|
||||||
return 0.0; /* invalid format (no '0x') */
|
return l_mathop(0.0); /* invalid format (no '0x') */
|
||||||
for (s += 2; ; s++) { /* skip '0x' and read numeral */
|
for (s += 2; ; s++) { /* skip '0x' and read numeral */
|
||||||
if (*s == dot) {
|
if (*s == dot) {
|
||||||
if (hasdot) break; /* second dot? stop loop */
|
if (hasdot) break; /* second dot? stop loop */
|
||||||
@ -184,14 +184,14 @@ static lua_Number lua_strx2number (const char *s, char **endptr) {
|
|||||||
if (sigdig == 0 && *s == '0') /* non-significant digit (zero)? */
|
if (sigdig == 0 && *s == '0') /* non-significant digit (zero)? */
|
||||||
nosigdig++;
|
nosigdig++;
|
||||||
else if (++sigdig <= MAXSIGDIG) /* can read it without overflow? */
|
else if (++sigdig <= MAXSIGDIG) /* can read it without overflow? */
|
||||||
r = (r * cast_num(16.0)) + luaO_hexavalue(*s);
|
r = (r * l_mathop(16.0)) + luaO_hexavalue(*s);
|
||||||
else e++; /* too many digits; ignore, but still count for exponent */
|
else e++; /* too many digits; ignore, but still count for exponent */
|
||||||
if (hasdot) e--; /* decimal digit? correct exponent */
|
if (hasdot) e--; /* decimal digit? correct exponent */
|
||||||
}
|
}
|
||||||
else break; /* neither a dot nor a digit */
|
else break; /* neither a dot nor a digit */
|
||||||
}
|
}
|
||||||
if (nosigdig + sigdig == 0) /* no digits? */
|
if (nosigdig + sigdig == 0) /* no digits? */
|
||||||
return 0.0; /* invalid format */
|
return l_mathop(0.0); /* invalid format */
|
||||||
*endptr = cast_charp(s); /* valid up to here */
|
*endptr = cast_charp(s); /* valid up to here */
|
||||||
e *= 4; /* each digit multiplies/divides value by 2^4 */
|
e *= 4; /* each digit multiplies/divides value by 2^4 */
|
||||||
if (*s == 'p' || *s == 'P') { /* exponent part? */
|
if (*s == 'p' || *s == 'P') { /* exponent part? */
|
||||||
@ -200,7 +200,7 @@ static lua_Number lua_strx2number (const char *s, char **endptr) {
|
|||||||
s++; /* skip 'p' */
|
s++; /* skip 'p' */
|
||||||
neg1 = isneg(&s); /* sign */
|
neg1 = isneg(&s); /* sign */
|
||||||
if (!lisdigit(cast_uchar(*s)))
|
if (!lisdigit(cast_uchar(*s)))
|
||||||
return 0.0; /* invalid; must have at least one digit */
|
return l_mathop(0.0); /* invalid; must have at least one digit */
|
||||||
while (lisdigit(cast_uchar(*s))) /* read exponent */
|
while (lisdigit(cast_uchar(*s))) /* read exponent */
|
||||||
exp1 = exp1 * 10 + *(s++) - '0';
|
exp1 = exp1 * 10 + *(s++) - '0';
|
||||||
if (neg1) exp1 = -exp1;
|
if (neg1) exp1 = -exp1;
|
@ -68,7 +68,7 @@ typedef struct TValue {
|
|||||||
|
|
||||||
|
|
||||||
#define val_(o) ((o)->value_)
|
#define val_(o) ((o)->value_)
|
||||||
#define valraw(o) (&val_(o))
|
#define valraw(o) (val_(o))
|
||||||
|
|
||||||
|
|
||||||
/* raw type tag of a TValue */
|
/* raw type tag of a TValue */
|
||||||
@ -112,7 +112,7 @@ typedef struct TValue {
|
|||||||
#define settt_(o,t) ((o)->tt_=(t))
|
#define settt_(o,t) ((o)->tt_=(t))
|
||||||
|
|
||||||
|
|
||||||
/* main macro to copy values (from 'obj1' to 'obj2') */
|
/* main macro to copy values (from 'obj2' to 'obj1') */
|
||||||
#define setobj(L,obj1,obj2) \
|
#define setobj(L,obj1,obj2) \
|
||||||
{ TValue *io1=(obj1); const TValue *io2=(obj2); \
|
{ TValue *io1=(obj1); const TValue *io2=(obj2); \
|
||||||
io1->value_ = io2->value_; settt_(io1, io2->tt_); \
|
io1->value_ = io2->value_; settt_(io1, io2->tt_); \
|
@ -190,7 +190,8 @@ enum OpMode {iABC, iABx, iAsBx, iAx, isJ}; /* basic instruction formats */
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** grep "ORDER OP" if you change these enums
|
** Grep "ORDER OP" if you change these enums. Opcodes marked with a (*)
|
||||||
|
** has extra descriptions in the notes after the enumeration.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -203,7 +204,7 @@ OP_LOADF,/* A sBx R[A] := (lua_Number)sBx */
|
|||||||
OP_LOADK,/* A Bx R[A] := K[Bx] */
|
OP_LOADK,/* A Bx R[A] := K[Bx] */
|
||||||
OP_LOADKX,/* A R[A] := K[extra arg] */
|
OP_LOADKX,/* A R[A] := K[extra arg] */
|
||||||
OP_LOADFALSE,/* A R[A] := false */
|
OP_LOADFALSE,/* A R[A] := false */
|
||||||
OP_LFALSESKIP,/*A R[A] := false; pc++ */
|
OP_LFALSESKIP,/*A R[A] := false; pc++ (*) */
|
||||||
OP_LOADTRUE,/* A R[A] := true */
|
OP_LOADTRUE,/* A R[A] := true */
|
||||||
OP_LOADNIL,/* A B R[A], R[A+1], ..., R[A+B] := nil */
|
OP_LOADNIL,/* A B R[A], R[A+1], ..., R[A+B] := nil */
|
||||||
OP_GETUPVAL,/* A B R[A] := UpValue[B] */
|
OP_GETUPVAL,/* A B R[A] := UpValue[B] */
|
||||||
@ -254,7 +255,7 @@ OP_BXOR,/* A B C R[A] := R[B] ~ R[C] */
|
|||||||
OP_SHL,/* A B C R[A] := R[B] << R[C] */
|
OP_SHL,/* A B C R[A] := R[B] << R[C] */
|
||||||
OP_SHR,/* A B C R[A] := R[B] >> R[C] */
|
OP_SHR,/* A B C R[A] := R[B] >> R[C] */
|
||||||
|
|
||||||
OP_MMBIN,/* A B C call C metamethod over R[A] and R[B] */
|
OP_MMBIN,/* A B C call C metamethod over R[A] and R[B] (*) */
|
||||||
OP_MMBINI,/* A sB C k call C metamethod over R[A] and sB */
|
OP_MMBINI,/* A sB C k call C metamethod over R[A] and sB */
|
||||||
OP_MMBINK,/* A B C k call C metamethod over R[A] and K[B] */
|
OP_MMBINK,/* A B C k call C metamethod over R[A] and K[B] */
|
||||||
|
|
||||||
@ -280,7 +281,7 @@ OP_GTI,/* A sB k if ((R[A] > sB) ~= k) then pc++ */
|
|||||||
OP_GEI,/* A sB k if ((R[A] >= sB) ~= k) then pc++ */
|
OP_GEI,/* A sB k if ((R[A] >= sB) ~= k) then pc++ */
|
||||||
|
|
||||||
OP_TEST,/* A k if (not R[A] == k) then pc++ */
|
OP_TEST,/* A k if (not R[A] == k) then pc++ */
|
||||||
OP_TESTSET,/* A B k if (not R[B] == k) then pc++ else R[A] := R[B] */
|
OP_TESTSET,/* A B k if (not R[B] == k) then pc++ else R[A] := R[B] (*) */
|
||||||
|
|
||||||
OP_CALL,/* A B C R[A], ... ,R[A+C-2] := R[A](R[A+1], ... ,R[A+B-1]) */
|
OP_CALL,/* A B C R[A], ... ,R[A+C-2] := R[A](R[A+1], ... ,R[A+B-1]) */
|
||||||
OP_TAILCALL,/* A B C k return R[A](R[A+1], ... ,R[A+B-1]) */
|
OP_TAILCALL,/* A B C k return R[A](R[A+1], ... ,R[A+B-1]) */
|
||||||
@ -315,6 +316,18 @@ OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */
|
|||||||
|
|
||||||
/*===========================================================================
|
/*===========================================================================
|
||||||
Notes:
|
Notes:
|
||||||
|
|
||||||
|
(*) Opcode OP_LFALSESKIP is used to convert a condition to a boolean
|
||||||
|
value, in a code equivalent to (not cond ? false : true). (It
|
||||||
|
produces false and skips the next instruction producing true.)
|
||||||
|
|
||||||
|
(*) Opcodes OP_MMBIN and variants follow each arithmetic and
|
||||||
|
bitwise opcode. If the operation succeeds, it skips this next
|
||||||
|
opcode. Otherwise, this opcode calls the corresponding metamethod.
|
||||||
|
|
||||||
|
(*) Opcode OP_TESTSET is used in short-circuit expressions that need
|
||||||
|
both to jump and to produce a value, such as (a = b or c).
|
||||||
|
|
||||||
(*) In OP_CALL, if (B == 0) then B = top - A. If (C == 0), then
|
(*) In OP_CALL, if (B == 0) then B = top - A. If (C == 0), then
|
||||||
'top' is set to last_result+1, so next open instruction (OP_CALL,
|
'top' is set to last_result+1, so next open instruction (OP_CALL,
|
||||||
OP_RETURN*, OP_SETLIST) may use 'top'.
|
OP_RETURN*, OP_SETLIST) may use 'top'.
|
@ -416,6 +416,17 @@ static void markupval (FuncState *fs, int level) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Mark that current block has a to-be-closed variable.
|
||||||
|
*/
|
||||||
|
static void marktobeclosed (FuncState *fs) {
|
||||||
|
BlockCnt *bl = fs->bl;
|
||||||
|
bl->upval = 1;
|
||||||
|
bl->insidetbc = 1;
|
||||||
|
fs->needclose = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Find a variable with the given name 'n'. If it is an upvalue, add
|
** Find a variable with the given name 'n'. If it is an upvalue, add
|
||||||
** this upvalue into all intermediate functions. If it is a global, set
|
** this upvalue into all intermediate functions. If it is a global, set
|
||||||
@ -1599,7 +1610,7 @@ static void forlist (LexState *ls, TString *indexname) {
|
|||||||
line = ls->linenumber;
|
line = ls->linenumber;
|
||||||
adjust_assign(ls, 4, explist(ls, &e), &e);
|
adjust_assign(ls, 4, explist(ls, &e), &e);
|
||||||
adjustlocalvars(ls, 4); /* control variables */
|
adjustlocalvars(ls, 4); /* control variables */
|
||||||
markupval(fs, fs->nactvar); /* last control var. must be closed */
|
marktobeclosed(fs); /* last control var. must be closed */
|
||||||
luaK_checkstack(fs, 3); /* extra space to call generator */
|
luaK_checkstack(fs, 3); /* extra space to call generator */
|
||||||
forbody(ls, base, line, nvars - 4, 1);
|
forbody(ls, base, line, nvars - 4, 1);
|
||||||
}
|
}
|
||||||
@ -1703,11 +1714,9 @@ static int getlocalattribute (LexState *ls) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void checktoclose (LexState *ls, int level) {
|
static void checktoclose (FuncState *fs, int level) {
|
||||||
if (level != -1) { /* is there a to-be-closed variable? */
|
if (level != -1) { /* is there a to-be-closed variable? */
|
||||||
FuncState *fs = ls->fs;
|
marktobeclosed(fs);
|
||||||
markupval(fs, level + 1);
|
|
||||||
fs->bl->insidetbc = 1; /* in the scope of a to-be-closed variable */
|
|
||||||
luaK_codeABC(fs, OP_TBC, reglevel(fs, level), 0, 0);
|
luaK_codeABC(fs, OP_TBC, reglevel(fs, level), 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1751,7 +1760,7 @@ static void localstat (LexState *ls) {
|
|||||||
adjust_assign(ls, nvars, nexps, &e);
|
adjust_assign(ls, nvars, nexps, &e);
|
||||||
adjustlocalvars(ls, nvars);
|
adjustlocalvars(ls, nvars);
|
||||||
}
|
}
|
||||||
checktoclose(ls, toclose);
|
checktoclose(fs, toclose);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1776,6 +1785,7 @@ static void funcstat (LexState *ls, int line) {
|
|||||||
luaX_next(ls); /* skip FUNCTION */
|
luaX_next(ls); /* skip FUNCTION */
|
||||||
ismethod = funcname(ls, &v);
|
ismethod = funcname(ls, &v);
|
||||||
body(ls, &b, ismethod, line);
|
body(ls, &b, ismethod, line);
|
||||||
|
check_readonly(ls, &v);
|
||||||
luaK_storevar(ls->fs, &v, &b);
|
luaK_storevar(ls->fs, &v, &b);
|
||||||
luaK_fixline(ls->fs, line); /* definition "happens" in the first line */
|
luaK_fixline(ls->fs, line); /* definition "happens" in the first line */
|
||||||
}
|
}
|
@ -166,7 +166,7 @@ void luaE_checkcstack (lua_State *L) {
|
|||||||
if (getCcalls(L) == LUAI_MAXCCALLS)
|
if (getCcalls(L) == LUAI_MAXCCALLS)
|
||||||
luaG_runerror(L, "C stack overflow");
|
luaG_runerror(L, "C stack overflow");
|
||||||
else if (getCcalls(L) >= (LUAI_MAXCCALLS / 10 * 11))
|
else if (getCcalls(L) >= (LUAI_MAXCCALLS / 10 * 11))
|
||||||
luaD_throw(L, LUA_ERRERR); /* error while handing stack error */
|
luaD_throw(L, LUA_ERRERR); /* error while handling stack error */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -236,7 +236,7 @@ static void f_luaopen (lua_State *L, void *ud) {
|
|||||||
luaS_init(L);
|
luaS_init(L);
|
||||||
luaT_init(L);
|
luaT_init(L);
|
||||||
luaX_init(L);
|
luaX_init(L);
|
||||||
g->gcrunning = 1; /* allow gc */
|
g->gcstp = 0; /* allow gc */
|
||||||
setnilvalue(&g->nilvalue); /* now state is complete */
|
setnilvalue(&g->nilvalue); /* now state is complete */
|
||||||
luai_userstateopen(L);
|
luai_userstateopen(L);
|
||||||
}
|
}
|
||||||
@ -269,8 +269,9 @@ static void preinit_thread (lua_State *L, global_State *g) {
|
|||||||
static void close_state (lua_State *L) {
|
static void close_state (lua_State *L) {
|
||||||
global_State *g = G(L);
|
global_State *g = G(L);
|
||||||
if (!completestate(g)) /* closing a partially built state? */
|
if (!completestate(g)) /* closing a partially built state? */
|
||||||
luaC_freeallobjects(L); /* jucst collect its objects */
|
luaC_freeallobjects(L); /* just collect its objects */
|
||||||
else { /* closing a fully built state */
|
else { /* closing a fully built state */
|
||||||
|
L->ci = &L->base_ci; /* unwind CallInfo list */
|
||||||
luaD_closeprotected(L, 1, LUA_OK); /* close all upvalues */
|
luaD_closeprotected(L, 1, LUA_OK); /* close all upvalues */
|
||||||
luaC_freeallobjects(L); /* collect all objects */
|
luaC_freeallobjects(L); /* collect all objects */
|
||||||
luai_userstateclose(L);
|
luai_userstateclose(L);
|
||||||
@ -330,13 +331,13 @@ int luaE_resetthread (lua_State *L, int status) {
|
|||||||
ci->callstatus = CIST_C;
|
ci->callstatus = CIST_C;
|
||||||
if (status == LUA_YIELD)
|
if (status == LUA_YIELD)
|
||||||
status = LUA_OK;
|
status = LUA_OK;
|
||||||
|
L->status = LUA_OK; /* so it can run __close metamethods */
|
||||||
status = luaD_closeprotected(L, 1, status);
|
status = luaD_closeprotected(L, 1, status);
|
||||||
if (status != LUA_OK) /* errors? */
|
if (status != LUA_OK) /* errors? */
|
||||||
luaD_seterrorobj(L, status, L->stack + 1);
|
luaD_seterrorobj(L, status, L->stack + 1);
|
||||||
else
|
else
|
||||||
L->top = L->stack + 1;
|
L->top = L->stack + 1;
|
||||||
ci->top = L->top + LUA_MINSTACK;
|
ci->top = L->top + LUA_MINSTACK;
|
||||||
L->status = cast_byte(status);
|
|
||||||
luaD_reallocstack(L, cast_int(ci->top - L->stack), 0);
|
luaD_reallocstack(L, cast_int(ci->top - L->stack), 0);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@ -372,7 +373,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
|
|||||||
g->ud_warn = NULL;
|
g->ud_warn = NULL;
|
||||||
g->mainthread = L;
|
g->mainthread = L;
|
||||||
g->seed = luai_makeseed(L);
|
g->seed = luai_makeseed(L);
|
||||||
g->gcrunning = 0; /* no GC while building state */
|
g->gcstp = GCSTPGC; /* no GC while building state */
|
||||||
g->strt.size = g->strt.nuse = 0;
|
g->strt.size = g->strt.nuse = 0;
|
||||||
g->strt.hash = NULL;
|
g->strt.hash = NULL;
|
||||||
setnilvalue(&g->l_registry);
|
setnilvalue(&g->l_registry);
|
@ -165,7 +165,7 @@ typedef struct stringtable {
|
|||||||
** - field 'nyield' is used only while a function is "doing" an
|
** - field 'nyield' is used only while a function is "doing" an
|
||||||
** yield (from the yield until the next resume);
|
** yield (from the yield until the next resume);
|
||||||
** - field 'nres' is used only while closing tbc variables when
|
** - field 'nres' is used only while closing tbc variables when
|
||||||
** returning from a C function;
|
** returning from a function;
|
||||||
** - field 'transferinfo' is used only during call/returnhooks,
|
** - field 'transferinfo' is used only during call/returnhooks,
|
||||||
** before the function starts or after it ends.
|
** before the function starts or after it ends.
|
||||||
*/
|
*/
|
||||||
@ -209,7 +209,7 @@ typedef struct CallInfo {
|
|||||||
#define CIST_YPCALL (1<<4) /* doing a yieldable protected call */
|
#define CIST_YPCALL (1<<4) /* doing a yieldable protected call */
|
||||||
#define CIST_TAIL (1<<5) /* call was tail called */
|
#define CIST_TAIL (1<<5) /* call was tail called */
|
||||||
#define CIST_HOOKYIELD (1<<6) /* last hook called yielded */
|
#define CIST_HOOKYIELD (1<<6) /* last hook called yielded */
|
||||||
#define CIST_FIN (1<<7) /* call is running a finalizer */
|
#define CIST_FIN (1<<7) /* function "called" a finalizer */
|
||||||
#define CIST_TRAN (1<<8) /* 'ci' has transfer information */
|
#define CIST_TRAN (1<<8) /* 'ci' has transfer information */
|
||||||
#define CIST_CLSRET (1<<9) /* function is closing tbc variables */
|
#define CIST_CLSRET (1<<9) /* function is closing tbc variables */
|
||||||
/* Bits 10-12 are used for CIST_RECST (see below) */
|
/* Bits 10-12 are used for CIST_RECST (see below) */
|
||||||
@ -263,7 +263,7 @@ typedef struct global_State {
|
|||||||
lu_byte gcstopem; /* stops emergency collections */
|
lu_byte gcstopem; /* stops emergency collections */
|
||||||
lu_byte genminormul; /* control for minor generational collections */
|
lu_byte genminormul; /* control for minor generational collections */
|
||||||
lu_byte genmajormul; /* control for major generational collections */
|
lu_byte genmajormul; /* control for major generational collections */
|
||||||
lu_byte gcrunning; /* true if GC is running */
|
lu_byte gcstp; /* control whether GC is running */
|
||||||
lu_byte gcemergency; /* true if this is an emergency collection */
|
lu_byte gcemergency; /* true if this is an emergency collection */
|
||||||
lu_byte gcpause; /* size of pause between successive GCs */
|
lu_byte gcpause; /* size of pause between successive GCs */
|
||||||
lu_byte gcstepmul; /* GC "speed" */
|
lu_byte gcstepmul; /* GC "speed" */
|
@ -1090,13 +1090,31 @@ static int lua_number2strx (lua_State *L, char *buff, int sz,
|
|||||||
|
|
||||||
|
|
||||||
/* valid flags in a format specification */
|
/* valid flags in a format specification */
|
||||||
#if !defined(L_FMTFLAGS)
|
#if !defined(L_FMTFLAGSF)
|
||||||
#define L_FMTFLAGS "-+ #0"
|
|
||||||
|
/* valid flags for a, A, e, E, f, F, g, and G conversions */
|
||||||
|
#define L_FMTFLAGSF "-+#0 "
|
||||||
|
|
||||||
|
/* valid flags for o, x, and X conversions */
|
||||||
|
#define L_FMTFLAGSX "-#0"
|
||||||
|
|
||||||
|
/* valid flags for d and i conversions */
|
||||||
|
#define L_FMTFLAGSI "-+0 "
|
||||||
|
|
||||||
|
/* valid flags for u conversions */
|
||||||
|
#define L_FMTFLAGSU "-0"
|
||||||
|
|
||||||
|
/* valid flags for c, p, and s conversions */
|
||||||
|
#define L_FMTFLAGSC "-"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** maximum size of each format specification (such as "%-099.99d")
|
** Maximum size of each format specification (such as "%-099.99d"):
|
||||||
|
** Initial '%', flags (up to 5), width (2), period, precision (2),
|
||||||
|
** length modifier (8), conversion specifier, and final '\0', plus some
|
||||||
|
** extra.
|
||||||
*/
|
*/
|
||||||
#define MAX_FORMAT 32
|
#define MAX_FORMAT 32
|
||||||
|
|
||||||
@ -1189,25 +1207,53 @@ static void addliteral (lua_State *L, luaL_Buffer *b, int arg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const char *scanformat (lua_State *L, const char *strfrmt, char *form) {
|
static const char *get2digits (const char *s) {
|
||||||
const char *p = strfrmt;
|
if (isdigit(uchar(*s))) {
|
||||||
while (*p != '\0' && strchr(L_FMTFLAGS, *p) != NULL) p++; /* skip flags */
|
s++;
|
||||||
if ((size_t)(p - strfrmt) >= sizeof(L_FMTFLAGS)/sizeof(char))
|
if (isdigit(uchar(*s))) s++; /* (2 digits at most) */
|
||||||
luaL_error(L, "invalid format (repeated flags)");
|
|
||||||
if (isdigit(uchar(*p))) p++; /* skip width */
|
|
||||||
if (isdigit(uchar(*p))) p++; /* (2 digits at most) */
|
|
||||||
if (*p == '.') {
|
|
||||||
p++;
|
|
||||||
if (isdigit(uchar(*p))) p++; /* skip precision */
|
|
||||||
if (isdigit(uchar(*p))) p++; /* (2 digits at most) */
|
|
||||||
}
|
}
|
||||||
if (isdigit(uchar(*p)))
|
return s;
|
||||||
luaL_error(L, "invalid format (width or precision too long)");
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Check whether a conversion specification is valid. When called,
|
||||||
|
** first character in 'form' must be '%' and last character must
|
||||||
|
** be a valid conversion specifier. 'flags' are the accepted flags;
|
||||||
|
** 'precision' signals whether to accept a precision.
|
||||||
|
*/
|
||||||
|
static void checkformat (lua_State *L, const char *form, const char *flags,
|
||||||
|
int precision) {
|
||||||
|
const char *spec = form + 1; /* skip '%' */
|
||||||
|
spec += strspn(spec, flags); /* skip flags */
|
||||||
|
if (*spec != '0') { /* a width cannot start with '0' */
|
||||||
|
spec = get2digits(spec); /* skip width */
|
||||||
|
if (*spec == '.' && precision) {
|
||||||
|
spec++;
|
||||||
|
spec = get2digits(spec); /* skip precision */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isalpha(uchar(*spec))) /* did not go to the end? */
|
||||||
|
luaL_error(L, "invalid conversion specification: '%s'", form);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Get a conversion specification and copy it to 'form'.
|
||||||
|
** Return the address of its last character.
|
||||||
|
*/
|
||||||
|
static const char *getformat (lua_State *L, const char *strfrmt,
|
||||||
|
char *form) {
|
||||||
|
/* spans flags, width, and precision ('0' is included as a flag) */
|
||||||
|
size_t len = strspn(strfrmt, L_FMTFLAGSF "123456789.");
|
||||||
|
len++; /* adds following character (should be the specifier) */
|
||||||
|
/* still needs space for '%', '\0', plus a length modifier */
|
||||||
|
if (len >= MAX_FORMAT - 10)
|
||||||
|
luaL_error(L, "invalid format (too long)");
|
||||||
*(form++) = '%';
|
*(form++) = '%';
|
||||||
memcpy(form, strfrmt, ((p - strfrmt) + 1) * sizeof(char));
|
memcpy(form, strfrmt, len * sizeof(char));
|
||||||
form += (p - strfrmt) + 1;
|
*(form + len) = '\0';
|
||||||
*form = '\0';
|
return strfrmt + len - 1;
|
||||||
return p;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1230,6 +1276,7 @@ static int str_format (lua_State *L) {
|
|||||||
size_t sfl;
|
size_t sfl;
|
||||||
const char *strfrmt = luaL_checklstring(L, arg, &sfl);
|
const char *strfrmt = luaL_checklstring(L, arg, &sfl);
|
||||||
const char *strfrmt_end = strfrmt+sfl;
|
const char *strfrmt_end = strfrmt+sfl;
|
||||||
|
const char *flags;
|
||||||
luaL_Buffer b;
|
luaL_Buffer b;
|
||||||
luaL_buffinit(L, &b);
|
luaL_buffinit(L, &b);
|
||||||
while (strfrmt < strfrmt_end) {
|
while (strfrmt < strfrmt_end) {
|
||||||
@ -1239,25 +1286,35 @@ static int str_format (lua_State *L) {
|
|||||||
luaL_addchar(&b, *strfrmt++); /* %% */
|
luaL_addchar(&b, *strfrmt++); /* %% */
|
||||||
else { /* format item */
|
else { /* format item */
|
||||||
char form[MAX_FORMAT]; /* to store the format ('%...') */
|
char form[MAX_FORMAT]; /* to store the format ('%...') */
|
||||||
int maxitem = MAX_ITEM;
|
int maxitem = MAX_ITEM; /* maximum length for the result */
|
||||||
char *buff = luaL_prepbuffsize(&b, maxitem); /* to put formatted item */
|
char *buff = luaL_prepbuffsize(&b, maxitem); /* to put result */
|
||||||
int nb = 0; /* number of bytes in added item */
|
int nb = 0; /* number of bytes in result */
|
||||||
if (++arg > top)
|
if (++arg > top)
|
||||||
return luaL_argerror(L, arg, "no value");
|
return luaL_argerror(L, arg, "no value");
|
||||||
strfrmt = scanformat(L, strfrmt, form);
|
strfrmt = getformat(L, strfrmt, form);
|
||||||
switch (*strfrmt++) {
|
switch (*strfrmt++) {
|
||||||
case 'c': {
|
case 'c': {
|
||||||
|
checkformat(L, form, L_FMTFLAGSC, 0);
|
||||||
nb = l_sprintf(buff, maxitem, form, (int)luaL_checkinteger(L, arg));
|
nb = l_sprintf(buff, maxitem, form, (int)luaL_checkinteger(L, arg));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'd': case 'i':
|
case 'd': case 'i':
|
||||||
case 'o': case 'u': case 'x': case 'X': {
|
flags = L_FMTFLAGSI;
|
||||||
|
goto intcase;
|
||||||
|
case 'u':
|
||||||
|
flags = L_FMTFLAGSU;
|
||||||
|
goto intcase;
|
||||||
|
case 'o': case 'x': case 'X':
|
||||||
|
flags = L_FMTFLAGSX;
|
||||||
|
intcase: {
|
||||||
lua_Integer n = luaL_checkinteger(L, arg);
|
lua_Integer n = luaL_checkinteger(L, arg);
|
||||||
|
checkformat(L, form, flags, 1);
|
||||||
addlenmod(form, LUA_INTEGER_FRMLEN);
|
addlenmod(form, LUA_INTEGER_FRMLEN);
|
||||||
nb = l_sprintf(buff, maxitem, form, (LUAI_UACINT)n);
|
nb = l_sprintf(buff, maxitem, form, (LUAI_UACINT)n);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'a': case 'A':
|
case 'a': case 'A':
|
||||||
|
checkformat(L, form, L_FMTFLAGSF, 1);
|
||||||
addlenmod(form, LUA_NUMBER_FRMLEN);
|
addlenmod(form, LUA_NUMBER_FRMLEN);
|
||||||
nb = lua_number2strx(L, buff, maxitem, form,
|
nb = lua_number2strx(L, buff, maxitem, form,
|
||||||
luaL_checknumber(L, arg));
|
luaL_checknumber(L, arg));
|
||||||
@ -1268,12 +1325,14 @@ static int str_format (lua_State *L) {
|
|||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case 'e': case 'E': case 'g': case 'G': {
|
case 'e': case 'E': case 'g': case 'G': {
|
||||||
lua_Number n = luaL_checknumber(L, arg);
|
lua_Number n = luaL_checknumber(L, arg);
|
||||||
|
checkformat(L, form, L_FMTFLAGSF, 1);
|
||||||
addlenmod(form, LUA_NUMBER_FRMLEN);
|
addlenmod(form, LUA_NUMBER_FRMLEN);
|
||||||
nb = l_sprintf(buff, maxitem, form, (LUAI_UACNUMBER)n);
|
nb = l_sprintf(buff, maxitem, form, (LUAI_UACNUMBER)n);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'p': {
|
case 'p': {
|
||||||
const void *p = lua_topointer(L, arg);
|
const void *p = lua_topointer(L, arg);
|
||||||
|
checkformat(L, form, L_FMTFLAGSC, 0);
|
||||||
if (p == NULL) { /* avoid calling 'printf' with argument NULL */
|
if (p == NULL) { /* avoid calling 'printf' with argument NULL */
|
||||||
p = "(null)"; /* result */
|
p = "(null)"; /* result */
|
||||||
form[strlen(form) - 1] = 's'; /* format it as a string */
|
form[strlen(form) - 1] = 's'; /* format it as a string */
|
||||||
@ -1294,7 +1353,8 @@ static int str_format (lua_State *L) {
|
|||||||
luaL_addvalue(&b); /* keep entire string */
|
luaL_addvalue(&b); /* keep entire string */
|
||||||
else {
|
else {
|
||||||
luaL_argcheck(L, l == strlen(s), arg, "string contains zeros");
|
luaL_argcheck(L, l == strlen(s), arg, "string contains zeros");
|
||||||
if (!strchr(form, '.') && l >= 100) {
|
checkformat(L, form, L_FMTFLAGSC, 1);
|
||||||
|
if (strchr(form, '.') == NULL && l >= 100) {
|
||||||
/* no precision and string is too long to be formatted */
|
/* no precision and string is too long to be formatted */
|
||||||
luaL_addvalue(&b); /* keep entire string */
|
luaL_addvalue(&b); /* keep entire string */
|
||||||
}
|
}
|
||||||
@ -1352,15 +1412,6 @@ static const union {
|
|||||||
} nativeendian = {1};
|
} nativeendian = {1};
|
||||||
|
|
||||||
|
|
||||||
/* dummy structure to get native alignment requirements */
|
|
||||||
struct cD {
|
|
||||||
char c;
|
|
||||||
union { double d; void *p; lua_Integer i; lua_Number n; } u;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define MAXALIGN (offsetof(struct cD, u))
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** information to pack/unpack stuff
|
** information to pack/unpack stuff
|
||||||
*/
|
*/
|
||||||
@ -1435,6 +1486,8 @@ static void initheader (lua_State *L, Header *h) {
|
|||||||
** Read and classify next option. 'size' is filled with option's size.
|
** Read and classify next option. 'size' is filled with option's size.
|
||||||
*/
|
*/
|
||||||
static KOption getoption (Header *h, const char **fmt, int *size) {
|
static KOption getoption (Header *h, const char **fmt, int *size) {
|
||||||
|
/* dummy structure to get native alignment requirements */
|
||||||
|
struct cD { char c; union { LUAI_MAXALIGN; } u; };
|
||||||
int opt = *((*fmt)++);
|
int opt = *((*fmt)++);
|
||||||
*size = 0; /* default */
|
*size = 0; /* default */
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
@ -1465,7 +1518,11 @@ static KOption getoption (Header *h, const char **fmt, int *size) {
|
|||||||
case '<': h->islittle = 1; break;
|
case '<': h->islittle = 1; break;
|
||||||
case '>': h->islittle = 0; break;
|
case '>': h->islittle = 0; break;
|
||||||
case '=': h->islittle = nativeendian.little; break;
|
case '=': h->islittle = nativeendian.little; break;
|
||||||
case '!': h->maxalign = getnumlimit(h, fmt, MAXALIGN); break;
|
case '!': {
|
||||||
|
const int maxalign = offsetof(struct cD, u);
|
||||||
|
h->maxalign = getnumlimit(h, fmt, maxalign);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: luaL_error(h->L, "invalid format option '%c'", opt);
|
default: luaL_error(h->L, "invalid format option '%c'", opt);
|
||||||
}
|
}
|
||||||
return Knop;
|
return Knop;
|
@ -84,8 +84,6 @@
|
|||||||
#define hashstr(t,str) hashpow2(t, (str)->hash)
|
#define hashstr(t,str) hashpow2(t, (str)->hash)
|
||||||
#define hashboolean(t,p) hashpow2(t, p)
|
#define hashboolean(t,p) hashpow2(t, p)
|
||||||
|
|
||||||
#define hashint(t,i) hashpow2(t, i)
|
|
||||||
|
|
||||||
|
|
||||||
#define hashpointer(t,p) hashmod(t, point2uint(p))
|
#define hashpointer(t,p) hashmod(t, point2uint(p))
|
||||||
|
|
||||||
@ -101,6 +99,20 @@ static const Node dummynode_ = {
|
|||||||
static const TValue absentkey = {ABSTKEYCONSTANT};
|
static const TValue absentkey = {ABSTKEYCONSTANT};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Hash for integers. To allow a good hash, use the remainder operator
|
||||||
|
** ('%'). If integer fits as a non-negative int, compute an int
|
||||||
|
** remainder, which is faster. Otherwise, use an unsigned-integer
|
||||||
|
** remainder, which uses all bits and ensures a non-negative result.
|
||||||
|
*/
|
||||||
|
static Node *hashint (const Table *t, lua_Integer i) {
|
||||||
|
lua_Unsigned ui = l_castS2U(i);
|
||||||
|
if (ui <= (unsigned int)INT_MAX)
|
||||||
|
return hashmod(t, cast_int(ui));
|
||||||
|
else
|
||||||
|
return hashmod(t, ui);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Hash for floating-point numbers.
|
** Hash for floating-point numbers.
|
||||||
@ -134,26 +146,24 @@ static int l_hashfloat (lua_Number n) {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
** returns the 'main' position of an element in a table (that is,
|
** returns the 'main' position of an element in a table (that is,
|
||||||
** the index of its hash value). The key comes broken (tag in 'ktt'
|
** the index of its hash value).
|
||||||
** and value in 'vkl') so that we can call it on keys inserted into
|
|
||||||
** nodes.
|
|
||||||
*/
|
*/
|
||||||
static Node *mainposition (const Table *t, int ktt, const Value *kvl) {
|
static Node *mainpositionTV (const Table *t, const TValue *key) {
|
||||||
switch (withvariant(ktt)) {
|
switch (ttypetag(key)) {
|
||||||
case LUA_VNUMINT: {
|
case LUA_VNUMINT: {
|
||||||
lua_Integer key = ivalueraw(*kvl);
|
lua_Integer i = ivalue(key);
|
||||||
return hashint(t, key);
|
return hashint(t, i);
|
||||||
}
|
}
|
||||||
case LUA_VNUMFLT: {
|
case LUA_VNUMFLT: {
|
||||||
lua_Number n = fltvalueraw(*kvl);
|
lua_Number n = fltvalue(key);
|
||||||
return hashmod(t, l_hashfloat(n));
|
return hashmod(t, l_hashfloat(n));
|
||||||
}
|
}
|
||||||
case LUA_VSHRSTR: {
|
case LUA_VSHRSTR: {
|
||||||
TString *ts = tsvalueraw(*kvl);
|
TString *ts = tsvalue(key);
|
||||||
return hashstr(t, ts);
|
return hashstr(t, ts);
|
||||||
}
|
}
|
||||||
case LUA_VLNGSTR: {
|
case LUA_VLNGSTR: {
|
||||||
TString *ts = tsvalueraw(*kvl);
|
TString *ts = tsvalue(key);
|
||||||
return hashpow2(t, luaS_hashlongstr(ts));
|
return hashpow2(t, luaS_hashlongstr(ts));
|
||||||
}
|
}
|
||||||
case LUA_VFALSE:
|
case LUA_VFALSE:
|
||||||
@ -161,26 +171,25 @@ static Node *mainposition (const Table *t, int ktt, const Value *kvl) {
|
|||||||
case LUA_VTRUE:
|
case LUA_VTRUE:
|
||||||
return hashboolean(t, 1);
|
return hashboolean(t, 1);
|
||||||
case LUA_VLIGHTUSERDATA: {
|
case LUA_VLIGHTUSERDATA: {
|
||||||
void *p = pvalueraw(*kvl);
|
void *p = pvalue(key);
|
||||||
return hashpointer(t, p);
|
return hashpointer(t, p);
|
||||||
}
|
}
|
||||||
case LUA_VLCF: {
|
case LUA_VLCF: {
|
||||||
lua_CFunction f = fvalueraw(*kvl);
|
lua_CFunction f = fvalue(key);
|
||||||
return hashpointer(t, f);
|
return hashpointer(t, f);
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
GCObject *o = gcvalueraw(*kvl);
|
GCObject *o = gcvalue(key);
|
||||||
return hashpointer(t, o);
|
return hashpointer(t, o);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
l_sinline Node *mainpositionfromnode (const Table *t, Node *nd) {
|
||||||
** Returns the main position of an element given as a 'TValue'
|
TValue key;
|
||||||
*/
|
getnodekey(cast(lua_State *, NULL), &key, nd);
|
||||||
static Node *mainpositionTV (const Table *t, const TValue *key) {
|
return mainpositionTV(t, &key);
|
||||||
return mainposition(t, rawtt(key), valraw(key));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -679,7 +688,7 @@ void luaH_newkey (lua_State *L, Table *t, const TValue *key, TValue *value) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
lua_assert(!isdummy(t));
|
lua_assert(!isdummy(t));
|
||||||
othern = mainposition(t, keytt(mp), &keyval(mp));
|
othern = mainpositionfromnode(t, mp);
|
||||||
if (othern != mp) { /* is colliding node out of its main position? */
|
if (othern != mp) { /* is colliding node out of its main position? */
|
||||||
/* yes; move colliding node into free position */
|
/* yes; move colliding node into free position */
|
||||||
while (othern + gnext(othern) != mp) /* find previous */
|
while (othern + gnext(othern) != mp) /* find previous */
|
@ -59,8 +59,9 @@ static void checktab (lua_State *L, int arg, int what) {
|
|||||||
|
|
||||||
|
|
||||||
static int tinsert (lua_State *L) {
|
static int tinsert (lua_State *L) {
|
||||||
lua_Integer e = aux_getn(L, 1, TAB_RW) + 1; /* first empty element */
|
|
||||||
lua_Integer pos; /* where to insert new element */
|
lua_Integer pos; /* where to insert new element */
|
||||||
|
lua_Integer e = aux_getn(L, 1, TAB_RW);
|
||||||
|
e = luaL_intop(+, e, 1); /* first empty element */
|
||||||
switch (lua_gettop(L)) {
|
switch (lua_gettop(L)) {
|
||||||
case 2: { /* called with only 2 arguments */
|
case 2: { /* called with only 2 arguments */
|
||||||
pos = e; /* insert new element at the end */
|
pos = e; /* insert new element at the end */
|
||||||
@ -147,7 +148,7 @@ static void addfield (lua_State *L, luaL_Buffer *b, lua_Integer i) {
|
|||||||
lua_geti(L, 1, i);
|
lua_geti(L, 1, i);
|
||||||
if (l_unlikely(!lua_isstring(L, -1)))
|
if (l_unlikely(!lua_isstring(L, -1)))
|
||||||
luaL_error(L, "invalid value (%s) at index %I in table for 'concat'",
|
luaL_error(L, "invalid value (%s) at index %I in table for 'concat'",
|
||||||
luaL_typename(L, -1), i);
|
luaL_typename(L, -1), (LUAI_UACINT)i);
|
||||||
luaL_addvalue(b);
|
luaL_addvalue(b);
|
||||||
}
|
}
|
||||||
|
|
@ -89,14 +89,15 @@ static void print_usage (const char *badoption) {
|
|||||||
lua_writestringerror(
|
lua_writestringerror(
|
||||||
"usage: %s [options] [script [args]]\n"
|
"usage: %s [options] [script [args]]\n"
|
||||||
"Available options are:\n"
|
"Available options are:\n"
|
||||||
" -e stat execute string 'stat'\n"
|
" -e stat execute string 'stat'\n"
|
||||||
" -i enter interactive mode after executing 'script'\n"
|
" -i enter interactive mode after executing 'script'\n"
|
||||||
" -l name require library 'name' into global 'name'\n"
|
" -l mod require library 'mod' into global 'mod'\n"
|
||||||
" -v show version information\n"
|
" -l g=mod require library 'mod' into global 'g'\n"
|
||||||
" -E ignore environment variables\n"
|
" -v show version information\n"
|
||||||
" -W turn warnings on\n"
|
" -E ignore environment variables\n"
|
||||||
" -- stop handling options\n"
|
" -W turn warnings on\n"
|
||||||
" - stop handling options and execute stdin\n"
|
" -- stop handling options\n"
|
||||||
|
" - stop handling options and execute stdin\n"
|
||||||
,
|
,
|
||||||
progname);
|
progname);
|
||||||
}
|
}
|
||||||
@ -207,16 +208,22 @@ static int dostring (lua_State *L, const char *s, const char *name) {
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Calls 'require(name)' and stores the result in a global variable
|
** Receives 'globname[=modname]' and runs 'globname = require(modname)'.
|
||||||
** with the given name.
|
|
||||||
*/
|
*/
|
||||||
static int dolibrary (lua_State *L, const char *name) {
|
static int dolibrary (lua_State *L, char *globname) {
|
||||||
int status;
|
int status;
|
||||||
|
char *modname = strchr(globname, '=');
|
||||||
|
if (modname == NULL) /* no explicit name? */
|
||||||
|
modname = globname; /* module name is equal to global name */
|
||||||
|
else {
|
||||||
|
*modname = '\0'; /* global name ends here */
|
||||||
|
modname++; /* module name starts after the '=' */
|
||||||
|
}
|
||||||
lua_getglobal(L, "require");
|
lua_getglobal(L, "require");
|
||||||
lua_pushstring(L, name);
|
lua_pushstring(L, modname);
|
||||||
status = docall(L, 1, 1); /* call 'require(name)' */
|
status = docall(L, 1, 1); /* call 'require(modname)' */
|
||||||
if (status == LUA_OK)
|
if (status == LUA_OK)
|
||||||
lua_setglobal(L, name); /* global[name] = require return */
|
lua_setglobal(L, globname); /* globname = require(modname) */
|
||||||
return report(L, status);
|
return report(L, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -327,7 +334,7 @@ static int runargs (lua_State *L, char **argv, int n) {
|
|||||||
switch (option) {
|
switch (option) {
|
||||||
case 'e': case 'l': {
|
case 'e': case 'l': {
|
||||||
int status;
|
int status;
|
||||||
const char *extra = argv[i] + 2; /* both options need an argument */
|
char *extra = argv[i] + 2; /* both options need an argument */
|
||||||
if (*extra == '\0') extra = argv[++i];
|
if (*extra == '\0') extra = argv[++i];
|
||||||
lua_assert(extra != NULL);
|
lua_assert(extra != NULL);
|
||||||
status = (option == 'e')
|
status = (option == 'e')
|
@ -155,6 +155,7 @@ static const Proto* combine(lua_State* L, int n)
|
|||||||
f->p[i]=toproto(L,i-n-1);
|
f->p[i]=toproto(L,i-n-1);
|
||||||
if (f->p[i]->sizeupvalues>0) f->p[i]->upvalues[0].instack=0;
|
if (f->p[i]->sizeupvalues>0) f->p[i]->upvalues[0].instack=0;
|
||||||
}
|
}
|
||||||
|
luaM_freearray(L,f->lineinfo,f->sizelineinfo);
|
||||||
f->sizelineinfo=0;
|
f->sizelineinfo=0;
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
@ -600,11 +601,11 @@ static void PrintCode(const Proto* f)
|
|||||||
if (c==0) printf("all out"); else printf("%d out",c-1);
|
if (c==0) printf("all out"); else printf("%d out",c-1);
|
||||||
break;
|
break;
|
||||||
case OP_TAILCALL:
|
case OP_TAILCALL:
|
||||||
printf("%d %d %d",a,b,c);
|
printf("%d %d %d%s",a,b,c,ISK);
|
||||||
printf(COMMENT "%d in",b-1);
|
printf(COMMENT "%d in",b-1);
|
||||||
break;
|
break;
|
||||||
case OP_RETURN:
|
case OP_RETURN:
|
||||||
printf("%d %d %d",a,b,c);
|
printf("%d %d %d%s",a,b,c,ISK);
|
||||||
printf(COMMENT);
|
printf(COMMENT);
|
||||||
if (b==0) printf("all out"); else printf("%d out",b-1);
|
if (b==0) printf("all out"); else printf("%d out",b-1);
|
||||||
break;
|
break;
|
||||||
@ -619,7 +620,7 @@ static void PrintCode(const Proto* f)
|
|||||||
break;
|
break;
|
||||||
case OP_FORPREP:
|
case OP_FORPREP:
|
||||||
printf("%d %d",a,bx);
|
printf("%d %d",a,bx);
|
||||||
printf(COMMENT "to %d",pc+bx+2);
|
printf(COMMENT "exit to %d",pc+bx+3);
|
||||||
break;
|
break;
|
||||||
case OP_TFORPREP:
|
case OP_TFORPREP:
|
||||||
printf("%d %d",a,bx);
|
printf("%d %d",a,bx);
|
@ -224,14 +224,11 @@ static int byteoffset (lua_State *L) {
|
|||||||
static int iter_aux (lua_State *L, int strict) {
|
static int iter_aux (lua_State *L, int strict) {
|
||||||
size_t len;
|
size_t len;
|
||||||
const char *s = luaL_checklstring(L, 1, &len);
|
const char *s = luaL_checklstring(L, 1, &len);
|
||||||
lua_Integer n = lua_tointeger(L, 2) - 1;
|
lua_Unsigned n = (lua_Unsigned)lua_tointeger(L, 2);
|
||||||
if (n < 0) /* first iteration? */
|
if (n < len) {
|
||||||
n = 0; /* start from here */
|
while (iscont(s + n)) n++; /* skip continuation bytes */
|
||||||
else if (n < (lua_Integer)len) {
|
|
||||||
n++; /* skip current byte */
|
|
||||||
while (iscont(s + n)) n++; /* and its continuations */
|
|
||||||
}
|
}
|
||||||
if (n >= (lua_Integer)len)
|
if (n >= len) /* (also handles original 'n' being negative) */
|
||||||
return 0; /* no more codepoints */
|
return 0; /* no more codepoints */
|
||||||
else {
|
else {
|
||||||
utfint code;
|
utfint code;
|
@ -406,7 +406,7 @@ static int l_strcmp (const TString *ls, const TString *rs) {
|
|||||||
** from float to int.)
|
** from float to int.)
|
||||||
** When 'f' is NaN, comparisons must result in false.
|
** When 'f' is NaN, comparisons must result in false.
|
||||||
*/
|
*/
|
||||||
static int LTintfloat (lua_Integer i, lua_Number f) {
|
l_sinline int LTintfloat (lua_Integer i, lua_Number f) {
|
||||||
if (l_intfitsf(i))
|
if (l_intfitsf(i))
|
||||||
return luai_numlt(cast_num(i), f); /* compare them as floats */
|
return luai_numlt(cast_num(i), f); /* compare them as floats */
|
||||||
else { /* i < f <=> i < ceil(f) */
|
else { /* i < f <=> i < ceil(f) */
|
||||||
@ -423,7 +423,7 @@ static int LTintfloat (lua_Integer i, lua_Number f) {
|
|||||||
** Check whether integer 'i' is less than or equal to float 'f'.
|
** Check whether integer 'i' is less than or equal to float 'f'.
|
||||||
** See comments on previous function.
|
** See comments on previous function.
|
||||||
*/
|
*/
|
||||||
static int LEintfloat (lua_Integer i, lua_Number f) {
|
l_sinline int LEintfloat (lua_Integer i, lua_Number f) {
|
||||||
if (l_intfitsf(i))
|
if (l_intfitsf(i))
|
||||||
return luai_numle(cast_num(i), f); /* compare them as floats */
|
return luai_numle(cast_num(i), f); /* compare them as floats */
|
||||||
else { /* i <= f <=> i <= floor(f) */
|
else { /* i <= f <=> i <= floor(f) */
|
||||||
@ -440,7 +440,7 @@ static int LEintfloat (lua_Integer i, lua_Number f) {
|
|||||||
** Check whether float 'f' is less than integer 'i'.
|
** Check whether float 'f' is less than integer 'i'.
|
||||||
** See comments on previous function.
|
** See comments on previous function.
|
||||||
*/
|
*/
|
||||||
static int LTfloatint (lua_Number f, lua_Integer i) {
|
l_sinline int LTfloatint (lua_Number f, lua_Integer i) {
|
||||||
if (l_intfitsf(i))
|
if (l_intfitsf(i))
|
||||||
return luai_numlt(f, cast_num(i)); /* compare them as floats */
|
return luai_numlt(f, cast_num(i)); /* compare them as floats */
|
||||||
else { /* f < i <=> floor(f) < i */
|
else { /* f < i <=> floor(f) < i */
|
||||||
@ -457,7 +457,7 @@ static int LTfloatint (lua_Number f, lua_Integer i) {
|
|||||||
** Check whether float 'f' is less than or equal to integer 'i'.
|
** Check whether float 'f' is less than or equal to integer 'i'.
|
||||||
** See comments on previous function.
|
** See comments on previous function.
|
||||||
*/
|
*/
|
||||||
static int LEfloatint (lua_Number f, lua_Integer i) {
|
l_sinline int LEfloatint (lua_Number f, lua_Integer i) {
|
||||||
if (l_intfitsf(i))
|
if (l_intfitsf(i))
|
||||||
return luai_numle(f, cast_num(i)); /* compare them as floats */
|
return luai_numle(f, cast_num(i)); /* compare them as floats */
|
||||||
else { /* f <= i <=> ceil(f) <= i */
|
else { /* f <= i <=> ceil(f) <= i */
|
||||||
@ -473,7 +473,7 @@ static int LEfloatint (lua_Number f, lua_Integer i) {
|
|||||||
/*
|
/*
|
||||||
** Return 'l < r', for numbers.
|
** Return 'l < r', for numbers.
|
||||||
*/
|
*/
|
||||||
static int LTnum (const TValue *l, const TValue *r) {
|
l_sinline int LTnum (const TValue *l, const TValue *r) {
|
||||||
lua_assert(ttisnumber(l) && ttisnumber(r));
|
lua_assert(ttisnumber(l) && ttisnumber(r));
|
||||||
if (ttisinteger(l)) {
|
if (ttisinteger(l)) {
|
||||||
lua_Integer li = ivalue(l);
|
lua_Integer li = ivalue(l);
|
||||||
@ -495,7 +495,7 @@ static int LTnum (const TValue *l, const TValue *r) {
|
|||||||
/*
|
/*
|
||||||
** Return 'l <= r', for numbers.
|
** Return 'l <= r', for numbers.
|
||||||
*/
|
*/
|
||||||
static int LEnum (const TValue *l, const TValue *r) {
|
l_sinline int LEnum (const TValue *l, const TValue *r) {
|
||||||
lua_assert(ttisnumber(l) && ttisnumber(r));
|
lua_assert(ttisnumber(l) && ttisnumber(r));
|
||||||
if (ttisinteger(l)) {
|
if (ttisinteger(l)) {
|
||||||
lua_Integer li = ivalue(l);
|
lua_Integer li = ivalue(l);
|
||||||
@ -766,7 +766,8 @@ lua_Number luaV_modf (lua_State *L, lua_Number m, lua_Number n) {
|
|||||||
/*
|
/*
|
||||||
** Shift left operation. (Shift right just negates 'y'.)
|
** Shift left operation. (Shift right just negates 'y'.)
|
||||||
*/
|
*/
|
||||||
#define luaV_shiftr(x,y) luaV_shiftl(x,-(y))
|
#define luaV_shiftr(x,y) luaV_shiftl(x,intop(-, 0, y))
|
||||||
|
|
||||||
|
|
||||||
lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y) {
|
lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y) {
|
||||||
if (y < 0) { /* shift right? */
|
if (y < 0) { /* shift right? */
|
||||||
@ -847,10 +848,19 @@ void luaV_finishOp (lua_State *L) {
|
|||||||
luaV_concat(L, total); /* concat them (may yield again) */
|
luaV_concat(L, total); /* concat them (may yield again) */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OP_CLOSE: case OP_RETURN: { /* yielded closing variables */
|
case OP_CLOSE: { /* yielded closing variables */
|
||||||
ci->u.l.savedpc--; /* repeat instruction to close other vars. */
|
ci->u.l.savedpc--; /* repeat instruction to close other vars. */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case OP_RETURN: { /* yielded closing variables */
|
||||||
|
StkId ra = base + GETARG_A(inst);
|
||||||
|
/* adjust top to signal correct number of returns, in case the
|
||||||
|
return is "up to top" ('isIT') */
|
||||||
|
L->top = ra + ci->u2.nres;
|
||||||
|
/* repeat instruction to close other vars. and complete the return */
|
||||||
|
ci->u.l.savedpc--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
/* only these other opcodes can yield */
|
/* only these other opcodes can yield */
|
||||||
lua_assert(op == OP_TFORCALL || op == OP_CALL ||
|
lua_assert(op == OP_TFORCALL || op == OP_CALL ||
|
||||||
@ -1099,7 +1109,7 @@ void luaV_finishOp (lua_State *L) {
|
|||||||
#define ProtectNT(exp) (savepc(L), (exp), updatetrap(ci))
|
#define ProtectNT(exp) (savepc(L), (exp), updatetrap(ci))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Protect code that can only raise errors. (That is, it cannnot change
|
** Protect code that can only raise errors. (That is, it cannot change
|
||||||
** the stack or hooks.)
|
** the stack or hooks.)
|
||||||
*/
|
*/
|
||||||
#define halfProtect(exp) (savestate(L,ci), (exp))
|
#define halfProtect(exp) (savestate(L,ci), (exp))
|
||||||
@ -1156,8 +1166,10 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|||||||
Instruction i; /* instruction being executed */
|
Instruction i; /* instruction being executed */
|
||||||
StkId ra; /* instruction's A register */
|
StkId ra; /* instruction's A register */
|
||||||
vmfetch();
|
vmfetch();
|
||||||
// low-level line tracing for debugging Lua
|
#if 0
|
||||||
// printf("line: %d\n", luaG_getfuncline(cl->p, pcRel(pc, cl->p)));
|
/* low-level line tracing for debugging Lua */
|
||||||
|
printf("line: %d\n", luaG_getfuncline(cl->p, pcRel(pc, cl->p)));
|
||||||
|
#endif
|
||||||
lua_assert(base == ci->func + 1);
|
lua_assert(base == ci->func + 1);
|
||||||
lua_assert(base <= L->top && L->top < L->stack_last);
|
lua_assert(base <= L->top && L->top < L->stack_last);
|
||||||
/* invalidate top for instructions not expecting it */
|
/* invalidate top for instructions not expecting it */
|
||||||
@ -1625,13 +1637,13 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|||||||
updatetrap(ci); /* C call; nothing else to be done */
|
updatetrap(ci); /* C call; nothing else to be done */
|
||||||
else { /* Lua call: run function in this same C frame */
|
else { /* Lua call: run function in this same C frame */
|
||||||
ci = newci;
|
ci = newci;
|
||||||
ci->callstatus = 0; /* call re-uses 'luaV_execute' */
|
|
||||||
goto startfunc;
|
goto startfunc;
|
||||||
}
|
}
|
||||||
vmbreak;
|
vmbreak;
|
||||||
}
|
}
|
||||||
vmcase(OP_TAILCALL) {
|
vmcase(OP_TAILCALL) {
|
||||||
int b = GETARG_B(i); /* number of arguments + 1 (function) */
|
int b = GETARG_B(i); /* number of arguments + 1 (function) */
|
||||||
|
int n; /* number of results when calling a C function */
|
||||||
int nparams1 = GETARG_C(i);
|
int nparams1 = GETARG_C(i);
|
||||||
/* delta is virtual 'func' - real 'func' (vararg functions) */
|
/* delta is virtual 'func' - real 'func' (vararg functions) */
|
||||||
int delta = (nparams1) ? ci->u.l.nextraargs + nparams1 : 0;
|
int delta = (nparams1) ? ci->u.l.nextraargs + nparams1 : 0;
|
||||||
@ -1645,23 +1657,14 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|||||||
lua_assert(L->tbclist < base); /* no pending tbc variables */
|
lua_assert(L->tbclist < base); /* no pending tbc variables */
|
||||||
lua_assert(base == ci->func + 1);
|
lua_assert(base == ci->func + 1);
|
||||||
}
|
}
|
||||||
while (!ttisfunction(s2v(ra))) { /* not a function? */
|
if ((n = luaD_pretailcall(L, ci, ra, b, delta)) < 0) /* Lua function? */
|
||||||
luaD_tryfuncTM(L, ra); /* try '__call' metamethod */
|
goto startfunc; /* execute the callee */
|
||||||
b++; /* there is now one extra argument */
|
else { /* C function? */
|
||||||
checkstackGCp(L, 1, ra);
|
|
||||||
}
|
|
||||||
if (!ttisLclosure(s2v(ra))) { /* C function? */
|
|
||||||
luaD_precall(L, ra, LUA_MULTRET); /* call it */
|
|
||||||
updatetrap(ci);
|
|
||||||
updatestack(ci); /* stack may have been relocated */
|
|
||||||
ci->func -= delta; /* restore 'func' (if vararg) */
|
ci->func -= delta; /* restore 'func' (if vararg) */
|
||||||
luaD_poscall(L, ci, cast_int(L->top - ra)); /* finish caller */
|
luaD_poscall(L, ci, n); /* finish caller */
|
||||||
updatetrap(ci); /* 'luaD_poscall' can change hooks */
|
updatetrap(ci); /* 'luaD_poscall' can change hooks */
|
||||||
goto ret; /* caller returns after the tail call */
|
goto ret; /* caller returns after the tail call */
|
||||||
}
|
}
|
||||||
ci->func -= delta; /* restore 'func' (if vararg) */
|
|
||||||
luaD_pretailcall(L, ci, ra, b); /* prepare call frame */
|
|
||||||
goto startfunc; /* execute the callee */
|
|
||||||
}
|
}
|
||||||
vmcase(OP_RETURN) {
|
vmcase(OP_RETURN) {
|
||||||
int n = GETARG_B(i) - 1; /* number of results */
|
int n = GETARG_B(i) - 1; /* number of results */
|
||||||
@ -1670,6 +1673,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|||||||
n = cast_int(L->top - ra); /* get what is available */
|
n = cast_int(L->top - ra); /* get what is available */
|
||||||
savepc(ci);
|
savepc(ci);
|
||||||
if (TESTARG_k(i)) { /* may there be open upvalues? */
|
if (TESTARG_k(i)) { /* may there be open upvalues? */
|
||||||
|
ci->u2.nres = n; /* save number of returns */
|
||||||
if (L->top < ci->top)
|
if (L->top < ci->top)
|
||||||
L->top = ci->top;
|
L->top = ci->top;
|
||||||
luaF_close(L, base, CLOSEKTOP, 1);
|
luaF_close(L, base, CLOSEKTOP, 1);
|
Binary file not shown.
BIN
orig_sources/lua-5.4.4.tar.gz
Normal file
BIN
orig_sources/lua-5.4.4.tar.gz
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user