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)
|
||||
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_BUILD_AS_CXX "Build lua as C++" OFF)
|
||||
@ -20,4 +20,4 @@ else()
|
||||
endif()
|
||||
|
||||
|
||||
add_subdirectory(lua-5.4.3)
|
||||
add_subdirectory(lua-5.4.4)
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Lua
|
||||
CMake based build of Lua 5.4.3
|
||||
CMake based build of Lua 5.4.4
|
||||
| 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) |
|
||||
|
@ -46,7 +46,7 @@ TO_MAN= lua.1 luac.1
|
||||
|
||||
# Lua version and release.
|
||||
V= 5.4
|
||||
R= $V.3
|
||||
R= $V.4
|
||||
|
||||
# Targets start here.
|
||||
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
|
||||
further information about Lua, see doc/readme.html.
|
@ -32,7 +32,7 @@ For a complete introduction to Lua programming, see the book
|
||||
|
||||
<P>
|
||||
<SMALL>
|
||||
Copyright © 2020–2021 Lua.org, PUC-Rio.
|
||||
Copyright © 2020–2022 Lua.org, PUC-Rio.
|
||||
Freely available under the terms of the
|
||||
<A HREF="http://www.lua.org/license.html">Lua license</A>.
|
||||
</SMALL>
|
||||
@ -664,10 +664,10 @@ Freely available under the terms of the
|
||||
|
||||
<P CLASS="footer">
|
||||
Last update:
|
||||
Wed Mar 3 13:04:44 UTC 2021
|
||||
Thu Jan 13 11:32:22 UTC 2022
|
||||
</P>
|
||||
<!--
|
||||
Last change: revised for Lua 5.4.3
|
||||
Last change: revised for Lua 5.4.4
|
||||
-->
|
||||
|
||||
</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>
|
||||
<SMALL>
|
||||
Copyright © 2020–2021 Lua.org, PUC-Rio.
|
||||
Copyright © 2020–2022 Lua.org, PUC-Rio.
|
||||
Freely available under the terms of the
|
||||
<a href="http://www.lua.org/license.html">Lua license</a>.
|
||||
</SMALL>
|
||||
@ -961,11 +961,8 @@ these marks have no effect.
|
||||
|
||||
|
||||
<p>
|
||||
Finalizers cannot yield.
|
||||
Except for that, they can do anything,
|
||||
such as raise errors, create new objects,
|
||||
or even run the garbage collector.
|
||||
However, because they can run in unpredictable times,
|
||||
Finalizers cannot yield nor run the garbage collector.
|
||||
Because they can run in unpredictable times,
|
||||
it is good practice to restrict each finalizer
|
||||
to the minimum necessary to properly release
|
||||
its associated resource.
|
||||
@ -1636,8 +1633,10 @@ before the adjustment
|
||||
|
||||
|
||||
<p>
|
||||
The assignment statement first evaluates all its expressions
|
||||
and only then the assignments are performed.
|
||||
If a variable is both assigned and read
|
||||
inside a multiple assignment,
|
||||
Lua ensures all reads get the value of the variable
|
||||
before the assignment.
|
||||
Thus the code
|
||||
|
||||
<pre>
|
||||
@ -1661,6 +1660,14 @@ and
|
||||
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>
|
||||
An assignment to a global name <code>x = val</code>
|
||||
is equivalent to the assignment
|
||||
@ -2416,16 +2423,21 @@ character is one byte.)
|
||||
<p>
|
||||
The length operator applied on a 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:
|
||||
|
||||
<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>
|
||||
In words,
|
||||
a border is any (natural) index present in the table
|
||||
that is followed by an absent index
|
||||
(or zero, when index 1 is absent).
|
||||
a border is any positive integer index present in the table
|
||||
that is followed by an absent index,
|
||||
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>
|
||||
@ -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.
|
||||
(The <b>nil</b> at index 4 is called a <em>hole</em>.)
|
||||
The table <code>{nil, 20, 30, nil, nil, 60, nil}</code>
|
||||
has three borders (0, 3, and 6) and three holes
|
||||
(at indices 1, 4, and 5),
|
||||
has three borders (0, 3, and 6),
|
||||
so it is not a sequence, too.
|
||||
The table <code>{}</code> is a sequence with border 0.
|
||||
Note that non-natural keys do not interfere
|
||||
with whether a table is a sequence.
|
||||
|
||||
|
||||
<p>
|
||||
@ -2459,7 +2468,7 @@ the memory addresses of its non-numeric keys.)
|
||||
<p>
|
||||
The computation of the length of a table
|
||||
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>
|
||||
@ -3979,6 +3988,10 @@ For more details about these options,
|
||||
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
|
||||
of this structure, for later use.
|
||||
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>
|
||||
@ -6110,11 +6126,25 @@ you can write the following code:
|
||||
<p>
|
||||
Each character in the string <code>what</code>
|
||||
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>
|
||||
|
||||
<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><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>;
|
||||
</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>
|
||||
|
||||
@ -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>;
|
||||
</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>
|
||||
pushes onto the stack a table whose indices are the
|
||||
numbers of the lines that are valid on the function.
|
||||
(A <em>valid line</em> is a line with some associated code,
|
||||
that is, a line where you can put a break point.
|
||||
Non-valid lines include empty lines and comments.)
|
||||
|
||||
|
||||
<p>
|
||||
pushes onto the stack a table whose indices are
|
||||
the lines on the function with some associated code,
|
||||
that is, the lines where you can put a break point.
|
||||
(Lines with no code include empty lines and comments.)
|
||||
If this option is given together with option '<code>f</code>',
|
||||
its table is pushed after the function.
|
||||
|
||||
|
||||
<p>
|
||||
This is the only option that can raise a memory error.
|
||||
</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>
|
||||
<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,
|
||||
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>
|
||||
<span class="apii">[-1, +?, <em>m</em>]</span>
|
||||
<span class="apii">[-?, +?, <em>m</em>]</span>
|
||||
<pre>void luaL_addvalue (luaL_Buffer *B);</pre>
|
||||
|
||||
<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>
|
||||
<span class="apii">[-0, +0, –]</span>
|
||||
<span class="apii">[-0, +?, –]</span>
|
||||
<pre>void luaL_buffinit (lua_State *L, luaL_Buffer *B);</pre>
|
||||
|
||||
<p>
|
||||
@ -6754,7 +6769,7 @@ Equivalent to the sequence
|
||||
|
||||
|
||||
<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>
|
||||
|
||||
<p>
|
||||
@ -7557,6 +7572,11 @@ on top of the library table.
|
||||
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.
|
||||
|
||||
|
||||
<p>
|
||||
This function should not be called by a finalizer.
|
||||
|
||||
|
||||
|
||||
|
||||
<p>
|
||||
@ -7936,7 +7960,7 @@ to its caller.
|
||||
|
||||
<p>
|
||||
<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.
|
||||
|
||||
|
||||
@ -8111,9 +8135,8 @@ use a numerical <b>for</b>.)
|
||||
|
||||
|
||||
<p>
|
||||
The behavior of <code>next</code> is undefined if,
|
||||
during the traversal,
|
||||
you assign any value to a non-existent field in the table.
|
||||
You should not assign any value to a non-existent field in a table
|
||||
during its traversal.
|
||||
You may however modify existing fields.
|
||||
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
|
||||
and returns a status code.
|
||||
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,
|
||||
after this first result.
|
||||
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>
|
||||
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.
|
||||
|
||||
|
||||
@ -8483,7 +8506,7 @@ If there is any error,
|
||||
|
||||
<p>
|
||||
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
|
||||
where to start the search;
|
||||
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,
|
||||
so the function does a plain "find substring" operation,
|
||||
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.
|
||||
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
|
||||
<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>.
|
||||
Both width and precision, when present,
|
||||
are limited to two digits.
|
||||
|
||||
|
||||
<p>
|
||||
@ -9071,7 +9096,7 @@ may produce the string:
|
||||
"a string with \"quotes\" and \
|
||||
new line"
|
||||
</pre><p>
|
||||
This specifier does not support modifiers (flags, width, length).
|
||||
This specifier does not support modifiers (flags, width, precision).
|
||||
|
||||
|
||||
<p>
|
||||
@ -10362,7 +10387,7 @@ or <b>fail</b> if <code>x</code> is not a number.
|
||||
|
||||
<p>
|
||||
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.
|
||||
|
||||
|
||||
@ -11924,10 +11949,10 @@ and LiteralString, see <a href="#3.1">§3.1</a>.)
|
||||
|
||||
<P CLASS="footer">
|
||||
Last update:
|
||||
Mon Mar 15 13:39:42 UTC 2021
|
||||
Thu Jan 13 11:33:16 UTC 2022
|
||||
</P>
|
||||
<!--
|
||||
Last change: revised for Lua 5.4.3
|
||||
Last change: revised for Lua 5.4.4
|
||||
-->
|
||||
|
||||
</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>
|
||||
<LI>
|
||||
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.
|
||||
<P>
|
||||
<LI>
|
||||
@ -303,7 +303,7 @@ For details, see
|
||||
<A HREF="http://www.lua.org/license.html">this</A>.
|
||||
|
||||
<BLOCKQUOTE STYLE="padding-bottom: 0em">
|
||||
Copyright © 1994–2021 Lua.org, PUC-Rio.
|
||||
Copyright © 1994–2022 Lua.org, PUC-Rio.
|
||||
|
||||
<P>
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
@ -330,10 +330,10 @@ THE SOFTWARE.
|
||||
|
||||
<P CLASS="footer">
|
||||
Last update:
|
||||
Wed Mar 3 10:16:26 UTC 2021
|
||||
Mon Jan 3 09:54:18 UTC 2022
|
||||
</P>
|
||||
<!--
|
||||
Last change: revised for Lua 5.4.3
|
||||
Last change: revised for Lua 5.4.4
|
||||
-->
|
||||
|
||||
</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 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);
|
||||
LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s,
|
||||
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)
|
||||
|
||||
|
||||
/*
|
||||
** 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 */
|
||||
#define luaL_pushfail(L) lua_pushnil(L)
|
||||
|
@ -18,14 +18,14 @@
|
||||
|
||||
#define LUA_VERSION_MAJOR "5"
|
||||
#define LUA_VERSION_MINOR "4"
|
||||
#define LUA_VERSION_RELEASE "3"
|
||||
#define LUA_VERSION_RELEASE "4"
|
||||
|
||||
#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_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"
|
||||
|
||||
|
||||
@ -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
|
||||
* 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_MININTEGER is the minimum value for a LUA_INTEGER.
|
||||
@@ 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.
|
||||
*/
|
||||
|
||||
@ -506,9 +505,6 @@
|
||||
#define LUA_UNSIGNED unsigned LUAI_UACINT
|
||||
|
||||
|
||||
#define LUA_UNSIGNEDBITS (sizeof(LUA_UNSIGNED) * CHAR_BIT)
|
||||
|
||||
|
||||
/* now the variable definitions */
|
||||
|
||||
#if LUA_INT_TYPE == LUA_INT_INT /* { int */
|
@ -79,7 +79,7 @@ echo:
|
||||
@echo "PLAT= $(PLAT)"
|
||||
@echo "CC= $(CC)"
|
||||
@echo "CFLAGS= $(CFLAGS)"
|
||||
@echo "LDFLAGS= $(SYSLDFLAGS)"
|
||||
@echo "LDFLAGS= $(LDFLAGS)"
|
||||
@echo "LIBS= $(LIBS)"
|
||||
@echo "AR= $(AR)"
|
||||
@echo "RANLIB= $(RANLIB)"
|
@ -53,6 +53,10 @@ const char lua_ident[] =
|
||||
#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) {
|
||||
CallInfo *ci = L->ci;
|
||||
if (idx > 0) {
|
||||
@ -70,22 +74,28 @@ static TValue *index2value (lua_State *L, int idx) {
|
||||
else { /* upvalues */
|
||||
idx = LUA_REGISTRYINDEX - idx;
|
||||
api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large");
|
||||
if (ttislcf(s2v(ci->func))) /* light C function? */
|
||||
return &G(L)->nilvalue; /* it has no upvalues */
|
||||
else {
|
||||
if (ttisCclosure(s2v(ci->func))) { /* C closure? */
|
||||
CClosure *func = clCvalue(s2v(ci->func));
|
||||
return (idx <= func->nupvalues) ? &func->upvalue[idx-1]
|
||||
: &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;
|
||||
if (idx > 0) {
|
||||
StkId o = ci->func + idx;
|
||||
api_check(L, o < L->top, "unacceptable index");
|
||||
api_check(L, o < L->top, "invalid index");
|
||||
return o;
|
||||
}
|
||||
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.
|
||||
** (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--) {
|
||||
TValue temp;
|
||||
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)) {
|
||||
case LUA_TUSERDATA: return getudatamem(uvalue(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;
|
||||
TString *str = luaS_new(L, k);
|
||||
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 */
|
||||
setnilvalue(s2v(L->top));
|
||||
else
|
||||
@ -1126,18 +1136,19 @@ LUA_API int lua_status (lua_State *L) {
|
||||
LUA_API int lua_gc (lua_State *L, int what, ...) {
|
||||
va_list argp;
|
||||
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);
|
||||
g = G(L);
|
||||
va_start(argp, what);
|
||||
switch (what) {
|
||||
case LUA_GCSTOP: {
|
||||
g->gcrunning = 0;
|
||||
g->gcstp = GCSTPUSR; /* stopped by the user */
|
||||
break;
|
||||
}
|
||||
case LUA_GCRESTART: {
|
||||
luaE_setdebt(g, 0);
|
||||
g->gcrunning = 1;
|
||||
g->gcstp = 0; /* (GCSTPGC must be already zero here) */
|
||||
break;
|
||||
}
|
||||
case LUA_GCCOLLECT: {
|
||||
@ -1156,8 +1167,8 @@ LUA_API int lua_gc (lua_State *L, int what, ...) {
|
||||
case LUA_GCSTEP: {
|
||||
int data = va_arg(argp, int);
|
||||
l_mem debt = 1; /* =1 to signal that it did an actual step */
|
||||
lu_byte oldrunning = g->gcrunning;
|
||||
g->gcrunning = 1; /* allow GC to run */
|
||||
lu_byte oldstp = g->gcstp;
|
||||
g->gcstp = 0; /* allow GC to run (GCSTPGC must be zero here) */
|
||||
if (data == 0) {
|
||||
luaE_setdebt(g, 0); /* do a basic step */
|
||||
luaC_step(L);
|
||||
@ -1167,7 +1178,7 @@ LUA_API int lua_gc (lua_State *L, int what, ...) {
|
||||
luaE_setdebt(g, debt);
|
||||
luaC_checkGC(L);
|
||||
}
|
||||
g->gcrunning = oldrunning; /* restore previous state */
|
||||
g->gcstp = oldstp; /* restore previous state */
|
||||
if (debt > 0 && g->gcstate == GCSpause) /* end of cycle? */
|
||||
res = 1; /* signal it */
|
||||
break;
|
||||
@ -1185,7 +1196,7 @@ LUA_API int lua_gc (lua_State *L, int what, ...) {
|
||||
break;
|
||||
}
|
||||
case LUA_GCISRUNNING: {
|
||||
res = g->gcrunning;
|
||||
res = gcrunning(g);
|
||||
break;
|
||||
}
|
||||
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) {
|
||||
idx = lua_absindex(L,idx);
|
||||
if (luaL_callmeta(L, idx, "__tostring")) { /* metafield? */
|
||||
if (!lua_isstring(L, -1))
|
||||
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) {
|
||||
if (oldmode == -1)
|
||||
luaL_pushfail(L); /* invalid call to 'lua_gc' */
|
||||
else
|
||||
lua_pushstring(L, (oldmode == LUA_GCINC) ? "incremental"
|
||||
: "generational");
|
||||
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 const char *const opts[] = {"stop", "restart", "collect",
|
||||
"count", "step", "setpause", "setstepmul",
|
||||
@ -200,12 +208,14 @@ static int luaB_collectgarbage (lua_State *L) {
|
||||
case LUA_GCCOUNT: {
|
||||
int k = lua_gc(L, o);
|
||||
int b = lua_gc(L, LUA_GCCOUNTB);
|
||||
checkvalres(k);
|
||||
lua_pushnumber(L, (lua_Number)k + ((lua_Number)b/1024));
|
||||
return 1;
|
||||
}
|
||||
case LUA_GCSTEP: {
|
||||
int step = (int)luaL_optinteger(L, 2, 0);
|
||||
int res = lua_gc(L, o, step);
|
||||
checkvalres(res);
|
||||
lua_pushboolean(L, res);
|
||||
return 1;
|
||||
}
|
||||
@ -213,11 +223,13 @@ static int luaB_collectgarbage (lua_State *L) {
|
||||
case LUA_GCSETSTEPMUL: {
|
||||
int p = (int)luaL_optinteger(L, 2, 0);
|
||||
int previous = lua_gc(L, o, p);
|
||||
checkvalres(previous);
|
||||
lua_pushinteger(L, previous);
|
||||
return 1;
|
||||
}
|
||||
case LUA_GCISRUNNING: {
|
||||
int res = lua_gc(L, o);
|
||||
checkvalres(res);
|
||||
lua_pushboolean(L, res);
|
||||
return 1;
|
||||
}
|
||||
@ -234,10 +246,13 @@ static int luaB_collectgarbage (lua_State *L) {
|
||||
}
|
||||
default: {
|
||||
int res = lua_gc(L, o);
|
||||
checkvalres(res);
|
||||
lua_pushinteger(L, res);
|
||||
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) {
|
||||
luaL_checkany(L, 1);
|
||||
if (luaL_getmetafield(L, 1, "__pairs") == LUA_TNIL) { /* no metamethod? */
|
||||
@ -270,7 +290,7 @@ static int luaB_pairs (lua_State *L) {
|
||||
}
|
||||
else {
|
||||
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;
|
||||
}
|
||||
@ -280,7 +300,8 @@ static int luaB_pairs (lua_State *L) {
|
||||
** Traversal function for 'ipairs'
|
||||
*/
|
||||
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);
|
||||
return (lua_geti(L, 1, i) == LUA_TNIL) ? 1 : 2;
|
||||
}
|
@ -10,6 +10,7 @@
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
#include <float.h>
|
||||
#include <limits.h>
|
||||
#include <math.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.
|
||||
** 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) {
|
||||
TValue k, o;
|
||||
setpvalue(&k, cast_voidp(cast_sizet(n)));
|
||||
TValue o;
|
||||
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) {
|
||||
TValue o;
|
||||
lua_Integer ik;
|
||||
setfltvalue(&o, r);
|
||||
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? */
|
||||
stat = lua_resetthread(co); /* close its tbc variables */
|
||||
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 ... */
|
||||
lua_type(L, -1) == LUA_TSTRING) { /* ... error object is a string? */
|
||||
@ -179,7 +179,7 @@ static int luaB_close (lua_State *L) {
|
||||
}
|
||||
else {
|
||||
lua_pushboolean(L, 0);
|
||||
lua_xmove(co, L, 1); /* copy error message */
|
||||
lua_xmove(co, L, 1); /* move error message */
|
||||
return 2;
|
||||
}
|
||||
}
|
@ -34,7 +34,7 @@
|
||||
#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);
|
||||
|
||||
|
||||
@ -64,7 +64,7 @@ static int getbaseline (const Proto *f, int pc, int *basepc) {
|
||||
}
|
||||
else {
|
||||
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 ||
|
||||
(i < f->sizeabslineinfo && f->abslineinfo[i].pc <= 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 */
|
||||
api_incr_top(L);
|
||||
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 */
|
||||
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) {
|
||||
if (ci == NULL) /* no 'ci'? */
|
||||
return NULL; /* no info */
|
||||
else if (ci->callstatus & CIST_FIN) { /* is this a finalizer? */
|
||||
*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);
|
||||
/* calling function is a known function? */
|
||||
if (ci != NULL && !(ci->callstatus & CIST_TAIL))
|
||||
return funcnamefromcall(L, ci->previous, 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",
|
||||
** "metamethod") and sets '*name' to point to the name.
|
||||
*/
|
||||
static const char *funcnamefromcode (lua_State *L, CallInfo *ci,
|
||||
const char **name) {
|
||||
static const char *funcnamefromcode (lua_State *L, const Proto *p,
|
||||
int pc, const char **name) {
|
||||
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 */
|
||||
if (ci->callstatus & CIST_HOOKED) { /* was it called inside a hook? */
|
||||
*name = "?";
|
||||
return "hook";
|
||||
}
|
||||
switch (GET_OPCODE(i)) {
|
||||
case OP_CALL:
|
||||
case OP_TAILCALL:
|
||||
@ -636,6 +631,26 @@ static const char *funcnamefromcode (lua_State *L, CallInfo *ci,
|
||||
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) {
|
||||
const char *name = NULL; /* to avoid warnings */
|
||||
CallInfo *ci = L->ci;
|
||||
const char *name = NULL; /* to avoid warnings */
|
||||
const char *kind = NULL;
|
||||
if (isLua(ci)) {
|
||||
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),
|
||||
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);
|
||||
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) {
|
||||
CallInfo *ci = L->ci;
|
||||
const char *name = NULL; /* to avoid warnings */
|
||||
const char *what = (isLua(ci)) ? funcnamefromcode(L, ci, &name) : NULL;
|
||||
if (what != NULL) {
|
||||
const char *t = luaT_objtypename(L, o);
|
||||
luaG_runerror(L, "%s '%s' is not callable (a %s value)", what, name, t);
|
||||
}
|
||||
else
|
||||
luaG_typeerror(L, o, "call");
|
||||
const char *kind = funcnamefromcall(L, ci, &name);
|
||||
const char *extra = kind ? formatvarinfo(L, kind, name) : varinfo(L, o);
|
||||
typeerror(L, o, "call", extra);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
** an error if there is no '__call' metafield.
|
||||
*/
|
||||
void luaD_tryfuncTM (lua_State *L, StkId func) {
|
||||
const TValue *tm = luaT_gettmbyobj(L, s2v(func), TM_CALL);
|
||||
StkId luaD_tryfuncTM (lua_State *L, StkId func) {
|
||||
const TValue *tm;
|
||||
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)))
|
||||
luaG_callerror(L, s2v(func)); /* nothing to call */
|
||||
for (p = L->top; p > func; p--) /* open space for metamethod */
|
||||
setobjs2s(L, p, p-1);
|
||||
L->top++; /* stack space pre-allocated by the caller */
|
||||
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)
|
||||
** 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;
|
||||
int i;
|
||||
switch (wanted) { /* handle typical cases separately */
|
||||
@ -473,19 +476,64 @@ void luaD_poscall (lua_State *L, CallInfo *ci, int nres) {
|
||||
#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
|
||||
** 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,
|
||||
int narg1, int delta) {
|
||||
retry:
|
||||
switch (ttypetag(s2v(func))) {
|
||||
case LUA_VCCL: /* C closure */
|
||||
return precallC(L, func, LUA_MULTRET, clCvalue(s2v(func))->f);
|
||||
case LUA_VLCF: /* light C function */
|
||||
return precallC(L, func, LUA_MULTRET, fvalue(s2v(func)));
|
||||
case LUA_VLCL: { /* Lua function */
|
||||
Proto *p = clLvalue(s2v(func))->p;
|
||||
int fsize = p->maxstacksize; /* frame size */
|
||||
int nfixparams = p->numparams;
|
||||
int i;
|
||||
checkstackGCp(L, fsize - delta, func);
|
||||
ci->func -= delta; /* restore 'func' (if vararg) */
|
||||
for (i = 0; i < narg1; i++) /* move down function and arguments */
|
||||
setobjs2s(L, ci->func + i, func + i);
|
||||
checkstackGC(L, fsize);
|
||||
func = ci->func; /* moved-down function */
|
||||
for (; narg1 <= nfixparams; narg1++)
|
||||
setnilvalue(s2v(func + narg1)); /* complete missing arguments */
|
||||
@ -494,6 +542,15 @@ void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1) {
|
||||
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.
|
||||
*/
|
||||
CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) {
|
||||
lua_CFunction f;
|
||||
retry:
|
||||
switch (ttypetag(s2v(func))) {
|
||||
case LUA_VCCL: /* C closure */
|
||||
f = clCvalue(s2v(func))->f;
|
||||
goto Cfunc;
|
||||
case LUA_VLCF: /* light C function */
|
||||
f = 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);
|
||||
precallC(L, func, nresults, clCvalue(s2v(func))->f);
|
||||
return NULL;
|
||||
case LUA_VLCF: /* light C function */
|
||||
precallC(L, func, nresults, fvalue(s2v(func)));
|
||||
return NULL;
|
||||
}
|
||||
case LUA_VLCL: { /* Lua function */
|
||||
CallInfo *ci;
|
||||
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 fsize = p->maxstacksize; /* frame size */
|
||||
checkstackGCp(L, fsize, func);
|
||||
L->ci = ci = next_ci(L);
|
||||
ci->nresults = nresults;
|
||||
L->ci = ci = prepCallInfo(L, func, nresults, 0, func + 1 + fsize);
|
||||
ci->u.l.savedpc = p->code; /* starting point */
|
||||
ci->top = func + 1 + fsize;
|
||||
ci->func = func;
|
||||
L->ci = ci;
|
||||
for (; narg < nfixparams; narg++)
|
||||
setnilvalue(s2v(L->top++)); /* complete missing arguments */
|
||||
lua_assert(ci->top <= L->stack_last);
|
||||
return ci;
|
||||
}
|
||||
default: { /* not a function */
|
||||
checkstackGCp(L, 1, func); /* space for metamethod */
|
||||
luaD_tryfuncTM(L, func); /* try to get '__call' metamethod */
|
||||
func = luaD_tryfuncTM(L, func); /* try to get '__call' metamethod */
|
||||
/* return luaD_precall(L, func, nresults); */
|
||||
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
|
||||
** 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;
|
||||
L->nCcalls += inc;
|
||||
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 */
|
||||
CallInfo *ci = L->ci;
|
||||
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 */
|
||||
lua_assert(L->status == LUA_YIELD);
|
||||
L->status = LUA_OK; /* mark that it is running (again) */
|
||||
luaE_incCstack(L); /* control the C stack */
|
||||
if (isLua(ci)) { /* yielded inside a hook? */
|
||||
L->top = firstArg; /* discard arguments */
|
||||
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? */
|
||||
return resume_error(L, "cannot resume dead coroutine", nargs);
|
||||
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);
|
||||
api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : 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,
|
||||
int fTransfer, int nTransfer);
|
||||
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 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_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_pcall (lua_State *L, Pfunc func, void *u,
|
||||
ptrdiff_t oldtop, ptrdiff_t ef);
|
@ -906,18 +906,18 @@ static void GCTM (lua_State *L) {
|
||||
if (!notm(tm)) { /* is there a finalizer? */
|
||||
int status;
|
||||
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 */
|
||||
g->gcrunning = 0; /* avoid GC steps */
|
||||
setobj2s(L, L->top++, tm); /* push finalizer... */
|
||||
setobj2s(L, L->top++, &v); /* ... and its argument */
|
||||
L->ci->callstatus |= CIST_FIN; /* will run a finalizer */
|
||||
status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0);
|
||||
L->ci->callstatus &= ~CIST_FIN; /* not running a finalizer anymore */
|
||||
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? */
|
||||
luaE_warnerror(L, "__gc metamethod");
|
||||
luaE_warnerror(L, "__gc");
|
||||
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) {
|
||||
global_State *g = G(L);
|
||||
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 */
|
||||
else { /* move 'o' to 'finobj' list */
|
||||
GCObject **p;
|
||||
@ -1502,12 +1503,13 @@ static void deletelist (lua_State *L, GCObject *p, GCObject *limit) {
|
||||
*/
|
||||
void luaC_freeallobjects (lua_State *L) {
|
||||
global_State *g = G(L);
|
||||
g->gcstp = GCSTPCLS; /* no extra finalizers after here */
|
||||
luaC_changemode(L, KGC_INC);
|
||||
separatetobefnz(g, 1); /* separate all objects with finalizers */
|
||||
lua_assert(g->finobj == NULL);
|
||||
callallpendingfinalizers(L);
|
||||
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 */
|
||||
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
|
||||
** 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) {
|
||||
global_State *g = G(L);
|
||||
lua_assert(!g->gcemergency);
|
||||
if (g->gcrunning) { /* running? */
|
||||
if (gcrunning(g)) { /* running? */
|
||||
if(isdecGCmodegen(g))
|
||||
genstep(L, g);
|
||||
else
|
@ -148,6 +148,16 @@
|
||||
*/
|
||||
#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'
|
||||
** allows some adjustments to be done only when needed. macro
|
@ -165,6 +165,20 @@ typedef LUAI_UACINT l_uacInt;
|
||||
#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;
|
||||
** 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)
|
||||
#else
|
||||
#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
|
@ -475,7 +475,7 @@ static lua_Number I2d (Rand64 x) {
|
||||
|
||||
/* 2^(-FIGS) = 1.0 / 2^30 / 2^3 / 2^(FIGS-33) */
|
||||
#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
|
||||
@ -486,7 +486,7 @@ static lua_Number I2d (Rand64 x) {
|
||||
/*
|
||||
** 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) {
|
@ -164,7 +164,7 @@ static int isneg (const char **s) {
|
||||
*/
|
||||
static lua_Number lua_strx2number (const char *s, char **endptr) {
|
||||
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 nosigdig = 0; /* number of non-significant digits */
|
||||
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 */
|
||||
neg = isneg(&s); /* check sign */
|
||||
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 */
|
||||
if (*s == dot) {
|
||||
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)? */
|
||||
nosigdig++;
|
||||
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 */
|
||||
if (hasdot) e--; /* decimal digit? correct exponent */
|
||||
}
|
||||
else break; /* neither a dot nor a digit */
|
||||
}
|
||||
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 */
|
||||
e *= 4; /* each digit multiplies/divides value by 2^4 */
|
||||
if (*s == 'p' || *s == 'P') { /* exponent part? */
|
||||
@ -200,7 +200,7 @@ static lua_Number lua_strx2number (const char *s, char **endptr) {
|
||||
s++; /* skip 'p' */
|
||||
neg1 = isneg(&s); /* sign */
|
||||
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 */
|
||||
exp1 = exp1 * 10 + *(s++) - '0';
|
||||
if (neg1) exp1 = -exp1;
|
@ -68,7 +68,7 @@ typedef struct TValue {
|
||||
|
||||
|
||||
#define val_(o) ((o)->value_)
|
||||
#define valraw(o) (&val_(o))
|
||||
#define valraw(o) (val_(o))
|
||||
|
||||
|
||||
/* raw type tag of a TValue */
|
||||
@ -112,7 +112,7 @@ typedef struct TValue {
|
||||
#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) \
|
||||
{ TValue *io1=(obj1); const TValue *io2=(obj2); \
|
||||
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 {
|
||||
@ -203,7 +204,7 @@ OP_LOADF,/* A sBx R[A] := (lua_Number)sBx */
|
||||
OP_LOADK,/* A Bx R[A] := K[Bx] */
|
||||
OP_LOADKX,/* A R[A] := K[extra arg] */
|
||||
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_LOADNIL,/* A B R[A], R[A+1], ..., R[A+B] := nil */
|
||||
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_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_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_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_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:
|
||||
|
||||
(*) 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
|
||||
'top' is set to last_result+1, so next open instruction (OP_CALL,
|
||||
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
|
||||
** 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;
|
||||
adjust_assign(ls, 4, explist(ls, &e), &e);
|
||||
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 */
|
||||
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? */
|
||||
FuncState *fs = ls->fs;
|
||||
markupval(fs, level + 1);
|
||||
fs->bl->insidetbc = 1; /* in the scope of a to-be-closed variable */
|
||||
marktobeclosed(fs);
|
||||
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);
|
||||
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 */
|
||||
ismethod = funcname(ls, &v);
|
||||
body(ls, &b, ismethod, line);
|
||||
check_readonly(ls, &v);
|
||||
luaK_storevar(ls->fs, &v, &b);
|
||||
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)
|
||||
luaG_runerror(L, "C stack overflow");
|
||||
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);
|
||||
luaT_init(L);
|
||||
luaX_init(L);
|
||||
g->gcrunning = 1; /* allow gc */
|
||||
g->gcstp = 0; /* allow gc */
|
||||
setnilvalue(&g->nilvalue); /* now state is complete */
|
||||
luai_userstateopen(L);
|
||||
}
|
||||
@ -269,8 +269,9 @@ static void preinit_thread (lua_State *L, global_State *g) {
|
||||
static void close_state (lua_State *L) {
|
||||
global_State *g = G(L);
|
||||
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 */
|
||||
L->ci = &L->base_ci; /* unwind CallInfo list */
|
||||
luaD_closeprotected(L, 1, LUA_OK); /* close all upvalues */
|
||||
luaC_freeallobjects(L); /* collect all objects */
|
||||
luai_userstateclose(L);
|
||||
@ -330,13 +331,13 @@ int luaE_resetthread (lua_State *L, int status) {
|
||||
ci->callstatus = CIST_C;
|
||||
if (status == LUA_YIELD)
|
||||
status = LUA_OK;
|
||||
L->status = LUA_OK; /* so it can run __close metamethods */
|
||||
status = luaD_closeprotected(L, 1, status);
|
||||
if (status != LUA_OK) /* errors? */
|
||||
luaD_seterrorobj(L, status, L->stack + 1);
|
||||
else
|
||||
L->top = L->stack + 1;
|
||||
ci->top = L->top + LUA_MINSTACK;
|
||||
L->status = cast_byte(status);
|
||||
luaD_reallocstack(L, cast_int(ci->top - L->stack), 0);
|
||||
return status;
|
||||
}
|
||||
@ -372,7 +373,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
|
||||
g->ud_warn = NULL;
|
||||
g->mainthread = 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.hash = NULL;
|
||||
setnilvalue(&g->l_registry);
|
@ -165,7 +165,7 @@ typedef struct stringtable {
|
||||
** - field 'nyield' is used only while a function is "doing" an
|
||||
** yield (from the yield until the next resume);
|
||||
** - 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,
|
||||
** 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_TAIL (1<<5) /* call was tail called */
|
||||
#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_CLSRET (1<<9) /* function is closing tbc variables */
|
||||
/* 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 genminormul; /* control for minor 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 gcpause; /* size of pause between successive GCs */
|
||||
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 */
|
||||
#if !defined(L_FMTFLAGS)
|
||||
#define L_FMTFLAGS "-+ #0"
|
||||
#if !defined(L_FMTFLAGSF)
|
||||
|
||||
/* 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
|
||||
|
||||
|
||||
/*
|
||||
** 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
|
||||
|
||||
@ -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) {
|
||||
const char *p = strfrmt;
|
||||
while (*p != '\0' && strchr(L_FMTFLAGS, *p) != NULL) p++; /* skip flags */
|
||||
if ((size_t)(p - strfrmt) >= sizeof(L_FMTFLAGS)/sizeof(char))
|
||||
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) */
|
||||
static const char *get2digits (const char *s) {
|
||||
if (isdigit(uchar(*s))) {
|
||||
s++;
|
||||
if (isdigit(uchar(*s))) s++; /* (2 digits at most) */
|
||||
}
|
||||
if (isdigit(uchar(*p)))
|
||||
luaL_error(L, "invalid format (width or precision too long)");
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** 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++) = '%';
|
||||
memcpy(form, strfrmt, ((p - strfrmt) + 1) * sizeof(char));
|
||||
form += (p - strfrmt) + 1;
|
||||
*form = '\0';
|
||||
return p;
|
||||
memcpy(form, strfrmt, len * sizeof(char));
|
||||
*(form + len) = '\0';
|
||||
return strfrmt + len - 1;
|
||||
}
|
||||
|
||||
|
||||
@ -1230,6 +1276,7 @@ static int str_format (lua_State *L) {
|
||||
size_t sfl;
|
||||
const char *strfrmt = luaL_checklstring(L, arg, &sfl);
|
||||
const char *strfrmt_end = strfrmt+sfl;
|
||||
const char *flags;
|
||||
luaL_Buffer b;
|
||||
luaL_buffinit(L, &b);
|
||||
while (strfrmt < strfrmt_end) {
|
||||
@ -1239,25 +1286,35 @@ static int str_format (lua_State *L) {
|
||||
luaL_addchar(&b, *strfrmt++); /* %% */
|
||||
else { /* format item */
|
||||
char form[MAX_FORMAT]; /* to store the format ('%...') */
|
||||
int maxitem = MAX_ITEM;
|
||||
char *buff = luaL_prepbuffsize(&b, maxitem); /* to put formatted item */
|
||||
int nb = 0; /* number of bytes in added item */
|
||||
int maxitem = MAX_ITEM; /* maximum length for the result */
|
||||
char *buff = luaL_prepbuffsize(&b, maxitem); /* to put result */
|
||||
int nb = 0; /* number of bytes in result */
|
||||
if (++arg > top)
|
||||
return luaL_argerror(L, arg, "no value");
|
||||
strfrmt = scanformat(L, strfrmt, form);
|
||||
strfrmt = getformat(L, strfrmt, form);
|
||||
switch (*strfrmt++) {
|
||||
case 'c': {
|
||||
checkformat(L, form, L_FMTFLAGSC, 0);
|
||||
nb = l_sprintf(buff, maxitem, form, (int)luaL_checkinteger(L, arg));
|
||||
break;
|
||||
}
|
||||
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);
|
||||
checkformat(L, form, flags, 1);
|
||||
addlenmod(form, LUA_INTEGER_FRMLEN);
|
||||
nb = l_sprintf(buff, maxitem, form, (LUAI_UACINT)n);
|
||||
break;
|
||||
}
|
||||
case 'a': case 'A':
|
||||
checkformat(L, form, L_FMTFLAGSF, 1);
|
||||
addlenmod(form, LUA_NUMBER_FRMLEN);
|
||||
nb = lua_number2strx(L, buff, maxitem, form,
|
||||
luaL_checknumber(L, arg));
|
||||
@ -1268,12 +1325,14 @@ static int str_format (lua_State *L) {
|
||||
/* FALLTHROUGH */
|
||||
case 'e': case 'E': case 'g': case 'G': {
|
||||
lua_Number n = luaL_checknumber(L, arg);
|
||||
checkformat(L, form, L_FMTFLAGSF, 1);
|
||||
addlenmod(form, LUA_NUMBER_FRMLEN);
|
||||
nb = l_sprintf(buff, maxitem, form, (LUAI_UACNUMBER)n);
|
||||
break;
|
||||
}
|
||||
case 'p': {
|
||||
const void *p = lua_topointer(L, arg);
|
||||
checkformat(L, form, L_FMTFLAGSC, 0);
|
||||
if (p == NULL) { /* avoid calling 'printf' with argument NULL */
|
||||
p = "(null)"; /* result */
|
||||
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 */
|
||||
else {
|
||||
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 */
|
||||
luaL_addvalue(&b); /* keep entire string */
|
||||
}
|
||||
@ -1352,15 +1412,6 @@ static const union {
|
||||
} 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
|
||||
*/
|
||||
@ -1435,6 +1486,8 @@ static void initheader (lua_State *L, Header *h) {
|
||||
** Read and classify next option. 'size' is filled with option's 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)++);
|
||||
*size = 0; /* default */
|
||||
switch (opt) {
|
||||
@ -1465,7 +1518,11 @@ static KOption getoption (Header *h, const char **fmt, int *size) {
|
||||
case '<': h->islittle = 1; break;
|
||||
case '>': h->islittle = 0; 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);
|
||||
}
|
||||
return Knop;
|
@ -84,8 +84,6 @@
|
||||
#define hashstr(t,str) hashpow2(t, (str)->hash)
|
||||
#define hashboolean(t,p) hashpow2(t, p)
|
||||
|
||||
#define hashint(t,i) hashpow2(t, i)
|
||||
|
||||
|
||||
#define hashpointer(t,p) hashmod(t, point2uint(p))
|
||||
|
||||
@ -101,6 +99,20 @@ static const Node dummynode_ = {
|
||||
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.
|
||||
@ -134,26 +146,24 @@ static int l_hashfloat (lua_Number n) {
|
||||
|
||||
/*
|
||||
** 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'
|
||||
** and value in 'vkl') so that we can call it on keys inserted into
|
||||
** nodes.
|
||||
** the index of its hash value).
|
||||
*/
|
||||
static Node *mainposition (const Table *t, int ktt, const Value *kvl) {
|
||||
switch (withvariant(ktt)) {
|
||||
static Node *mainpositionTV (const Table *t, const TValue *key) {
|
||||
switch (ttypetag(key)) {
|
||||
case LUA_VNUMINT: {
|
||||
lua_Integer key = ivalueraw(*kvl);
|
||||
return hashint(t, key);
|
||||
lua_Integer i = ivalue(key);
|
||||
return hashint(t, i);
|
||||
}
|
||||
case LUA_VNUMFLT: {
|
||||
lua_Number n = fltvalueraw(*kvl);
|
||||
lua_Number n = fltvalue(key);
|
||||
return hashmod(t, l_hashfloat(n));
|
||||
}
|
||||
case LUA_VSHRSTR: {
|
||||
TString *ts = tsvalueraw(*kvl);
|
||||
TString *ts = tsvalue(key);
|
||||
return hashstr(t, ts);
|
||||
}
|
||||
case LUA_VLNGSTR: {
|
||||
TString *ts = tsvalueraw(*kvl);
|
||||
TString *ts = tsvalue(key);
|
||||
return hashpow2(t, luaS_hashlongstr(ts));
|
||||
}
|
||||
case LUA_VFALSE:
|
||||
@ -161,26 +171,25 @@ static Node *mainposition (const Table *t, int ktt, const Value *kvl) {
|
||||
case LUA_VTRUE:
|
||||
return hashboolean(t, 1);
|
||||
case LUA_VLIGHTUSERDATA: {
|
||||
void *p = pvalueraw(*kvl);
|
||||
void *p = pvalue(key);
|
||||
return hashpointer(t, p);
|
||||
}
|
||||
case LUA_VLCF: {
|
||||
lua_CFunction f = fvalueraw(*kvl);
|
||||
lua_CFunction f = fvalue(key);
|
||||
return hashpointer(t, f);
|
||||
}
|
||||
default: {
|
||||
GCObject *o = gcvalueraw(*kvl);
|
||||
GCObject *o = gcvalue(key);
|
||||
return hashpointer(t, o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Returns the main position of an element given as a 'TValue'
|
||||
*/
|
||||
static Node *mainpositionTV (const Table *t, const TValue *key) {
|
||||
return mainposition(t, rawtt(key), valraw(key));
|
||||
l_sinline Node *mainpositionfromnode (const Table *t, Node *nd) {
|
||||
TValue key;
|
||||
getnodekey(cast(lua_State *, NULL), &key, nd);
|
||||
return mainpositionTV(t, &key);
|
||||
}
|
||||
|
||||
|
||||
@ -679,7 +688,7 @@ void luaH_newkey (lua_State *L, Table *t, const TValue *key, TValue *value) {
|
||||
return;
|
||||
}
|
||||
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? */
|
||||
/* yes; move colliding node into free position */
|
||||
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) {
|
||||
lua_Integer e = aux_getn(L, 1, TAB_RW) + 1; /* first empty 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)) {
|
||||
case 2: { /* called with only 2 arguments */
|
||||
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);
|
||||
if (l_unlikely(!lua_isstring(L, -1)))
|
||||
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);
|
||||
}
|
||||
|
@ -91,7 +91,8 @@ static void print_usage (const char *badoption) {
|
||||
"Available options are:\n"
|
||||
" -e stat execute string 'stat'\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"
|
||||
" -l g=mod require library 'mod' into global 'g'\n"
|
||||
" -v show version information\n"
|
||||
" -E ignore environment variables\n"
|
||||
" -W turn warnings on\n"
|
||||
@ -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
|
||||
** with the given name.
|
||||
** Receives 'globname[=modname]' and runs 'globname = require(modname)'.
|
||||
*/
|
||||
static int dolibrary (lua_State *L, const char *name) {
|
||||
static int dolibrary (lua_State *L, char *globname) {
|
||||
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_pushstring(L, name);
|
||||
status = docall(L, 1, 1); /* call 'require(name)' */
|
||||
lua_pushstring(L, modname);
|
||||
status = docall(L, 1, 1); /* call 'require(modname)' */
|
||||
if (status == LUA_OK)
|
||||
lua_setglobal(L, name); /* global[name] = require return */
|
||||
lua_setglobal(L, globname); /* globname = require(modname) */
|
||||
return report(L, status);
|
||||
}
|
||||
|
||||
@ -327,7 +334,7 @@ static int runargs (lua_State *L, char **argv, int n) {
|
||||
switch (option) {
|
||||
case 'e': case 'l': {
|
||||
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];
|
||||
lua_assert(extra != NULL);
|
||||
status = (option == 'e')
|
@ -155,6 +155,7 @@ static const Proto* combine(lua_State* L, int n)
|
||||
f->p[i]=toproto(L,i-n-1);
|
||||
if (f->p[i]->sizeupvalues>0) f->p[i]->upvalues[0].instack=0;
|
||||
}
|
||||
luaM_freearray(L,f->lineinfo,f->sizelineinfo);
|
||||
f->sizelineinfo=0;
|
||||
return f;
|
||||
}
|
||||
@ -600,11 +601,11 @@ static void PrintCode(const Proto* f)
|
||||
if (c==0) printf("all out"); else printf("%d out",c-1);
|
||||
break;
|
||||
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);
|
||||
break;
|
||||
case OP_RETURN:
|
||||
printf("%d %d %d",a,b,c);
|
||||
printf("%d %d %d%s",a,b,c,ISK);
|
||||
printf(COMMENT);
|
||||
if (b==0) printf("all out"); else printf("%d out",b-1);
|
||||
break;
|
||||
@ -619,7 +620,7 @@ static void PrintCode(const Proto* f)
|
||||
break;
|
||||
case OP_FORPREP:
|
||||
printf("%d %d",a,bx);
|
||||
printf(COMMENT "to %d",pc+bx+2);
|
||||
printf(COMMENT "exit to %d",pc+bx+3);
|
||||
break;
|
||||
case OP_TFORPREP:
|
||||
printf("%d %d",a,bx);
|
@ -224,14 +224,11 @@ static int byteoffset (lua_State *L) {
|
||||
static int iter_aux (lua_State *L, int strict) {
|
||||
size_t len;
|
||||
const char *s = luaL_checklstring(L, 1, &len);
|
||||
lua_Integer n = lua_tointeger(L, 2) - 1;
|
||||
if (n < 0) /* first iteration? */
|
||||
n = 0; /* start from here */
|
||||
else if (n < (lua_Integer)len) {
|
||||
n++; /* skip current byte */
|
||||
while (iscont(s + n)) n++; /* and its continuations */
|
||||
lua_Unsigned n = (lua_Unsigned)lua_tointeger(L, 2);
|
||||
if (n < len) {
|
||||
while (iscont(s + n)) n++; /* skip continuation bytes */
|
||||
}
|
||||
if (n >= (lua_Integer)len)
|
||||
if (n >= len) /* (also handles original 'n' being negative) */
|
||||
return 0; /* no more codepoints */
|
||||
else {
|
||||
utfint code;
|
@ -406,7 +406,7 @@ static int l_strcmp (const TString *ls, const TString *rs) {
|
||||
** from float to int.)
|
||||
** 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))
|
||||
return luai_numlt(cast_num(i), f); /* compare them as floats */
|
||||
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'.
|
||||
** 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))
|
||||
return luai_numle(cast_num(i), f); /* compare them as floats */
|
||||
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'.
|
||||
** 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))
|
||||
return luai_numlt(f, cast_num(i)); /* compare them as floats */
|
||||
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'.
|
||||
** 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))
|
||||
return luai_numle(f, cast_num(i)); /* compare them as floats */
|
||||
else { /* f <= i <=> ceil(f) <= i */
|
||||
@ -473,7 +473,7 @@ static int LEfloatint (lua_Number f, lua_Integer i) {
|
||||
/*
|
||||
** 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));
|
||||
if (ttisinteger(l)) {
|
||||
lua_Integer li = ivalue(l);
|
||||
@ -495,7 +495,7 @@ static int LTnum (const TValue *l, const TValue *r) {
|
||||
/*
|
||||
** 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));
|
||||
if (ttisinteger(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'.)
|
||||
*/
|
||||
#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) {
|
||||
if (y < 0) { /* shift right? */
|
||||
@ -847,10 +848,19 @@ void luaV_finishOp (lua_State *L) {
|
||||
luaV_concat(L, total); /* concat them (may yield again) */
|
||||
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. */
|
||||
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: {
|
||||
/* only these other opcodes can yield */
|
||||
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))
|
||||
|
||||
/*
|
||||
** 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.)
|
||||
*/
|
||||
#define halfProtect(exp) (savestate(L,ci), (exp))
|
||||
@ -1156,8 +1166,10 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||
Instruction i; /* instruction being executed */
|
||||
StkId ra; /* instruction's A register */
|
||||
vmfetch();
|
||||
// low-level line tracing for debugging Lua
|
||||
// printf("line: %d\n", luaG_getfuncline(cl->p, pcRel(pc, cl->p)));
|
||||
#if 0
|
||||
/* 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 <= L->top && L->top < L->stack_last);
|
||||
/* 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 */
|
||||
else { /* Lua call: run function in this same C frame */
|
||||
ci = newci;
|
||||
ci->callstatus = 0; /* call re-uses 'luaV_execute' */
|
||||
goto startfunc;
|
||||
}
|
||||
vmbreak;
|
||||
}
|
||||
vmcase(OP_TAILCALL) {
|
||||
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);
|
||||
/* delta is virtual 'func' - real 'func' (vararg functions) */
|
||||
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(base == ci->func + 1);
|
||||
}
|
||||
while (!ttisfunction(s2v(ra))) { /* not a function? */
|
||||
luaD_tryfuncTM(L, ra); /* try '__call' metamethod */
|
||||
b++; /* there is now one extra argument */
|
||||
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 */
|
||||
if ((n = luaD_pretailcall(L, ci, ra, b, delta)) < 0) /* Lua function? */
|
||||
goto startfunc; /* execute the callee */
|
||||
else { /* C function? */
|
||||
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 */
|
||||
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) {
|
||||
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 */
|
||||
savepc(ci);
|
||||
if (TESTARG_k(i)) { /* may there be open upvalues? */
|
||||
ci->u2.nres = n; /* save number of returns */
|
||||
if (L->top < ci->top)
|
||||
L->top = ci->top;
|
||||
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