Lua 5.4.7
This commit is contained in:
parent
38b1d3a4e3
commit
a59883b3c1
2
Makefile
2
Makefile
@ -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.6
|
R= $V.7
|
||||||
|
|
||||||
# Targets start here.
|
# Targets start here.
|
||||||
all: $(PLAT)
|
all: $(PLAT)
|
||||||
|
2
README
2
README
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
This is Lua 5.4.6, released on 02 May 2023.
|
This is Lua 5.4.7, released on 13 Jun 2024.
|
||||||
|
|
||||||
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.
|
||||||
|
BIN
doc/OSIApproved_100X125.png
Normal file
BIN
doc/OSIApproved_100X125.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
@ -10,7 +10,7 @@
|
|||||||
<BODY>
|
<BODY>
|
||||||
|
|
||||||
<H1>
|
<H1>
|
||||||
<A HREF="http://www.lua.org/"><IMG SRC="logo.gif" ALT="Lua"></A>
|
<A HREF="https://www.lua.org/"><IMG SRC="logo.gif" ALT="Lua"></A>
|
||||||
Lua 5.4 Reference Manual
|
Lua 5.4 Reference Manual
|
||||||
</H1>
|
</H1>
|
||||||
|
|
||||||
@ -18,7 +18,7 @@ Lua 5.4 Reference Manual
|
|||||||
The reference manual is the official definition of the Lua language.
|
The reference manual is the official definition of the Lua language.
|
||||||
<BR>
|
<BR>
|
||||||
For a complete introduction to Lua programming, see the book
|
For a complete introduction to Lua programming, see the book
|
||||||
<A HREF="http://www.lua.org/pil/">Programming in Lua</A>.
|
<A HREF="https://www.lua.org/pil/">Programming in Lua</A>.
|
||||||
|
|
||||||
<DIV CLASS="menubar">
|
<DIV CLASS="menubar">
|
||||||
<A HREF="manual.html">start</A>
|
<A HREF="manual.html">start</A>
|
||||||
@ -27,14 +27,14 @@ For a complete introduction to Lua programming, see the book
|
|||||||
·
|
·
|
||||||
<A HREF="#index">index</A>
|
<A HREF="#index">index</A>
|
||||||
·
|
·
|
||||||
<A HREF="http://www.lua.org/manual/">other versions</A>
|
<A HREF="https://www.lua.org/manual/">other versions</A>
|
||||||
</DIV>
|
</DIV>
|
||||||
|
|
||||||
<P>
|
<P>
|
||||||
<SMALL>
|
<SMALL>
|
||||||
Copyright © 2020–2023 Lua.org, PUC-Rio.
|
Copyright © 2020–2024 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="https://www.lua.org/license.html">Lua license</A>.
|
||||||
</SMALL>
|
</SMALL>
|
||||||
|
|
||||||
<H2><A NAME="contents">Contents</A></H2>
|
<H2><A NAME="contents">Contents</A></H2>
|
||||||
@ -668,10 +668,10 @@ Freely available under the terms of the
|
|||||||
|
|
||||||
<P CLASS="footer">
|
<P CLASS="footer">
|
||||||
Last update:
|
Last update:
|
||||||
Sat Apr 1 17:57:05 UTC 2023
|
Thu May 9 14:47:09 UTC 2024
|
||||||
</P>
|
</P>
|
||||||
<!--
|
<!--
|
||||||
Last change: revised for Lua 5.4.5
|
Last change: revised for Lua 5.4.7
|
||||||
-->
|
-->
|
||||||
|
|
||||||
</BODY>
|
</BODY>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.\" $Id: lua.man,v 1.14 2022/09/23 09:06:36 lhf Exp $
|
.\" $Id: lua.man,v 1.14 2024/05/08 18:48:27 lhf Exp $
|
||||||
.TH LUA 1 "$Date: 2022/09/23 09:06:36 $"
|
.TH LUA 1 "$Date: 2024/05/08 18:48:27 $"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
lua \- Lua interpreter
|
lua \- Lua interpreter
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -123,7 +123,7 @@ and the version-neutral variants are ignored.
|
|||||||
Code to be executed before command line options and scripts.
|
Code to be executed before command line options and scripts.
|
||||||
.TP
|
.TP
|
||||||
.B LUA_PATH, LUA_PATH_5_4
|
.B LUA_PATH, LUA_PATH_5_4
|
||||||
Initial value of package.cpath,
|
Initial value of package.path,
|
||||||
the path used by require to search for Lua loaders.
|
the path used by require to search for Lua loaders.
|
||||||
.TP
|
.TP
|
||||||
.B LUA_CPATH, LUA_CPATH_5_4
|
.B LUA_CPATH, LUA_CPATH_5_4
|
||||||
|
@ -143,6 +143,7 @@ table.book td.cover {
|
|||||||
|
|
||||||
table.book img {
|
table.book img {
|
||||||
border: solid #000080 1px ;
|
border: solid #000080 1px ;
|
||||||
|
border-radius: 2px ;
|
||||||
}
|
}
|
||||||
|
|
||||||
table.book span {
|
table.book span {
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
<BODY>
|
<BODY>
|
||||||
|
|
||||||
<H1>
|
<H1>
|
||||||
<A HREF="http://www.lua.org/"><IMG SRC="logo.gif" ALT="Lua"></A>
|
<A HREF="https://www.lua.org/"><IMG SRC="logo.gif" ALT="Lua"></A>
|
||||||
Lua 5.4 Reference Manual
|
Lua 5.4 Reference Manual
|
||||||
</H1>
|
</H1>
|
||||||
|
|
||||||
@ -19,9 +19,9 @@ by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes
|
|||||||
|
|
||||||
<P>
|
<P>
|
||||||
<SMALL>
|
<SMALL>
|
||||||
Copyright © 2020–2023 Lua.org, PUC-Rio.
|
Copyright © 2020–2024 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="https://www.lua.org/license.html">Lua license</a>.
|
||||||
</SMALL>
|
</SMALL>
|
||||||
|
|
||||||
<DIV CLASS="menubar">
|
<DIV CLASS="menubar">
|
||||||
@ -29,7 +29,7 @@ Freely available under the terms of the
|
|||||||
·
|
·
|
||||||
<A HREF="contents.html#index">index</A>
|
<A HREF="contents.html#index">index</A>
|
||||||
·
|
·
|
||||||
<A HREF="http://www.lua.org/manual/">other versions</A>
|
<A HREF="https://www.lua.org/manual/">other versions</A>
|
||||||
</DIV>
|
</DIV>
|
||||||
|
|
||||||
<!-- ====================================================================== -->
|
<!-- ====================================================================== -->
|
||||||
@ -391,7 +391,7 @@ Whenever there is an error,
|
|||||||
an <em>error object</em>
|
an <em>error object</em>
|
||||||
is propagated with information about the error.
|
is propagated with information about the error.
|
||||||
Lua itself only generates errors whose error object is a string,
|
Lua itself only generates errors whose error object is a string,
|
||||||
but programs may generate errors with
|
but programs can generate errors with
|
||||||
any value as the error object.
|
any value as the error object.
|
||||||
It is up to the Lua program or its host to handle such error objects.
|
It is up to the Lua program or its host to handle such error objects.
|
||||||
For historical reasons,
|
For historical reasons,
|
||||||
@ -401,7 +401,7 @@ even though it does not have to be a string.
|
|||||||
|
|
||||||
<p>
|
<p>
|
||||||
When you use <a href="#pdf-xpcall"><code>xpcall</code></a> (or <a href="#lua_pcall"><code>lua_pcall</code></a>, in C)
|
When you use <a href="#pdf-xpcall"><code>xpcall</code></a> (or <a href="#lua_pcall"><code>lua_pcall</code></a>, in C)
|
||||||
you may give a <em>message handler</em>
|
you can give a <em>message handler</em>
|
||||||
to be called in case of errors.
|
to be called in case of errors.
|
||||||
This function is called with the original error object
|
This function is called with the original error object
|
||||||
and returns a new error object.
|
and returns a new error object.
|
||||||
@ -453,7 +453,7 @@ which is then called a <em>metamethod</em>.
|
|||||||
In the previous example, the key is the string "<code>__add</code>"
|
In the previous example, the key is the string "<code>__add</code>"
|
||||||
and the metamethod is the function that performs the addition.
|
and the metamethod is the function that performs the addition.
|
||||||
Unless stated otherwise,
|
Unless stated otherwise,
|
||||||
a metamethod may in fact be any callable value,
|
a metamethod can in fact be any callable value,
|
||||||
which is either a function or a value with a <code>__call</code> metamethod.
|
which is either a function or a value with a <code>__call</code> metamethod.
|
||||||
|
|
||||||
|
|
||||||
@ -1725,7 +1725,7 @@ labels in Lua are considered statements too:
|
|||||||
<p>
|
<p>
|
||||||
A label is visible in the entire block where it is defined,
|
A label is visible in the entire block where it is defined,
|
||||||
except inside nested functions.
|
except inside nested functions.
|
||||||
A goto may jump to any visible label as long as it does not
|
A goto can jump to any visible label as long as it does not
|
||||||
enter into the scope of a local variable.
|
enter into the scope of a local variable.
|
||||||
A label should not be declared
|
A label should not be declared
|
||||||
where a label with the same name is visible,
|
where a label with the same name is visible,
|
||||||
@ -5571,7 +5571,7 @@ otherwise, returns <code>NULL</code>.
|
|||||||
|
|
||||||
|
|
||||||
<hr><h3><a name="lua_toclose"><code>lua_toclose</code></a></h3><p>
|
<hr><h3><a name="lua_toclose"><code>lua_toclose</code></a></h3><p>
|
||||||
<span class="apii">[-0, +0, <em>m</em>]</span>
|
<span class="apii">[-0, +0, <em>v</em>]</span>
|
||||||
<pre>void lua_toclose (lua_State *L, int index);</pre>
|
<pre>void lua_toclose (lua_State *L, int index);</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@ -5591,6 +5591,11 @@ by any other function in the API except <a href="#lua_settop"><code>lua_settop</
|
|||||||
unless previously deactivated by <a href="#lua_closeslot"><code>lua_closeslot</code></a>.
|
unless previously deactivated by <a href="#lua_closeslot"><code>lua_closeslot</code></a>.
|
||||||
|
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This function raises an error if the value at the given slot
|
||||||
|
neither has a <code>__close</code> metamethod nor is a false value.
|
||||||
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
This function should not be called for an index
|
This function should not be called for an index
|
||||||
that is equal to or below an active to-be-closed slot.
|
that is equal to or below an active to-be-closed slot.
|
||||||
@ -5664,6 +5669,12 @@ after its last character (as in C),
|
|||||||
but can contain other zeros in its body.
|
but can contain other zeros in its body.
|
||||||
|
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This function can raise memory errors only
|
||||||
|
when converting a number to a string
|
||||||
|
(as then it may create a new string).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -11276,13 +11287,13 @@ The returned table can contain all the fields returned by <a href="#lua_getinfo"
|
|||||||
with the string <code>what</code> describing which fields to fill in.
|
with the string <code>what</code> describing which fields to fill in.
|
||||||
The default for <code>what</code> is to get all information available,
|
The default for <code>what</code> is to get all information available,
|
||||||
except the table of valid lines.
|
except the table of valid lines.
|
||||||
If present,
|
The option '<code>f</code>'
|
||||||
the option '<code>f</code>'
|
|
||||||
adds a field named <code>func</code> with the function itself.
|
adds a field named <code>func</code> with the function itself.
|
||||||
If present,
|
The option '<code>L</code>' adds a field named <code>activelines</code>
|
||||||
the option '<code>L</code>'
|
with the table of valid lines,
|
||||||
adds a field named <code>activelines</code> with the table of
|
provided the function is a Lua function.
|
||||||
valid lines.
|
If the function has no debug information,
|
||||||
|
the table is empty.
|
||||||
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@ -11619,6 +11630,10 @@ Lua does not consult any environment variables.
|
|||||||
In particular,
|
In particular,
|
||||||
the values of <a href="#pdf-package.path"><code>package.path</code></a> and <a href="#pdf-package.cpath"><code>package.cpath</code></a>
|
the values of <a href="#pdf-package.path"><code>package.path</code></a> and <a href="#pdf-package.cpath"><code>package.cpath</code></a>
|
||||||
are set with the default paths defined in <code>luaconf.h</code>.
|
are set with the default paths defined in <code>luaconf.h</code>.
|
||||||
|
To signal to the libraries that this option is on,
|
||||||
|
the stand-alone interpreter sets the field
|
||||||
|
<code>"LUA_NOENV"</code> in the registry to a true value.
|
||||||
|
Other libraries may consult this field for the same purpose.
|
||||||
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@ -12033,13 +12048,12 @@ and LiteralString, see <a href="#3.1">§3.1</a>.)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<P CLASS="footer">
|
<P CLASS="footer">
|
||||||
Last update:
|
Last update:
|
||||||
Tue May 2 20:09:38 UTC 2023
|
Thu Jun 13 22:15:52 UTC 2024
|
||||||
</P>
|
</P>
|
||||||
<!--
|
<!--
|
||||||
Last change: revised for Lua 5.4.6
|
Last change: revised for Lua 5.4.7
|
||||||
-->
|
-->
|
||||||
|
|
||||||
</body></html>
|
</body></html>
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 3.7 KiB |
@ -29,7 +29,7 @@ tt, kbd, code {
|
|||||||
<BODY>
|
<BODY>
|
||||||
|
|
||||||
<H1>
|
<H1>
|
||||||
<A HREF="http://www.lua.org/"><IMG SRC="logo.gif" ALT="Lua"></A>
|
<A HREF="https://www.lua.org/"><IMG SRC="logo.gif" ALT="Lua"></A>
|
||||||
Welcome to Lua 5.4
|
Welcome to Lua 5.4
|
||||||
</H1>
|
</H1>
|
||||||
|
|
||||||
@ -49,29 +49,31 @@ Welcome to Lua 5.4
|
|||||||
<P>
|
<P>
|
||||||
Lua is a powerful, efficient, lightweight, embeddable scripting language
|
Lua is a powerful, efficient, lightweight, embeddable scripting language
|
||||||
developed by a
|
developed by a
|
||||||
<A HREF="http://www.lua.org/authors.html">team</A>
|
<A HREF="https://www.lua.org/authors.html">team</A>
|
||||||
at
|
at
|
||||||
<A HREF="http://www.puc-rio.br/">PUC-Rio</A>,
|
<A HREF="https://www.puc-rio.br/">PUC-Rio</A>,
|
||||||
the Pontifical Catholic University of Rio de Janeiro in Brazil.
|
the Pontifical Catholic University of Rio de Janeiro in Brazil.
|
||||||
Lua is
|
Lua is
|
||||||
<A HREF="#license">free software</A>
|
<A HREF="#license">free software</A>
|
||||||
used in
|
used in
|
||||||
<A HREF="http://www.lua.org/uses.html">many products and projects</A>
|
<A HREF="https://www.lua.org/uses.html">many products and projects</A>
|
||||||
around the world.
|
around the world.
|
||||||
|
|
||||||
<P>
|
<P>
|
||||||
Lua's
|
Lua's
|
||||||
<A HREF="http://www.lua.org/">official web site</A>
|
<A HREF="https://www.lua.org/">official website</A>
|
||||||
provides complete information
|
provides complete information
|
||||||
about Lua,
|
about Lua,
|
||||||
including
|
including
|
||||||
an
|
an
|
||||||
<A HREF="http://www.lua.org/about.html">executive summary</A>
|
<A HREF="https://www.lua.org/about.html">executive summary</A>,
|
||||||
|
tips on
|
||||||
|
<A HREF="https://www.lua.org/start.html">getting started</A>,
|
||||||
and
|
and
|
||||||
updated
|
updated
|
||||||
<A HREF="http://www.lua.org/docs.html">documentation</A>,
|
<A HREF="https://www.lua.org/docs.html">documentation</A>,
|
||||||
especially the
|
especially the
|
||||||
<A HREF="http://www.lua.org/manual/5.4/">reference manual</A>,
|
<A HREF="https://www.lua.org/manual/5.4/">reference manual</A>,
|
||||||
which may differ slightly from the
|
which may differ slightly from the
|
||||||
<A HREF="contents.html">local copy</A>
|
<A HREF="contents.html">local copy</A>
|
||||||
distributed in this package.
|
distributed in this package.
|
||||||
@ -79,7 +81,7 @@ distributed in this package.
|
|||||||
<H2><A NAME="install">Installing Lua</A></H2>
|
<H2><A NAME="install">Installing Lua</A></H2>
|
||||||
<P>
|
<P>
|
||||||
Lua is distributed in
|
Lua is distributed in
|
||||||
<A HREF="http://www.lua.org/ftp/">source</A>
|
<A HREF="https://www.lua.org/ftp/">source</A>
|
||||||
form.
|
form.
|
||||||
You need to build it before using it.
|
You need to build it before using it.
|
||||||
Building Lua should be straightforward
|
Building Lua should be straightforward
|
||||||
@ -88,7 +90,7 @@ Lua is implemented in pure ANSI C and compiles unmodified in all known
|
|||||||
platforms that have an ANSI C compiler.
|
platforms that have an ANSI C compiler.
|
||||||
Lua also compiles unmodified as C++.
|
Lua also compiles unmodified as C++.
|
||||||
The instructions given below for building Lua are for Unix-like platforms,
|
The instructions given below for building Lua are for Unix-like platforms,
|
||||||
such as Linux and Mac OS X.
|
such as Linux and macOS.
|
||||||
See also
|
See also
|
||||||
<A HREF="#other">instructions for other systems</A>
|
<A HREF="#other">instructions for other systems</A>
|
||||||
and
|
and
|
||||||
@ -97,7 +99,7 @@ and
|
|||||||
<P>
|
<P>
|
||||||
If you don't have the time or the inclination to compile Lua yourself,
|
If you don't have the time or the inclination to compile Lua yourself,
|
||||||
get a binary from
|
get a binary from
|
||||||
<A HREF="http://lua-users.org/wiki/LuaBinaries">LuaBinaries</A>.
|
<A HREF="https://luabinaries.sourceforge.net">LuaBinaries</A>.
|
||||||
|
|
||||||
<H3>Building Lua</H3>
|
<H3>Building Lua</H3>
|
||||||
<P>
|
<P>
|
||||||
@ -107,7 +109,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.6</TT>.
|
the top-level directory, which is named <TT>lua-5.4.7</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>
|
||||||
@ -211,8 +213,8 @@ then try "<KBD>make linux-readline MYLIBS=-ltermcap</KBD>".
|
|||||||
record the changes you've made.
|
record the changes you've made.
|
||||||
|
|
||||||
<P>
|
<P>
|
||||||
On the other hand, if you need to customize some Lua features, you'll need
|
On the other hand, if you need to customize some Lua features,
|
||||||
to edit <TT>src/luaconf.h</TT> before building and installing Lua.
|
edit <TT>src/luaconf.h</TT> before building and installing Lua.
|
||||||
The edited file will be the one installed, and
|
The edited file will be the one installed, and
|
||||||
it will be used by any Lua clients that you build, to ensure consistency.
|
it will be used by any Lua clients that you build, to ensure consistency.
|
||||||
Further customization is available to experts by editing the Lua sources.
|
Further customization is available to experts by editing the Lua sources.
|
||||||
@ -241,7 +243,7 @@ compiler:
|
|||||||
</DL>
|
</DL>
|
||||||
|
|
||||||
<P>
|
<P>
|
||||||
To use Lua as a library in your own programs, you'll need to know how to
|
To use Lua as a library in your own programs, you need to know how to
|
||||||
create and use libraries with your compiler. Moreover, to dynamically load
|
create and use libraries with your compiler. Moreover, to dynamically load
|
||||||
C libraries for Lua, you'll need to know how to create dynamic libraries
|
C libraries for Lua, you'll need to know how to create dynamic libraries
|
||||||
and you'll need to make sure that the Lua API functions are accessible to
|
and you'll need to make sure that the Lua API functions are accessible to
|
||||||
@ -284,11 +286,11 @@ lists the
|
|||||||
|
|
||||||
<H2><A NAME="license">License</A></H2>
|
<H2><A NAME="license">License</A></H2>
|
||||||
<P>
|
<P>
|
||||||
<A HREF="http://www.opensource.org/docs/definition.php">
|
<A HREF="https://opensource.org/osd">
|
||||||
<IMG SRC="osi-certified-72x60.png" ALIGN="right" ALT="[osi certified]" STYLE="padding-left: 30px ;">
|
<IMG SRC="OSIApproved_100X125.png" ALIGN="right" ALT="[Open Source Initiative Approved License]" STYLE="padding-left: 1em" WIDTH=50>
|
||||||
</A>
|
</A>
|
||||||
Lua is free software distributed under the terms of the
|
Lua is free software distributed under the terms of the
|
||||||
<A HREF="http://www.opensource.org/licenses/mit-license.html">MIT license</A>
|
<A HREF="https://opensource.org/license/mit">MIT license</A>
|
||||||
reproduced below;
|
reproduced below;
|
||||||
it may be used for any purpose, including commercial purposes,
|
it may be used for any purpose, including commercial purposes,
|
||||||
at absolutely no cost without having to ask us.
|
at absolutely no cost without having to ask us.
|
||||||
@ -296,11 +298,11 @@ at absolutely no cost without having to ask us.
|
|||||||
The only requirement is that if you do use Lua,
|
The only requirement is that if you do use Lua,
|
||||||
then you should give us credit by including the appropriate copyright notice somewhere in your product or its documentation.
|
then you should give us credit by including the appropriate copyright notice somewhere in your product or its documentation.
|
||||||
|
|
||||||
For details, see
|
For details, see the
|
||||||
<A HREF="http://www.lua.org/license.html">this</A>.
|
<A HREF="https://www.lua.org/license.html">license page</A>.
|
||||||
|
|
||||||
<BLOCKQUOTE STYLE="padding-bottom: 0em">
|
<BLOCKQUOTE STYLE="padding-bottom: 0em">
|
||||||
Copyright © 1994–2023 Lua.org, PUC-Rio.
|
Copyright © 1994–2024 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
|
||||||
@ -327,10 +329,10 @@ THE SOFTWARE.
|
|||||||
|
|
||||||
<P CLASS="footer">
|
<P CLASS="footer">
|
||||||
Last update:
|
Last update:
|
||||||
Tue May 2 20:08:55 UTC 2023
|
Wed May 8 21:56:16 UTC 2024
|
||||||
</P>
|
</P>
|
||||||
<!--
|
<!--
|
||||||
Last change: revised for Lua 5.4.6
|
Last change: revised for Lua 5.4.7
|
||||||
-->
|
-->
|
||||||
|
|
||||||
</BODY>
|
</BODY>
|
||||||
|
@ -417,9 +417,9 @@ LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) {
|
|||||||
o = index2value(L, idx); /* previous call may reallocate the stack */
|
o = index2value(L, idx); /* previous call may reallocate the stack */
|
||||||
}
|
}
|
||||||
if (len != NULL)
|
if (len != NULL)
|
||||||
*len = vslen(o);
|
*len = tsslen(tsvalue(o));
|
||||||
lua_unlock(L);
|
lua_unlock(L);
|
||||||
return svalue(o);
|
return getstr(tsvalue(o));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -80,6 +80,7 @@ static int pushglobalfuncname (lua_State *L, lua_Debug *ar) {
|
|||||||
int top = lua_gettop(L);
|
int top = lua_gettop(L);
|
||||||
lua_getinfo(L, "f", ar); /* push function */
|
lua_getinfo(L, "f", ar); /* push function */
|
||||||
lua_getfield(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE);
|
lua_getfield(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE);
|
||||||
|
luaL_checkstack(L, 6, "not enough stack"); /* slots for 'findfield' */
|
||||||
if (findfield(L, top + 1, 2)) {
|
if (findfield(L, top + 1, 2)) {
|
||||||
const char *name = lua_tostring(L, -1);
|
const char *name = lua_tostring(L, -1);
|
||||||
if (strncmp(name, LUA_GNAME ".", 3) == 0) { /* name start with '_G.'? */
|
if (strncmp(name, LUA_GNAME ".", 3) == 0) { /* name start with '_G.'? */
|
||||||
@ -249,11 +250,13 @@ LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
const char *msg;
|
||||||
luaL_pushfail(L);
|
luaL_pushfail(L);
|
||||||
|
msg = (en != 0) ? strerror(en) : "(no extra info)";
|
||||||
if (fname)
|
if (fname)
|
||||||
lua_pushfstring(L, "%s: %s", fname, strerror(en));
|
lua_pushfstring(L, "%s: %s", fname, msg);
|
||||||
else
|
else
|
||||||
lua_pushstring(L, strerror(en));
|
lua_pushstring(L, msg);
|
||||||
lua_pushinteger(L, en);
|
lua_pushinteger(L, en);
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
@ -732,9 +735,12 @@ static const char *getF (lua_State *L, void *ud, size_t *size) {
|
|||||||
|
|
||||||
|
|
||||||
static int errfile (lua_State *L, const char *what, int fnameindex) {
|
static int errfile (lua_State *L, const char *what, int fnameindex) {
|
||||||
const char *serr = strerror(errno);
|
int err = errno;
|
||||||
const char *filename = lua_tostring(L, fnameindex) + 1;
|
const char *filename = lua_tostring(L, fnameindex) + 1;
|
||||||
lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr);
|
if (err != 0)
|
||||||
|
lua_pushfstring(L, "cannot %s %s: %s", what, filename, strerror(err));
|
||||||
|
else
|
||||||
|
lua_pushfstring(L, "cannot %s %s", what, filename);
|
||||||
lua_remove(L, fnameindex);
|
lua_remove(L, fnameindex);
|
||||||
return LUA_ERRFILE;
|
return LUA_ERRFILE;
|
||||||
}
|
}
|
||||||
@ -787,6 +793,7 @@ LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename,
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
lua_pushfstring(L, "@%s", filename);
|
lua_pushfstring(L, "@%s", filename);
|
||||||
|
errno = 0;
|
||||||
lf.f = fopen(filename, "r");
|
lf.f = fopen(filename, "r");
|
||||||
if (lf.f == NULL) return errfile(L, "open", fnameindex);
|
if (lf.f == NULL) return errfile(L, "open", fnameindex);
|
||||||
}
|
}
|
||||||
@ -796,6 +803,7 @@ LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename,
|
|||||||
if (c == LUA_SIGNATURE[0]) { /* binary file? */
|
if (c == LUA_SIGNATURE[0]) { /* binary file? */
|
||||||
lf.n = 0; /* remove possible newline */
|
lf.n = 0; /* remove possible newline */
|
||||||
if (filename) { /* "real" file? */
|
if (filename) { /* "real" file? */
|
||||||
|
errno = 0;
|
||||||
lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */
|
lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */
|
||||||
if (lf.f == NULL) return errfile(L, "reopen", fnameindex);
|
if (lf.f == NULL) return errfile(L, "reopen", fnameindex);
|
||||||
skipcomment(lf.f, &c); /* re-read initial portion */
|
skipcomment(lf.f, &c); /* re-read initial portion */
|
||||||
@ -803,6 +811,7 @@ LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename,
|
|||||||
}
|
}
|
||||||
if (c != EOF)
|
if (c != EOF)
|
||||||
lf.buff[lf.n++] = c; /* 'c' is the first character of the stream */
|
lf.buff[lf.n++] = c; /* 'c' is the first character of the stream */
|
||||||
|
errno = 0;
|
||||||
status = lua_load(L, getF, &lf, lua_tostring(L, -1), mode);
|
status = lua_load(L, getF, &lf, lua_tostring(L, -1), mode);
|
||||||
readstatus = ferror(lf.f);
|
readstatus = ferror(lf.f);
|
||||||
if (filename) fclose(lf.f); /* close file (even in case of errors) */
|
if (filename) fclose(lf.f); /* close file (even in case of errors) */
|
||||||
@ -933,7 +942,7 @@ LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) {
|
|||||||
LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
|
LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
|
||||||
luaL_checkstack(L, nup, "too many upvalues");
|
luaL_checkstack(L, nup, "too many upvalues");
|
||||||
for (; l->name != NULL; l++) { /* fill the table with given functions */
|
for (; l->name != NULL; l++) { /* fill the table with given functions */
|
||||||
if (l->func == NULL) /* place holder? */
|
if (l->func == NULL) /* placeholder? */
|
||||||
lua_pushboolean(L, 0);
|
lua_pushboolean(L, 0);
|
||||||
else {
|
else {
|
||||||
int i;
|
int i;
|
||||||
@ -1025,9 +1034,14 @@ static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Standard panic funcion just prints an error message. The test
|
||||||
|
** with 'lua_type' avoids possible memory errors in 'lua_tostring'.
|
||||||
|
*/
|
||||||
static int panic (lua_State *L) {
|
static int panic (lua_State *L) {
|
||||||
const char *msg = lua_tostring(L, -1);
|
const char *msg = (lua_type(L, -1) == LUA_TSTRING)
|
||||||
if (msg == NULL) msg = "error object is not a string";
|
? lua_tostring(L, -1)
|
||||||
|
: "error object is not a string";
|
||||||
lua_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n",
|
lua_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n",
|
||||||
msg);
|
msg);
|
||||||
return 0; /* return to Lua to abort */
|
return 0; /* return to Lua to abort */
|
||||||
|
35
src/lcode.c
35
src/lcode.c
@ -415,7 +415,7 @@ int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) {
|
|||||||
/*
|
/*
|
||||||
** Format and emit an 'iAsBx' instruction.
|
** Format and emit an 'iAsBx' instruction.
|
||||||
*/
|
*/
|
||||||
int luaK_codeAsBx (FuncState *fs, OpCode o, int a, int bc) {
|
static int codeAsBx (FuncState *fs, OpCode o, int a, int bc) {
|
||||||
unsigned int b = bc + OFFSET_sBx;
|
unsigned int b = bc + OFFSET_sBx;
|
||||||
lua_assert(getOpMode(o) == iAsBx);
|
lua_assert(getOpMode(o) == iAsBx);
|
||||||
lua_assert(a <= MAXARG_A && b <= MAXARG_Bx);
|
lua_assert(a <= MAXARG_A && b <= MAXARG_Bx);
|
||||||
@ -671,7 +671,7 @@ static int fitsBx (lua_Integer i) {
|
|||||||
|
|
||||||
void luaK_int (FuncState *fs, int reg, lua_Integer i) {
|
void luaK_int (FuncState *fs, int reg, lua_Integer i) {
|
||||||
if (fitsBx(i))
|
if (fitsBx(i))
|
||||||
luaK_codeAsBx(fs, OP_LOADI, reg, cast_int(i));
|
codeAsBx(fs, OP_LOADI, reg, cast_int(i));
|
||||||
else
|
else
|
||||||
luaK_codek(fs, reg, luaK_intK(fs, i));
|
luaK_codek(fs, reg, luaK_intK(fs, i));
|
||||||
}
|
}
|
||||||
@ -680,7 +680,7 @@ void luaK_int (FuncState *fs, int reg, lua_Integer i) {
|
|||||||
static void luaK_float (FuncState *fs, int reg, lua_Number f) {
|
static void luaK_float (FuncState *fs, int reg, lua_Number f) {
|
||||||
lua_Integer fi;
|
lua_Integer fi;
|
||||||
if (luaV_flttointeger(f, &fi, F2Ieq) && fitsBx(fi))
|
if (luaV_flttointeger(f, &fi, F2Ieq) && fitsBx(fi))
|
||||||
luaK_codeAsBx(fs, OP_LOADF, reg, cast_int(fi));
|
codeAsBx(fs, OP_LOADF, reg, cast_int(fi));
|
||||||
else
|
else
|
||||||
luaK_codek(fs, reg, luaK_numberK(fs, f));
|
luaK_codek(fs, reg, luaK_numberK(fs, f));
|
||||||
}
|
}
|
||||||
@ -776,7 +776,8 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case VLOCAL: { /* already in a register */
|
case VLOCAL: { /* already in a register */
|
||||||
e->u.info = e->u.var.ridx;
|
int temp = e->u.var.ridx;
|
||||||
|
e->u.info = temp; /* (can't do a direct assignment; values overlap) */
|
||||||
e->k = VNONRELOC; /* becomes a non-relocatable value */
|
e->k = VNONRELOC; /* becomes a non-relocatable value */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1025,7 +1026,7 @@ static int luaK_exp2K (FuncState *fs, expdesc *e) {
|
|||||||
** in the range of R/K indices).
|
** in the range of R/K indices).
|
||||||
** Returns 1 iff expression is K.
|
** Returns 1 iff expression is K.
|
||||||
*/
|
*/
|
||||||
int luaK_exp2RK (FuncState *fs, expdesc *e) {
|
static int exp2RK (FuncState *fs, expdesc *e) {
|
||||||
if (luaK_exp2K(fs, e))
|
if (luaK_exp2K(fs, e))
|
||||||
return 1;
|
return 1;
|
||||||
else { /* not a constant in the right range: put it in a register */
|
else { /* not a constant in the right range: put it in a register */
|
||||||
@ -1037,7 +1038,7 @@ int luaK_exp2RK (FuncState *fs, expdesc *e) {
|
|||||||
|
|
||||||
static void codeABRK (FuncState *fs, OpCode o, int a, int b,
|
static void codeABRK (FuncState *fs, OpCode o, int a, int b,
|
||||||
expdesc *ec) {
|
expdesc *ec) {
|
||||||
int k = luaK_exp2RK(fs, ec);
|
int k = exp2RK(fs, ec);
|
||||||
luaK_codeABCk(fs, o, a, b, ec->u.info, k);
|
luaK_codeABCk(fs, o, a, b, ec->u.info, k);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1215,7 +1216,7 @@ static void codenot (FuncState *fs, expdesc *e) {
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Check whether expression 'e' is a small literal string
|
** Check whether expression 'e' is a short literal string
|
||||||
*/
|
*/
|
||||||
static int isKstr (FuncState *fs, expdesc *e) {
|
static int isKstr (FuncState *fs, expdesc *e) {
|
||||||
return (e->k == VK && !hasjumps(e) && e->u.info <= MAXARG_B &&
|
return (e->k == VK && !hasjumps(e) && e->u.info <= MAXARG_B &&
|
||||||
@ -1225,7 +1226,7 @@ static int isKstr (FuncState *fs, expdesc *e) {
|
|||||||
/*
|
/*
|
||||||
** Check whether expression 'e' is a literal integer.
|
** Check whether expression 'e' is a literal integer.
|
||||||
*/
|
*/
|
||||||
int luaK_isKint (expdesc *e) {
|
static int isKint (expdesc *e) {
|
||||||
return (e->k == VKINT && !hasjumps(e));
|
return (e->k == VKINT && !hasjumps(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1235,7 +1236,7 @@ int luaK_isKint (expdesc *e) {
|
|||||||
** proper range to fit in register C
|
** proper range to fit in register C
|
||||||
*/
|
*/
|
||||||
static int isCint (expdesc *e) {
|
static int isCint (expdesc *e) {
|
||||||
return luaK_isKint(e) && (l_castS2U(e->u.ival) <= l_castS2U(MAXARG_C));
|
return isKint(e) && (l_castS2U(e->u.ival) <= l_castS2U(MAXARG_C));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1244,7 +1245,7 @@ static int isCint (expdesc *e) {
|
|||||||
** proper range to fit in register sC
|
** proper range to fit in register sC
|
||||||
*/
|
*/
|
||||||
static int isSCint (expdesc *e) {
|
static int isSCint (expdesc *e) {
|
||||||
return luaK_isKint(e) && fitsC(e->u.ival);
|
return isKint(e) && fitsC(e->u.ival);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1283,15 +1284,17 @@ void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
|
|||||||
if (t->k == VUPVAL && !isKstr(fs, k)) /* upvalue indexed by non 'Kstr'? */
|
if (t->k == VUPVAL && !isKstr(fs, k)) /* upvalue indexed by non 'Kstr'? */
|
||||||
luaK_exp2anyreg(fs, t); /* put it in a register */
|
luaK_exp2anyreg(fs, t); /* put it in a register */
|
||||||
if (t->k == VUPVAL) {
|
if (t->k == VUPVAL) {
|
||||||
t->u.ind.t = t->u.info; /* upvalue index */
|
int temp = t->u.info; /* upvalue index */
|
||||||
t->u.ind.idx = k->u.info; /* literal string */
|
lua_assert(isKstr(fs, k));
|
||||||
|
t->u.ind.t = temp; /* (can't do a direct assignment; values overlap) */
|
||||||
|
t->u.ind.idx = k->u.info; /* literal short string */
|
||||||
t->k = VINDEXUP;
|
t->k = VINDEXUP;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* register index of the table */
|
/* register index of the table */
|
||||||
t->u.ind.t = (t->k == VLOCAL) ? t->u.var.ridx: t->u.info;
|
t->u.ind.t = (t->k == VLOCAL) ? t->u.var.ridx: t->u.info;
|
||||||
if (isKstr(fs, k)) {
|
if (isKstr(fs, k)) {
|
||||||
t->u.ind.idx = k->u.info; /* literal string */
|
t->u.ind.idx = k->u.info; /* literal short string */
|
||||||
t->k = VINDEXSTR;
|
t->k = VINDEXSTR;
|
||||||
}
|
}
|
||||||
else if (isCint(k)) {
|
else if (isCint(k)) {
|
||||||
@ -1459,7 +1462,7 @@ static void codebinK (FuncState *fs, BinOpr opr,
|
|||||||
*/
|
*/
|
||||||
static int finishbinexpneg (FuncState *fs, expdesc *e1, expdesc *e2,
|
static int finishbinexpneg (FuncState *fs, expdesc *e1, expdesc *e2,
|
||||||
OpCode op, int line, TMS event) {
|
OpCode op, int line, TMS event) {
|
||||||
if (!luaK_isKint(e2))
|
if (!isKint(e2))
|
||||||
return 0; /* not an integer constant */
|
return 0; /* not an integer constant */
|
||||||
else {
|
else {
|
||||||
lua_Integer i2 = e2->u.ival;
|
lua_Integer i2 = e2->u.ival;
|
||||||
@ -1592,7 +1595,7 @@ static void codeeq (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) {
|
|||||||
op = OP_EQI;
|
op = OP_EQI;
|
||||||
r2 = im; /* immediate operand */
|
r2 = im; /* immediate operand */
|
||||||
}
|
}
|
||||||
else if (luaK_exp2RK(fs, e2)) { /* 2nd expression is constant? */
|
else if (exp2RK(fs, e2)) { /* 2nd expression is constant? */
|
||||||
op = OP_EQK;
|
op = OP_EQK;
|
||||||
r2 = e2->u.info; /* constant index */
|
r2 = e2->u.info; /* constant index */
|
||||||
}
|
}
|
||||||
@ -1658,7 +1661,7 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
|
|||||||
}
|
}
|
||||||
case OPR_EQ: case OPR_NE: {
|
case OPR_EQ: case OPR_NE: {
|
||||||
if (!tonumeral(v, NULL))
|
if (!tonumeral(v, NULL))
|
||||||
luaK_exp2RK(fs, v);
|
exp2RK(fs, v);
|
||||||
/* else keep numeral, which may be an immediate operand */
|
/* else keep numeral, which may be an immediate operand */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -61,10 +61,8 @@ typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;
|
|||||||
|
|
||||||
LUAI_FUNC int luaK_code (FuncState *fs, Instruction i);
|
LUAI_FUNC int luaK_code (FuncState *fs, Instruction i);
|
||||||
LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx);
|
LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx);
|
||||||
LUAI_FUNC int luaK_codeAsBx (FuncState *fs, OpCode o, int A, int Bx);
|
|
||||||
LUAI_FUNC int luaK_codeABCk (FuncState *fs, OpCode o, int A,
|
LUAI_FUNC int luaK_codeABCk (FuncState *fs, OpCode o, int A,
|
||||||
int B, int C, int k);
|
int B, int C, int k);
|
||||||
LUAI_FUNC int luaK_isKint (expdesc *e);
|
|
||||||
LUAI_FUNC int luaK_exp2const (FuncState *fs, const expdesc *e, TValue *v);
|
LUAI_FUNC int luaK_exp2const (FuncState *fs, const expdesc *e, TValue *v);
|
||||||
LUAI_FUNC void luaK_fixline (FuncState *fs, int line);
|
LUAI_FUNC void luaK_fixline (FuncState *fs, int line);
|
||||||
LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n);
|
LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n);
|
||||||
@ -76,7 +74,6 @@ LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e);
|
|||||||
LUAI_FUNC void luaK_exp2anyregup (FuncState *fs, expdesc *e);
|
LUAI_FUNC void luaK_exp2anyregup (FuncState *fs, expdesc *e);
|
||||||
LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e);
|
LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e);
|
||||||
LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e);
|
LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e);
|
||||||
LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e);
|
|
||||||
LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key);
|
LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key);
|
||||||
LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k);
|
LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k);
|
||||||
LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e);
|
LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e);
|
||||||
|
218
src/ldebug.c
218
src/ldebug.c
@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_VCCL)
|
#define LuaClosure(f) ((f) != NULL && (f)->c.tt == LUA_VLCL)
|
||||||
|
|
||||||
|
|
||||||
static const char *funcnamefromcall (lua_State *L, CallInfo *ci,
|
static const char *funcnamefromcall (lua_State *L, CallInfo *ci,
|
||||||
@ -254,7 +254,7 @@ LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
|
|||||||
|
|
||||||
|
|
||||||
static void funcinfo (lua_Debug *ar, Closure *cl) {
|
static void funcinfo (lua_Debug *ar, Closure *cl) {
|
||||||
if (noLuaClosure(cl)) {
|
if (!LuaClosure(cl)) {
|
||||||
ar->source = "=[C]";
|
ar->source = "=[C]";
|
||||||
ar->srclen = LL("=[C]");
|
ar->srclen = LL("=[C]");
|
||||||
ar->linedefined = -1;
|
ar->linedefined = -1;
|
||||||
@ -288,29 +288,31 @@ static int nextline (const Proto *p, int currentline, int pc) {
|
|||||||
|
|
||||||
|
|
||||||
static void collectvalidlines (lua_State *L, Closure *f) {
|
static void collectvalidlines (lua_State *L, Closure *f) {
|
||||||
if (noLuaClosure(f)) {
|
if (!LuaClosure(f)) {
|
||||||
setnilvalue(s2v(L->top.p));
|
setnilvalue(s2v(L->top.p));
|
||||||
api_incr_top(L);
|
api_incr_top(L);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int i;
|
|
||||||
TValue v;
|
|
||||||
const Proto *p = f->l.p;
|
const Proto *p = f->l.p;
|
||||||
int currentline = p->linedefined;
|
int currentline = p->linedefined;
|
||||||
Table *t = luaH_new(L); /* new table to store active lines */
|
Table *t = luaH_new(L); /* new table to store active lines */
|
||||||
sethvalue2s(L, L->top.p, t); /* push it on stack */
|
sethvalue2s(L, L->top.p, t); /* push it on stack */
|
||||||
api_incr_top(L);
|
api_incr_top(L);
|
||||||
setbtvalue(&v); /* boolean 'true' to be the value of all indices */
|
if (p->lineinfo != NULL) { /* proto with debug information? */
|
||||||
if (!p->is_vararg) /* regular function? */
|
int i;
|
||||||
i = 0; /* consider all instructions */
|
TValue v;
|
||||||
else { /* vararg function */
|
setbtvalue(&v); /* boolean 'true' to be the value of all indices */
|
||||||
lua_assert(GET_OPCODE(p->code[0]) == OP_VARARGPREP);
|
if (!p->is_vararg) /* regular function? */
|
||||||
currentline = nextline(p, currentline, 0);
|
i = 0; /* consider all instructions */
|
||||||
i = 1; /* skip first instruction (OP_VARARGPREP) */
|
else { /* vararg function */
|
||||||
}
|
lua_assert(GET_OPCODE(p->code[0]) == OP_VARARGPREP);
|
||||||
for (; i < p->sizelineinfo; i++) { /* for each instruction */
|
currentline = nextline(p, currentline, 0);
|
||||||
currentline = nextline(p, currentline, i); /* get its line */
|
i = 1; /* skip first instruction (OP_VARARGPREP) */
|
||||||
luaH_setint(L, t, currentline, &v); /* table[line] = true */
|
}
|
||||||
|
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 */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -339,7 +341,7 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
|
|||||||
}
|
}
|
||||||
case 'u': {
|
case 'u': {
|
||||||
ar->nups = (f == NULL) ? 0 : f->c.nupvalues;
|
ar->nups = (f == NULL) ? 0 : f->c.nupvalues;
|
||||||
if (noLuaClosure(f)) {
|
if (!LuaClosure(f)) {
|
||||||
ar->isvararg = 1;
|
ar->isvararg = 1;
|
||||||
ar->nparams = 0;
|
ar->nparams = 0;
|
||||||
}
|
}
|
||||||
@ -417,40 +419,6 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
|
|||||||
** =======================================================
|
** =======================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static const char *getobjname (const Proto *p, int lastpc, int reg,
|
|
||||||
const char **name);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Find a "name" for the constant 'c'.
|
|
||||||
*/
|
|
||||||
static void kname (const Proto *p, int c, const char **name) {
|
|
||||||
TValue *kvalue = &p->k[c];
|
|
||||||
*name = (ttisstring(kvalue)) ? svalue(kvalue) : "?";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Find a "name" for the register 'c'.
|
|
||||||
*/
|
|
||||||
static void rname (const Proto *p, int pc, int c, const char **name) {
|
|
||||||
const char *what = getobjname(p, pc, c, name); /* search for 'c' */
|
|
||||||
if (!(what && *what == 'c')) /* did not find a constant name? */
|
|
||||||
*name = "?";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Find a "name" for a 'C' value in an RK instruction.
|
|
||||||
*/
|
|
||||||
static void rkname (const Proto *p, int pc, Instruction i, const char **name) {
|
|
||||||
int c = GETARG_C(i); /* key index */
|
|
||||||
if (GETARG_k(i)) /* is 'c' a constant? */
|
|
||||||
kname(p, c, name);
|
|
||||||
else /* 'c' is a register */
|
|
||||||
rname(p, pc, c, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int filterpc (int pc, int jmptarget) {
|
static int filterpc (int pc, int jmptarget) {
|
||||||
if (pc < jmptarget) /* is code conditional (inside a jump)? */
|
if (pc < jmptarget) /* is code conditional (inside a jump)? */
|
||||||
@ -509,28 +477,29 @@ static int findsetreg (const Proto *p, int lastpc, int reg) {
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Check whether table being indexed by instruction 'i' is the
|
** Find a "name" for the constant 'c'.
|
||||||
** environment '_ENV'
|
|
||||||
*/
|
*/
|
||||||
static const char *gxf (const Proto *p, int pc, Instruction i, int isup) {
|
static const char *kname (const Proto *p, int index, const char **name) {
|
||||||
int t = GETARG_B(i); /* table index */
|
TValue *kvalue = &p->k[index];
|
||||||
const char *name; /* name of indexed variable */
|
if (ttisstring(kvalue)) {
|
||||||
if (isup) /* is an upvalue? */
|
*name = getstr(tsvalue(kvalue));
|
||||||
name = upvalname(p, t);
|
return "constant";
|
||||||
else
|
}
|
||||||
getobjname(p, pc, t, &name);
|
else {
|
||||||
return (name && strcmp(name, LUA_ENV) == 0) ? "global" : "field";
|
*name = "?";
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const char *getobjname (const Proto *p, int lastpc, int reg,
|
static const char *basicgetobjname (const Proto *p, int *ppc, int reg,
|
||||||
const char **name) {
|
const char **name) {
|
||||||
int pc;
|
int pc = *ppc;
|
||||||
*name = luaF_getlocalname(p, reg + 1, lastpc);
|
*name = luaF_getlocalname(p, reg + 1, pc);
|
||||||
if (*name) /* is a local? */
|
if (*name) /* is a local? */
|
||||||
return "local";
|
return "local";
|
||||||
/* else try symbolic execution */
|
/* else try symbolic execution */
|
||||||
pc = findsetreg(p, lastpc, reg);
|
*ppc = pc = findsetreg(p, pc, reg);
|
||||||
if (pc != -1) { /* could find instruction? */
|
if (pc != -1) { /* could find instruction? */
|
||||||
Instruction i = p->code[pc];
|
Instruction i = p->code[pc];
|
||||||
OpCode op = GET_OPCODE(i);
|
OpCode op = GET_OPCODE(i);
|
||||||
@ -538,18 +507,80 @@ static const char *getobjname (const Proto *p, int lastpc, int reg,
|
|||||||
case OP_MOVE: {
|
case OP_MOVE: {
|
||||||
int b = GETARG_B(i); /* move from 'b' to 'a' */
|
int b = GETARG_B(i); /* move from 'b' to 'a' */
|
||||||
if (b < GETARG_A(i))
|
if (b < GETARG_A(i))
|
||||||
return getobjname(p, pc, b, name); /* get name for 'b' */
|
return basicgetobjname(p, ppc, b, name); /* get name for 'b' */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case OP_GETUPVAL: {
|
||||||
|
*name = upvalname(p, GETARG_B(i));
|
||||||
|
return "upvalue";
|
||||||
|
}
|
||||||
|
case OP_LOADK: return kname(p, GETARG_Bx(i), name);
|
||||||
|
case OP_LOADKX: return kname(p, GETARG_Ax(p->code[pc + 1]), name);
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL; /* could not find reasonable name */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Find a "name" for the register 'c'.
|
||||||
|
*/
|
||||||
|
static void rname (const Proto *p, int pc, int c, const char **name) {
|
||||||
|
const char *what = basicgetobjname(p, &pc, c, name); /* search for 'c' */
|
||||||
|
if (!(what && *what == 'c')) /* did not find a constant name? */
|
||||||
|
*name = "?";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Find a "name" for a 'C' value in an RK instruction.
|
||||||
|
*/
|
||||||
|
static void rkname (const Proto *p, int pc, Instruction i, const char **name) {
|
||||||
|
int c = GETARG_C(i); /* key index */
|
||||||
|
if (GETARG_k(i)) /* is 'c' a constant? */
|
||||||
|
kname(p, c, name);
|
||||||
|
else /* 'c' is a register */
|
||||||
|
rname(p, pc, c, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Check whether table being indexed by instruction 'i' is the
|
||||||
|
** environment '_ENV'
|
||||||
|
*/
|
||||||
|
static const char *isEnv (const Proto *p, int pc, Instruction i, int isup) {
|
||||||
|
int t = GETARG_B(i); /* table index */
|
||||||
|
const char *name; /* name of indexed variable */
|
||||||
|
if (isup) /* is 't' an upvalue? */
|
||||||
|
name = upvalname(p, t);
|
||||||
|
else /* 't' is a register */
|
||||||
|
basicgetobjname(p, &pc, t, &name);
|
||||||
|
return (name && strcmp(name, LUA_ENV) == 0) ? "global" : "field";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Extend 'basicgetobjname' to handle table accesses
|
||||||
|
*/
|
||||||
|
static const char *getobjname (const Proto *p, int lastpc, int reg,
|
||||||
|
const char **name) {
|
||||||
|
const char *kind = basicgetobjname(p, &lastpc, reg, name);
|
||||||
|
if (kind != NULL)
|
||||||
|
return kind;
|
||||||
|
else if (lastpc != -1) { /* could find instruction? */
|
||||||
|
Instruction i = p->code[lastpc];
|
||||||
|
OpCode op = GET_OPCODE(i);
|
||||||
|
switch (op) {
|
||||||
case OP_GETTABUP: {
|
case OP_GETTABUP: {
|
||||||
int k = GETARG_C(i); /* key index */
|
int k = GETARG_C(i); /* key index */
|
||||||
kname(p, k, name);
|
kname(p, k, name);
|
||||||
return gxf(p, pc, i, 1);
|
return isEnv(p, lastpc, i, 1);
|
||||||
}
|
}
|
||||||
case OP_GETTABLE: {
|
case OP_GETTABLE: {
|
||||||
int k = GETARG_C(i); /* key index */
|
int k = GETARG_C(i); /* key index */
|
||||||
rname(p, pc, k, name);
|
rname(p, lastpc, k, name);
|
||||||
return gxf(p, pc, i, 0);
|
return isEnv(p, lastpc, i, 0);
|
||||||
}
|
}
|
||||||
case OP_GETI: {
|
case OP_GETI: {
|
||||||
*name = "integer index";
|
*name = "integer index";
|
||||||
@ -558,24 +589,10 @@ static const char *getobjname (const Proto *p, int lastpc, int reg,
|
|||||||
case OP_GETFIELD: {
|
case OP_GETFIELD: {
|
||||||
int k = GETARG_C(i); /* key index */
|
int k = GETARG_C(i); /* key index */
|
||||||
kname(p, k, name);
|
kname(p, k, name);
|
||||||
return gxf(p, pc, i, 0);
|
return isEnv(p, lastpc, i, 0);
|
||||||
}
|
|
||||||
case OP_GETUPVAL: {
|
|
||||||
*name = upvalname(p, GETARG_B(i));
|
|
||||||
return "upvalue";
|
|
||||||
}
|
|
||||||
case OP_LOADK:
|
|
||||||
case OP_LOADKX: {
|
|
||||||
int b = (op == OP_LOADK) ? GETARG_Bx(i)
|
|
||||||
: GETARG_Ax(p->code[pc + 1]);
|
|
||||||
if (ttisstring(&p->k[b])) {
|
|
||||||
*name = svalue(&p->k[b]);
|
|
||||||
return "constant";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case OP_SELF: {
|
case OP_SELF: {
|
||||||
rkname(p, pc, i, name);
|
rkname(p, lastpc, i, name);
|
||||||
return "method";
|
return "method";
|
||||||
}
|
}
|
||||||
default: break; /* go through to return NULL */
|
default: break; /* go through to return NULL */
|
||||||
@ -627,7 +644,7 @@ static const char *funcnamefromcode (lua_State *L, const Proto *p,
|
|||||||
default:
|
default:
|
||||||
return NULL; /* cannot find a reasonable name */
|
return NULL; /* cannot find a reasonable name */
|
||||||
}
|
}
|
||||||
*name = getstr(G(L)->tmname[tm]) + 2;
|
*name = getshrstr(G(L)->tmname[tm]) + 2;
|
||||||
return "metamethod";
|
return "metamethod";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -865,6 +882,28 @@ static int changedline (const Proto *p, int oldpc, int newpc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Traces Lua calls. If code is running the first instruction of a function,
|
||||||
|
** and function is not vararg, and it is not coming from an yield,
|
||||||
|
** calls 'luaD_hookcall'. (Vararg functions will call 'luaD_hookcall'
|
||||||
|
** after adjusting its variable arguments; otherwise, they could call
|
||||||
|
** a line/count hook before the call hook. Functions coming from
|
||||||
|
** an yield already called 'luaD_hookcall' before yielding.)
|
||||||
|
*/
|
||||||
|
int luaG_tracecall (lua_State *L) {
|
||||||
|
CallInfo *ci = L->ci;
|
||||||
|
Proto *p = ci_func(ci)->p;
|
||||||
|
ci->u.l.trap = 1; /* ensure hooks will be checked */
|
||||||
|
if (ci->u.l.savedpc == p->code) { /* first instruction (not resuming)? */
|
||||||
|
if (p->is_vararg)
|
||||||
|
return 0; /* hooks will start at VARARGPREP instruction */
|
||||||
|
else if (!(ci->callstatus & CIST_HOOKYIELD)) /* not yieded? */
|
||||||
|
luaD_hookcall(L, ci); /* check 'call' hook */
|
||||||
|
}
|
||||||
|
return 1; /* keep 'trap' on */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Traces the execution of a Lua function. Called before the execution
|
** Traces the execution of a Lua function. Called before the execution
|
||||||
** of each opcode, when debug is on. 'L->oldpc' stores the last
|
** of each opcode, when debug is on. 'L->oldpc' stores the last
|
||||||
@ -888,12 +927,12 @@ int luaG_traceexec (lua_State *L, const Instruction *pc) {
|
|||||||
}
|
}
|
||||||
pc++; /* reference is always next instruction */
|
pc++; /* reference is always next instruction */
|
||||||
ci->u.l.savedpc = pc; /* save 'pc' */
|
ci->u.l.savedpc = pc; /* save 'pc' */
|
||||||
counthook = (--L->hookcount == 0 && (mask & LUA_MASKCOUNT));
|
counthook = (mask & LUA_MASKCOUNT) && (--L->hookcount == 0);
|
||||||
if (counthook)
|
if (counthook)
|
||||||
resethookcount(L); /* reset count */
|
resethookcount(L); /* reset count */
|
||||||
else if (!(mask & LUA_MASKLINE))
|
else if (!(mask & LUA_MASKLINE))
|
||||||
return 1; /* no line hook and count != 0; nothing to be done now */
|
return 1; /* no line hook and count != 0; nothing to be done now */
|
||||||
if (ci->callstatus & CIST_HOOKYIELD) { /* called hook last time? */
|
if (ci->callstatus & CIST_HOOKYIELD) { /* hook yielded last time? */
|
||||||
ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */
|
ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */
|
||||||
return 1; /* do not call hook again (VM yielded, so it did not move) */
|
return 1; /* do not call hook again (VM yielded, so it did not move) */
|
||||||
}
|
}
|
||||||
@ -915,7 +954,6 @@ int luaG_traceexec (lua_State *L, const Instruction *pc) {
|
|||||||
if (L->status == LUA_YIELD) { /* did hook yield? */
|
if (L->status == LUA_YIELD) { /* did hook yield? */
|
||||||
if (counthook)
|
if (counthook)
|
||||||
L->hookcount = 1; /* undo decrement to zero */
|
L->hookcount = 1; /* undo decrement to zero */
|
||||||
ci->u.l.savedpc--; /* undo increment (resume will increment it again) */
|
|
||||||
ci->callstatus |= CIST_HOOKYIELD; /* mark that it yielded */
|
ci->callstatus |= CIST_HOOKYIELD; /* mark that it yielded */
|
||||||
luaD_throw(L, LUA_YIELD);
|
luaD_throw(L, LUA_YIELD);
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,7 @@ LUAI_FUNC const char *luaG_addinfo (lua_State *L, const char *msg,
|
|||||||
TString *src, int line);
|
TString *src, int line);
|
||||||
LUAI_FUNC l_noret luaG_errormsg (lua_State *L);
|
LUAI_FUNC l_noret luaG_errormsg (lua_State *L);
|
||||||
LUAI_FUNC int luaG_traceexec (lua_State *L, const Instruction *pc);
|
LUAI_FUNC int luaG_traceexec (lua_State *L, const Instruction *pc);
|
||||||
|
LUAI_FUNC int luaG_tracecall (lua_State *L);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
10
src/ldo.c
10
src/ldo.c
@ -409,7 +409,7 @@ 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.
|
||||||
*/
|
*/
|
||||||
StkId luaD_tryfuncTM (lua_State *L, StkId func) {
|
static StkId tryfuncTM (lua_State *L, StkId func) {
|
||||||
const TValue *tm;
|
const TValue *tm;
|
||||||
StkId p;
|
StkId p;
|
||||||
checkstackGCp(L, 1, func); /* space for metamethod */
|
checkstackGCp(L, 1, func); /* space for metamethod */
|
||||||
@ -568,7 +568,7 @@ int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
default: { /* not a function */
|
default: { /* not a function */
|
||||||
func = luaD_tryfuncTM(L, func); /* try to get '__call' metamethod */
|
func = tryfuncTM(L, func); /* try to get '__call' metamethod */
|
||||||
/* return luaD_pretailcall(L, ci, func, narg1 + 1, delta); */
|
/* return luaD_pretailcall(L, ci, func, narg1 + 1, delta); */
|
||||||
narg1++;
|
narg1++;
|
||||||
goto retry; /* try again */
|
goto retry; /* try again */
|
||||||
@ -609,7 +609,7 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) {
|
|||||||
return ci;
|
return ci;
|
||||||
}
|
}
|
||||||
default: { /* not a function */
|
default: { /* not a function */
|
||||||
func = luaD_tryfuncTM(L, func); /* try to get '__call' metamethod */
|
func = tryfuncTM(L, func); /* try to get '__call' metamethod */
|
||||||
/* return luaD_precall(L, func, nresults); */
|
/* return luaD_precall(L, func, nresults); */
|
||||||
goto retry; /* try again with metamethod */
|
goto retry; /* try again with metamethod */
|
||||||
}
|
}
|
||||||
@ -792,6 +792,10 @@ static void resume (lua_State *L, void *ud) {
|
|||||||
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) */
|
||||||
if (isLua(ci)) { /* yielded inside a hook? */
|
if (isLua(ci)) { /* yielded inside a hook? */
|
||||||
|
/* undo increment made by 'luaG_traceexec': instruction was not
|
||||||
|
executed yet */
|
||||||
|
lua_assert(ci->callstatus & CIST_HOOKYIELD);
|
||||||
|
ci->u.l.savedpc--;
|
||||||
L->top.p = firstArg; /* discard arguments */
|
L->top.p = firstArg; /* discard arguments */
|
||||||
luaV_execute(L, ci); /* just continue running Lua code */
|
luaV_execute(L, ci); /* just continue running Lua code */
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,6 @@ LUAI_FUNC int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func,
|
|||||||
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 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);
|
||||||
|
20
src/lgc.c
20
src/lgc.c
@ -542,10 +542,12 @@ static void traversestrongtable (global_State *g, Table *h) {
|
|||||||
static lu_mem traversetable (global_State *g, Table *h) {
|
static lu_mem traversetable (global_State *g, Table *h) {
|
||||||
const char *weakkey, *weakvalue;
|
const char *weakkey, *weakvalue;
|
||||||
const TValue *mode = gfasttm(g, h->metatable, TM_MODE);
|
const TValue *mode = gfasttm(g, h->metatable, TM_MODE);
|
||||||
|
TString *smode;
|
||||||
markobjectN(g, h->metatable);
|
markobjectN(g, h->metatable);
|
||||||
if (mode && ttisstring(mode) && /* is there a weak mode? */
|
if (mode && ttisshrstring(mode) && /* is there a weak mode? */
|
||||||
(cast_void(weakkey = strchr(svalue(mode), 'k')),
|
(cast_void(smode = tsvalue(mode)),
|
||||||
cast_void(weakvalue = strchr(svalue(mode), 'v')),
|
cast_void(weakkey = strchr(getshrstr(smode), 'k')),
|
||||||
|
cast_void(weakvalue = strchr(getshrstr(smode), 'v')),
|
||||||
(weakkey || weakvalue))) { /* is really weak? */
|
(weakkey || weakvalue))) { /* is really weak? */
|
||||||
if (!weakkey) /* strong keys? */
|
if (!weakkey) /* strong keys? */
|
||||||
traverseweakvalue(g, h);
|
traverseweakvalue(g, h);
|
||||||
@ -638,7 +640,9 @@ static int traversethread (global_State *g, lua_State *th) {
|
|||||||
for (uv = th->openupval; uv != NULL; uv = uv->u.open.next)
|
for (uv = th->openupval; uv != NULL; uv = uv->u.open.next)
|
||||||
markobject(g, uv); /* open upvalues cannot be collected */
|
markobject(g, uv); /* open upvalues cannot be collected */
|
||||||
if (g->gcstate == GCSatomic) { /* final traversal? */
|
if (g->gcstate == GCSatomic) { /* final traversal? */
|
||||||
for (; o < th->stack_last.p + EXTRA_STACK; o++)
|
if (!g->gcemergency)
|
||||||
|
luaD_shrinkstack(th); /* do not change stack in emergency cycle */
|
||||||
|
for (o = th->top.p; o < th->stack_last.p + EXTRA_STACK; o++)
|
||||||
setnilvalue(s2v(o)); /* clear dead stack slice */
|
setnilvalue(s2v(o)); /* clear dead stack slice */
|
||||||
/* 'remarkupvals' may have removed thread from 'twups' list */
|
/* 'remarkupvals' may have removed thread from 'twups' list */
|
||||||
if (!isintwups(th) && th->openupval != NULL) {
|
if (!isintwups(th) && th->openupval != NULL) {
|
||||||
@ -646,8 +650,6 @@ static int traversethread (global_State *g, lua_State *th) {
|
|||||||
g->twups = th;
|
g->twups = th;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!g->gcemergency)
|
|
||||||
luaD_shrinkstack(th); /* do not change stack in emergency cycle */
|
|
||||||
return 1 + stacksize(th);
|
return 1 + stacksize(th);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1409,7 +1411,7 @@ static void stepgenfull (lua_State *L, global_State *g) {
|
|||||||
setminordebt(g);
|
setminordebt(g);
|
||||||
}
|
}
|
||||||
else { /* another bad collection; stay in incremental mode */
|
else { /* another bad collection; stay in incremental mode */
|
||||||
g->GCestimate = gettotalbytes(g); /* first estimate */;
|
g->GCestimate = gettotalbytes(g); /* first estimate */
|
||||||
entersweep(L);
|
entersweep(L);
|
||||||
luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */
|
luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */
|
||||||
setpause(g);
|
setpause(g);
|
||||||
@ -1604,7 +1606,7 @@ static lu_mem singlestep (lua_State *L) {
|
|||||||
case GCSenteratomic: {
|
case GCSenteratomic: {
|
||||||
work = atomic(L); /* work is what was traversed by 'atomic' */
|
work = atomic(L); /* work is what was traversed by 'atomic' */
|
||||||
entersweep(L);
|
entersweep(L);
|
||||||
g->GCestimate = gettotalbytes(g); /* first estimate */;
|
g->GCestimate = gettotalbytes(g); /* first estimate */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GCSswpallgc: { /* sweep "regular" objects */
|
case GCSswpallgc: { /* sweep "regular" objects */
|
||||||
@ -1710,6 +1712,8 @@ static void fullinc (lua_State *L, global_State *g) {
|
|||||||
entersweep(L); /* sweep everything to turn them back to white */
|
entersweep(L); /* sweep everything to turn them back to white */
|
||||||
/* finish any pending sweep phase to start a new cycle */
|
/* finish any pending sweep phase to start a new cycle */
|
||||||
luaC_runtilstate(L, bitmask(GCSpause));
|
luaC_runtilstate(L, bitmask(GCSpause));
|
||||||
|
luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */
|
||||||
|
g->gcstate = GCSenteratomic; /* go straight to atomic phase */
|
||||||
luaC_runtilstate(L, bitmask(GCScallfin)); /* run up to finalizers */
|
luaC_runtilstate(L, bitmask(GCScallfin)); /* run up to finalizers */
|
||||||
/* estimate must be correct after a full GC cycle */
|
/* estimate must be correct after a full GC cycle */
|
||||||
lua_assert(g->GCestimate == gettotalbytes(g));
|
lua_assert(g->GCestimate == gettotalbytes(g));
|
||||||
|
27
src/liolib.c
27
src/liolib.c
@ -245,8 +245,8 @@ static int f_gc (lua_State *L) {
|
|||||||
*/
|
*/
|
||||||
static int io_fclose (lua_State *L) {
|
static int io_fclose (lua_State *L) {
|
||||||
LStream *p = tolstream(L);
|
LStream *p = tolstream(L);
|
||||||
int res = fclose(p->f);
|
errno = 0;
|
||||||
return luaL_fileresult(L, (res == 0), NULL);
|
return luaL_fileresult(L, (fclose(p->f) == 0), NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -272,6 +272,7 @@ static int io_open (lua_State *L) {
|
|||||||
LStream *p = newfile(L);
|
LStream *p = newfile(L);
|
||||||
const char *md = mode; /* to traverse/check mode */
|
const char *md = mode; /* to traverse/check mode */
|
||||||
luaL_argcheck(L, l_checkmode(md), 2, "invalid mode");
|
luaL_argcheck(L, l_checkmode(md), 2, "invalid mode");
|
||||||
|
errno = 0;
|
||||||
p->f = fopen(filename, mode);
|
p->f = fopen(filename, mode);
|
||||||
return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
|
return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
|
||||||
}
|
}
|
||||||
@ -292,6 +293,7 @@ static int io_popen (lua_State *L) {
|
|||||||
const char *mode = luaL_optstring(L, 2, "r");
|
const char *mode = luaL_optstring(L, 2, "r");
|
||||||
LStream *p = newprefile(L);
|
LStream *p = newprefile(L);
|
||||||
luaL_argcheck(L, l_checkmodep(mode), 2, "invalid mode");
|
luaL_argcheck(L, l_checkmodep(mode), 2, "invalid mode");
|
||||||
|
errno = 0;
|
||||||
p->f = l_popen(L, filename, mode);
|
p->f = l_popen(L, filename, mode);
|
||||||
p->closef = &io_pclose;
|
p->closef = &io_pclose;
|
||||||
return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
|
return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
|
||||||
@ -300,6 +302,7 @@ static int io_popen (lua_State *L) {
|
|||||||
|
|
||||||
static int io_tmpfile (lua_State *L) {
|
static int io_tmpfile (lua_State *L) {
|
||||||
LStream *p = newfile(L);
|
LStream *p = newfile(L);
|
||||||
|
errno = 0;
|
||||||
p->f = tmpfile();
|
p->f = tmpfile();
|
||||||
return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1;
|
return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1;
|
||||||
}
|
}
|
||||||
@ -567,6 +570,7 @@ static int g_read (lua_State *L, FILE *f, int first) {
|
|||||||
int nargs = lua_gettop(L) - 1;
|
int nargs = lua_gettop(L) - 1;
|
||||||
int n, success;
|
int n, success;
|
||||||
clearerr(f);
|
clearerr(f);
|
||||||
|
errno = 0;
|
||||||
if (nargs == 0) { /* no arguments? */
|
if (nargs == 0) { /* no arguments? */
|
||||||
success = read_line(L, f, 1);
|
success = read_line(L, f, 1);
|
||||||
n = first + 1; /* to return 1 result */
|
n = first + 1; /* to return 1 result */
|
||||||
@ -660,6 +664,7 @@ static int io_readline (lua_State *L) {
|
|||||||
static int g_write (lua_State *L, FILE *f, int arg) {
|
static int g_write (lua_State *L, FILE *f, int arg) {
|
||||||
int nargs = lua_gettop(L) - arg;
|
int nargs = lua_gettop(L) - arg;
|
||||||
int status = 1;
|
int status = 1;
|
||||||
|
errno = 0;
|
||||||
for (; nargs--; arg++) {
|
for (; nargs--; arg++) {
|
||||||
if (lua_type(L, arg) == LUA_TNUMBER) {
|
if (lua_type(L, arg) == LUA_TNUMBER) {
|
||||||
/* optimization: could be done exactly as for strings */
|
/* optimization: could be done exactly as for strings */
|
||||||
@ -678,7 +683,8 @@ static int g_write (lua_State *L, FILE *f, int arg) {
|
|||||||
}
|
}
|
||||||
if (l_likely(status))
|
if (l_likely(status))
|
||||||
return 1; /* file handle already on stack top */
|
return 1; /* file handle already on stack top */
|
||||||
else return luaL_fileresult(L, status, NULL);
|
else
|
||||||
|
return luaL_fileresult(L, status, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -703,6 +709,7 @@ static int f_seek (lua_State *L) {
|
|||||||
l_seeknum offset = (l_seeknum)p3;
|
l_seeknum offset = (l_seeknum)p3;
|
||||||
luaL_argcheck(L, (lua_Integer)offset == p3, 3,
|
luaL_argcheck(L, (lua_Integer)offset == p3, 3,
|
||||||
"not an integer in proper range");
|
"not an integer in proper range");
|
||||||
|
errno = 0;
|
||||||
op = l_fseek(f, offset, mode[op]);
|
op = l_fseek(f, offset, mode[op]);
|
||||||
if (l_unlikely(op))
|
if (l_unlikely(op))
|
||||||
return luaL_fileresult(L, 0, NULL); /* error */
|
return luaL_fileresult(L, 0, NULL); /* error */
|
||||||
@ -719,19 +726,25 @@ static int f_setvbuf (lua_State *L) {
|
|||||||
FILE *f = tofile(L);
|
FILE *f = tofile(L);
|
||||||
int op = luaL_checkoption(L, 2, NULL, modenames);
|
int op = luaL_checkoption(L, 2, NULL, modenames);
|
||||||
lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
|
lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
|
||||||
int res = setvbuf(f, NULL, mode[op], (size_t)sz);
|
int res;
|
||||||
|
errno = 0;
|
||||||
|
res = setvbuf(f, NULL, mode[op], (size_t)sz);
|
||||||
return luaL_fileresult(L, res == 0, NULL);
|
return luaL_fileresult(L, res == 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int io_flush (lua_State *L) {
|
static int io_flush (lua_State *L) {
|
||||||
return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
|
FILE *f = getiofile(L, IO_OUTPUT);
|
||||||
|
errno = 0;
|
||||||
|
return luaL_fileresult(L, fflush(f) == 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int f_flush (lua_State *L) {
|
static int f_flush (lua_State *L) {
|
||||||
return luaL_fileresult(L, fflush(tofile(L)) == 0, NULL);
|
FILE *f = tofile(L);
|
||||||
|
errno = 0;
|
||||||
|
return luaL_fileresult(L, fflush(f) == 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -773,7 +786,7 @@ static const luaL_Reg meth[] = {
|
|||||||
** metamethods for file handles
|
** metamethods for file handles
|
||||||
*/
|
*/
|
||||||
static const luaL_Reg metameth[] = {
|
static const luaL_Reg metameth[] = {
|
||||||
{"__index", NULL}, /* place holder */
|
{"__index", NULL}, /* placeholder */
|
||||||
{"__gc", f_gc},
|
{"__gc", f_gc},
|
||||||
{"__close", f_gc},
|
{"__close", f_gc},
|
||||||
{"__tostring", f_tostring},
|
{"__tostring", f_tostring},
|
||||||
|
@ -249,6 +249,15 @@ static int math_type (lua_State *L) {
|
|||||||
** ===================================================================
|
** ===================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
** This code uses lots of shifts. ANSI C does not allow shifts greater
|
||||||
|
** than or equal to the width of the type being shifted, so some shifts
|
||||||
|
** are written in convoluted ways to match that restriction. For
|
||||||
|
** preprocessor tests, it assumes a width of 32 bits, so the maximum
|
||||||
|
** shift there is 31 bits.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
/* number of binary digits in the mantissa of a float */
|
/* number of binary digits in the mantissa of a float */
|
||||||
#define FIGS l_floatatt(MANT_DIG)
|
#define FIGS l_floatatt(MANT_DIG)
|
||||||
|
|
||||||
@ -271,16 +280,19 @@ static int math_type (lua_State *L) {
|
|||||||
|
|
||||||
/* 'long' has at least 64 bits */
|
/* 'long' has at least 64 bits */
|
||||||
#define Rand64 unsigned long
|
#define Rand64 unsigned long
|
||||||
|
#define SRand64 long
|
||||||
|
|
||||||
#elif !defined(LUA_USE_C89) && defined(LLONG_MAX)
|
#elif !defined(LUA_USE_C89) && defined(LLONG_MAX)
|
||||||
|
|
||||||
/* there is a 'long long' type (which must have at least 64 bits) */
|
/* there is a 'long long' type (which must have at least 64 bits) */
|
||||||
#define Rand64 unsigned long long
|
#define Rand64 unsigned long long
|
||||||
|
#define SRand64 long long
|
||||||
|
|
||||||
#elif ((LUA_MAXUNSIGNED >> 31) >> 31) >= 3
|
#elif ((LUA_MAXUNSIGNED >> 31) >> 31) >= 3
|
||||||
|
|
||||||
/* 'lua_Unsigned' has at least 64 bits */
|
/* 'lua_Unsigned' has at least 64 bits */
|
||||||
#define Rand64 lua_Unsigned
|
#define Rand64 lua_Unsigned
|
||||||
|
#define SRand64 lua_Integer
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -319,23 +331,30 @@ static Rand64 nextrand (Rand64 *state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* must take care to not shift stuff by more than 63 slots */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Convert bits from a random integer into a float in the
|
** Convert bits from a random integer into a float in the
|
||||||
** interval [0,1), getting the higher FIG bits from the
|
** interval [0,1), getting the higher FIG bits from the
|
||||||
** random unsigned integer and converting that to a float.
|
** random unsigned integer and converting that to a float.
|
||||||
|
** Some old Microsoft compilers cannot cast an unsigned long
|
||||||
|
** to a floating-point number, so we use a signed long as an
|
||||||
|
** intermediary. When lua_Number is float or double, the shift ensures
|
||||||
|
** that 'sx' is non negative; in that case, a good compiler will remove
|
||||||
|
** the correction.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* must throw out the extra (64 - FIGS) bits */
|
/* must throw out the extra (64 - FIGS) bits */
|
||||||
#define shift64_FIG (64 - FIGS)
|
#define shift64_FIG (64 - FIGS)
|
||||||
|
|
||||||
/* to scale to [0, 1), multiply by scaleFIG = 2^(-FIGS) */
|
/* 2^(-FIGS) == 2^-1 / 2^(FIGS-1) */
|
||||||
#define scaleFIG (l_mathop(0.5) / ((Rand64)1 << (FIGS - 1)))
|
#define scaleFIG (l_mathop(0.5) / ((Rand64)1 << (FIGS - 1)))
|
||||||
|
|
||||||
static lua_Number I2d (Rand64 x) {
|
static lua_Number I2d (Rand64 x) {
|
||||||
return (lua_Number)(trim64(x) >> shift64_FIG) * scaleFIG;
|
SRand64 sx = (SRand64)(trim64(x) >> shift64_FIG);
|
||||||
|
lua_Number res = (lua_Number)(sx) * scaleFIG;
|
||||||
|
if (sx < 0)
|
||||||
|
res += l_mathop(1.0); /* correct the two's complement if negative */
|
||||||
|
lua_assert(0 <= res && res < 1);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* convert a 'Rand64' to a 'lua_Unsigned' */
|
/* convert a 'Rand64' to a 'lua_Unsigned' */
|
||||||
@ -471,8 +490,6 @@ static lua_Number I2d (Rand64 x) {
|
|||||||
|
|
||||||
#else /* 32 < FIGS <= 64 */
|
#else /* 32 < FIGS <= 64 */
|
||||||
|
|
||||||
/* must take care to not shift stuff by more than 31 slots */
|
|
||||||
|
|
||||||
/* 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 \
|
||||||
(l_mathop(1.0) / (UONE << 30) / l_mathop(8.0) / (UONE << (FIGS - 33)))
|
(l_mathop(1.0) / (UONE << 30) / l_mathop(8.0) / (UONE << (FIGS - 33)))
|
||||||
|
@ -24,15 +24,6 @@
|
|||||||
#include "lualib.h"
|
#include "lualib.h"
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
** LUA_IGMARK is a mark to ignore all before it when building the
|
|
||||||
** luaopen_ function name.
|
|
||||||
*/
|
|
||||||
#if !defined (LUA_IGMARK)
|
|
||||||
#define LUA_IGMARK "-"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** LUA_CSUBSEP is the character that replaces dots in submodule names
|
** LUA_CSUBSEP is the character that replaces dots in submodule names
|
||||||
** when searching for a C loader.
|
** when searching for a C loader.
|
||||||
|
@ -542,7 +542,7 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
|
|||||||
addstr2buff(&buff, fmt, strlen(fmt)); /* rest of 'fmt' */
|
addstr2buff(&buff, fmt, strlen(fmt)); /* rest of 'fmt' */
|
||||||
clearbuff(&buff); /* empty buffer into the stack */
|
clearbuff(&buff); /* empty buffer into the stack */
|
||||||
lua_assert(buff.pushed == 1);
|
lua_assert(buff.pushed == 1);
|
||||||
return svalue(s2v(L->top.p - 1));
|
return getstr(tsvalue(s2v(L->top.p - 1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -386,7 +386,7 @@ typedef struct GCObject {
|
|||||||
typedef struct TString {
|
typedef struct TString {
|
||||||
CommonHeader;
|
CommonHeader;
|
||||||
lu_byte extra; /* reserved words for short strings; "has hash" for longs */
|
lu_byte extra; /* reserved words for short strings; "has hash" for longs */
|
||||||
lu_byte shrlen; /* length for short strings */
|
lu_byte shrlen; /* length for short strings, 0xFF for long strings */
|
||||||
unsigned int hash;
|
unsigned int hash;
|
||||||
union {
|
union {
|
||||||
size_t lnglen; /* length for long strings */
|
size_t lnglen; /* length for long strings */
|
||||||
@ -398,19 +398,17 @@ typedef struct TString {
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Get the actual string (array of bytes) from a 'TString'.
|
** Get the actual string (array of bytes) from a 'TString'. (Generic
|
||||||
|
** version and specialized versions for long and short strings.)
|
||||||
*/
|
*/
|
||||||
#define getstr(ts) ((ts)->contents)
|
#define getstr(ts) ((ts)->contents)
|
||||||
|
#define getlngstr(ts) check_exp((ts)->shrlen == 0xFF, (ts)->contents)
|
||||||
|
#define getshrstr(ts) check_exp((ts)->shrlen != 0xFF, (ts)->contents)
|
||||||
|
|
||||||
|
|
||||||
/* get the actual string (array of bytes) from a Lua value */
|
|
||||||
#define svalue(o) getstr(tsvalue(o))
|
|
||||||
|
|
||||||
/* get string length from 'TString *s' */
|
/* get string length from 'TString *s' */
|
||||||
#define tsslen(s) ((s)->tt == LUA_VSHRSTR ? (s)->shrlen : (s)->u.lnglen)
|
#define tsslen(s) \
|
||||||
|
((s)->shrlen != 0xFF ? (s)->shrlen : (s)->u.lnglen)
|
||||||
/* get string length from 'TValue *o' */
|
|
||||||
#define vslen(o) tsslen(tsvalue(o))
|
|
||||||
|
|
||||||
/* }================================================================== */
|
/* }================================================================== */
|
||||||
|
|
||||||
|
@ -210,15 +210,15 @@ 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] */
|
||||||
OP_SETUPVAL,/* A B UpValue[B] := R[A] */
|
OP_SETUPVAL,/* A B UpValue[B] := R[A] */
|
||||||
|
|
||||||
OP_GETTABUP,/* A B C R[A] := UpValue[B][K[C]:string] */
|
OP_GETTABUP,/* A B C R[A] := UpValue[B][K[C]:shortstring] */
|
||||||
OP_GETTABLE,/* A B C R[A] := R[B][R[C]] */
|
OP_GETTABLE,/* A B C R[A] := R[B][R[C]] */
|
||||||
OP_GETI,/* A B C R[A] := R[B][C] */
|
OP_GETI,/* A B C R[A] := R[B][C] */
|
||||||
OP_GETFIELD,/* A B C R[A] := R[B][K[C]:string] */
|
OP_GETFIELD,/* A B C R[A] := R[B][K[C]:shortstring] */
|
||||||
|
|
||||||
OP_SETTABUP,/* A B C UpValue[A][K[B]:string] := RK(C) */
|
OP_SETTABUP,/* A B C UpValue[A][K[B]:shortstring] := RK(C) */
|
||||||
OP_SETTABLE,/* A B C R[A][R[B]] := RK(C) */
|
OP_SETTABLE,/* A B C R[A][R[B]] := RK(C) */
|
||||||
OP_SETI,/* A B C R[A][B] := RK(C) */
|
OP_SETI,/* A B C R[A][B] := RK(C) */
|
||||||
OP_SETFIELD,/* A B C R[A][K[B]:string] := RK(C) */
|
OP_SETFIELD,/* A B C R[A][K[B]:shortstring] := RK(C) */
|
||||||
|
|
||||||
OP_NEWTABLE,/* A B C k R[A] := {} */
|
OP_NEWTABLE,/* A B C k R[A] := {} */
|
||||||
|
|
||||||
|
@ -155,6 +155,7 @@ static int os_execute (lua_State *L) {
|
|||||||
|
|
||||||
static int os_remove (lua_State *L) {
|
static int os_remove (lua_State *L) {
|
||||||
const char *filename = luaL_checkstring(L, 1);
|
const char *filename = luaL_checkstring(L, 1);
|
||||||
|
errno = 0;
|
||||||
return luaL_fileresult(L, remove(filename) == 0, filename);
|
return luaL_fileresult(L, remove(filename) == 0, filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,6 +163,7 @@ static int os_remove (lua_State *L) {
|
|||||||
static int os_rename (lua_State *L) {
|
static int os_rename (lua_State *L) {
|
||||||
const char *fromname = luaL_checkstring(L, 1);
|
const char *fromname = luaL_checkstring(L, 1);
|
||||||
const char *toname = luaL_checkstring(L, 2);
|
const char *toname = luaL_checkstring(L, 2);
|
||||||
|
errno = 0;
|
||||||
return luaL_fileresult(L, rename(fromname, toname) == 0, NULL);
|
return luaL_fileresult(L, rename(fromname, toname) == 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1022,10 +1022,11 @@ static int explist (LexState *ls, expdesc *v) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void funcargs (LexState *ls, expdesc *f, int line) {
|
static void funcargs (LexState *ls, expdesc *f) {
|
||||||
FuncState *fs = ls->fs;
|
FuncState *fs = ls->fs;
|
||||||
expdesc args;
|
expdesc args;
|
||||||
int base, nparams;
|
int base, nparams;
|
||||||
|
int line = ls->linenumber;
|
||||||
switch (ls->t.token) {
|
switch (ls->t.token) {
|
||||||
case '(': { /* funcargs -> '(' [ explist ] ')' */
|
case '(': { /* funcargs -> '(' [ explist ] ')' */
|
||||||
luaX_next(ls);
|
luaX_next(ls);
|
||||||
@ -1063,8 +1064,8 @@ static void funcargs (LexState *ls, expdesc *f, int line) {
|
|||||||
}
|
}
|
||||||
init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2));
|
init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2));
|
||||||
luaK_fixline(fs, line);
|
luaK_fixline(fs, line);
|
||||||
fs->freereg = base+1; /* call remove function and arguments and leaves
|
fs->freereg = base+1; /* call removes function and arguments and leaves
|
||||||
(unless changed) one result */
|
one result (unless changed later) */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1103,7 +1104,6 @@ static void suffixedexp (LexState *ls, expdesc *v) {
|
|||||||
/* suffixedexp ->
|
/* suffixedexp ->
|
||||||
primaryexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs } */
|
primaryexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs } */
|
||||||
FuncState *fs = ls->fs;
|
FuncState *fs = ls->fs;
|
||||||
int line = ls->linenumber;
|
|
||||||
primaryexp(ls, v);
|
primaryexp(ls, v);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
switch (ls->t.token) {
|
switch (ls->t.token) {
|
||||||
@ -1123,12 +1123,12 @@ static void suffixedexp (LexState *ls, expdesc *v) {
|
|||||||
luaX_next(ls);
|
luaX_next(ls);
|
||||||
codename(ls, &key);
|
codename(ls, &key);
|
||||||
luaK_self(fs, v, &key);
|
luaK_self(fs, v, &key);
|
||||||
funcargs(ls, v, line);
|
funcargs(ls, v);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case '(': case TK_STRING: case '{': { /* funcargs */
|
case '(': case TK_STRING: case '{': { /* funcargs */
|
||||||
luaK_exp2nextreg(fs, v);
|
luaK_exp2nextreg(fs, v);
|
||||||
funcargs(ls, v, line);
|
funcargs(ls, v);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: return;
|
default: return;
|
||||||
|
@ -119,7 +119,7 @@ CallInfo *luaE_extendCI (lua_State *L) {
|
|||||||
/*
|
/*
|
||||||
** free all CallInfo structures not in use by a thread
|
** free all CallInfo structures not in use by a thread
|
||||||
*/
|
*/
|
||||||
void luaE_freeCI (lua_State *L) {
|
static void freeCI (lua_State *L) {
|
||||||
CallInfo *ci = L->ci;
|
CallInfo *ci = L->ci;
|
||||||
CallInfo *next = ci->next;
|
CallInfo *next = ci->next;
|
||||||
ci->next = NULL;
|
ci->next = NULL;
|
||||||
@ -204,7 +204,7 @@ static void freestack (lua_State *L) {
|
|||||||
if (L->stack.p == NULL)
|
if (L->stack.p == NULL)
|
||||||
return; /* stack not completely built yet */
|
return; /* stack not completely built yet */
|
||||||
L->ci = &L->base_ci; /* free the entire 'ci' list */
|
L->ci = &L->base_ci; /* free the entire 'ci' list */
|
||||||
luaE_freeCI(L);
|
freeCI(L);
|
||||||
lua_assert(L->nci == 0);
|
lua_assert(L->nci == 0);
|
||||||
luaM_freearray(L, L->stack.p, stacksize(L) + EXTRA_STACK); /* free stack */
|
luaM_freearray(L, L->stack.p, stacksize(L) + EXTRA_STACK); /* free stack */
|
||||||
}
|
}
|
||||||
@ -433,7 +433,7 @@ void luaE_warning (lua_State *L, const char *msg, int tocont) {
|
|||||||
void luaE_warnerror (lua_State *L, const char *where) {
|
void luaE_warnerror (lua_State *L, const char *where) {
|
||||||
TValue *errobj = s2v(L->top.p - 1); /* error object */
|
TValue *errobj = s2v(L->top.p - 1); /* error object */
|
||||||
const char *msg = (ttisstring(errobj))
|
const char *msg = (ttisstring(errobj))
|
||||||
? svalue(errobj)
|
? getstr(tsvalue(errobj))
|
||||||
: "error object is not a string";
|
: "error object is not a string";
|
||||||
/* produce warning "error in %s (%s)" (where, msg) */
|
/* produce warning "error in %s (%s)" (where, msg) */
|
||||||
luaE_warning(L, "error in ", 1);
|
luaE_warning(L, "error in ", 1);
|
||||||
|
@ -181,7 +181,7 @@ struct CallInfo {
|
|||||||
union {
|
union {
|
||||||
struct { /* only for Lua functions */
|
struct { /* only for Lua functions */
|
||||||
const Instruction *savedpc;
|
const Instruction *savedpc;
|
||||||
volatile l_signalT trap;
|
volatile l_signalT trap; /* function is tracing lines/counts */
|
||||||
int nextraargs; /* # of extra arguments in vararg functions */
|
int nextraargs; /* # of extra arguments in vararg functions */
|
||||||
} l;
|
} l;
|
||||||
struct { /* only for C functions */
|
struct { /* only for C functions */
|
||||||
@ -396,7 +396,6 @@ union GCUnion {
|
|||||||
LUAI_FUNC void luaE_setdebt (global_State *g, l_mem debt);
|
LUAI_FUNC void luaE_setdebt (global_State *g, l_mem debt);
|
||||||
LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1);
|
LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1);
|
||||||
LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L);
|
LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L);
|
||||||
LUAI_FUNC void luaE_freeCI (lua_State *L);
|
|
||||||
LUAI_FUNC void luaE_shrinkCI (lua_State *L);
|
LUAI_FUNC void luaE_shrinkCI (lua_State *L);
|
||||||
LUAI_FUNC void luaE_checkcstack (lua_State *L);
|
LUAI_FUNC void luaE_checkcstack (lua_State *L);
|
||||||
LUAI_FUNC void luaE_incCstack (lua_State *L);
|
LUAI_FUNC void luaE_incCstack (lua_State *L);
|
||||||
|
@ -36,7 +36,7 @@ int luaS_eqlngstr (TString *a, TString *b) {
|
|||||||
lua_assert(a->tt == LUA_VLNGSTR && b->tt == LUA_VLNGSTR);
|
lua_assert(a->tt == LUA_VLNGSTR && b->tt == LUA_VLNGSTR);
|
||||||
return (a == b) || /* same instance or... */
|
return (a == b) || /* same instance or... */
|
||||||
((len == b->u.lnglen) && /* equal length and ... */
|
((len == b->u.lnglen) && /* equal length and ... */
|
||||||
(memcmp(getstr(a), getstr(b), len) == 0)); /* equal contents */
|
(memcmp(getlngstr(a), getlngstr(b), len) == 0)); /* equal contents */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ unsigned int luaS_hashlongstr (TString *ts) {
|
|||||||
lua_assert(ts->tt == LUA_VLNGSTR);
|
lua_assert(ts->tt == LUA_VLNGSTR);
|
||||||
if (ts->extra == 0) { /* no hash? */
|
if (ts->extra == 0) { /* no hash? */
|
||||||
size_t len = ts->u.lnglen;
|
size_t len = ts->u.lnglen;
|
||||||
ts->hash = luaS_hash(getstr(ts), len, ts->hash);
|
ts->hash = luaS_hash(getlngstr(ts), len, ts->hash);
|
||||||
ts->extra = 1; /* now it has its hash */
|
ts->extra = 1; /* now it has its hash */
|
||||||
}
|
}
|
||||||
return ts->hash;
|
return ts->hash;
|
||||||
@ -157,6 +157,7 @@ static TString *createstrobj (lua_State *L, size_t l, int tag, unsigned int h) {
|
|||||||
TString *luaS_createlngstrobj (lua_State *L, size_t l) {
|
TString *luaS_createlngstrobj (lua_State *L, size_t l) {
|
||||||
TString *ts = createstrobj(L, l, LUA_VLNGSTR, G(L)->seed);
|
TString *ts = createstrobj(L, l, LUA_VLNGSTR, G(L)->seed);
|
||||||
ts->u.lnglen = l;
|
ts->u.lnglen = l;
|
||||||
|
ts->shrlen = 0xFF; /* signals that it is a long string */
|
||||||
return ts;
|
return ts;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,7 +194,7 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) {
|
|||||||
TString **list = &tb->hash[lmod(h, tb->size)];
|
TString **list = &tb->hash[lmod(h, tb->size)];
|
||||||
lua_assert(str != NULL); /* otherwise 'memcmp'/'memcpy' are undefined */
|
lua_assert(str != NULL); /* otherwise 'memcmp'/'memcpy' are undefined */
|
||||||
for (ts = *list; ts != NULL; ts = ts->u.hnext) {
|
for (ts = *list; ts != NULL; ts = ts->u.hnext) {
|
||||||
if (l == ts->shrlen && (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) {
|
if (l == ts->shrlen && (memcmp(str, getshrstr(ts), l * sizeof(char)) == 0)) {
|
||||||
/* found! */
|
/* found! */
|
||||||
if (isdead(g, ts)) /* dead (but not collected yet)? */
|
if (isdead(g, ts)) /* dead (but not collected yet)? */
|
||||||
changewhite(ts); /* resurrect it */
|
changewhite(ts); /* resurrect it */
|
||||||
@ -206,8 +207,8 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) {
|
|||||||
list = &tb->hash[lmod(h, tb->size)]; /* rehash with new size */
|
list = &tb->hash[lmod(h, tb->size)]; /* rehash with new size */
|
||||||
}
|
}
|
||||||
ts = createstrobj(L, l, LUA_VSHRSTR, h);
|
ts = createstrobj(L, l, LUA_VSHRSTR, h);
|
||||||
memcpy(getstr(ts), str, l * sizeof(char));
|
|
||||||
ts->shrlen = cast_byte(l);
|
ts->shrlen = cast_byte(l);
|
||||||
|
memcpy(getshrstr(ts), str, l * sizeof(char));
|
||||||
ts->u.hnext = *list;
|
ts->u.hnext = *list;
|
||||||
*list = ts;
|
*list = ts;
|
||||||
tb->nuse++;
|
tb->nuse++;
|
||||||
@ -223,10 +224,10 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
|
|||||||
return internshrstr(L, str, l);
|
return internshrstr(L, str, l);
|
||||||
else {
|
else {
|
||||||
TString *ts;
|
TString *ts;
|
||||||
if (l_unlikely(l >= (MAX_SIZE - sizeof(TString))/sizeof(char)))
|
if (l_unlikely(l * sizeof(char) >= (MAX_SIZE - sizeof(TString))))
|
||||||
luaM_toobig(L);
|
luaM_toobig(L);
|
||||||
ts = luaS_createlngstrobj(L, l);
|
ts = luaS_createlngstrobj(L, l);
|
||||||
memcpy(getstr(ts), str, l * sizeof(char));
|
memcpy(getlngstr(ts), str, l * sizeof(char));
|
||||||
return ts;
|
return ts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
39
src/ltable.c
39
src/ltable.c
@ -252,7 +252,7 @@ LUAI_FUNC unsigned int luaH_realasize (const Table *t) {
|
|||||||
return t->alimit; /* this is the size */
|
return t->alimit; /* this is the size */
|
||||||
else {
|
else {
|
||||||
unsigned int size = t->alimit;
|
unsigned int size = t->alimit;
|
||||||
/* compute the smallest power of 2 not smaller than 'n' */
|
/* compute the smallest power of 2 not smaller than 'size' */
|
||||||
size |= (size >> 1);
|
size |= (size >> 1);
|
||||||
size |= (size >> 2);
|
size |= (size >> 2);
|
||||||
size |= (size >> 4);
|
size |= (size >> 4);
|
||||||
@ -662,7 +662,8 @@ static Node *getfreepos (Table *t) {
|
|||||||
** put new key in its main position; otherwise (colliding node is in its main
|
** put new key in its main position; otherwise (colliding node is in its main
|
||||||
** position), new key goes to an empty position.
|
** position), new key goes to an empty position.
|
||||||
*/
|
*/
|
||||||
void luaH_newkey (lua_State *L, Table *t, const TValue *key, TValue *value) {
|
static void luaH_newkey (lua_State *L, Table *t, const TValue *key,
|
||||||
|
TValue *value) {
|
||||||
Node *mp;
|
Node *mp;
|
||||||
TValue aux;
|
TValue aux;
|
||||||
if (l_unlikely(ttisnil(key)))
|
if (l_unlikely(ttisnil(key)))
|
||||||
@ -721,22 +722,36 @@ void luaH_newkey (lua_State *L, Table *t, const TValue *key, TValue *value) {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
** Search function for integers. If integer is inside 'alimit', get it
|
** Search function for integers. If integer is inside 'alimit', get it
|
||||||
** directly from the array part. Otherwise, if 'alimit' is not equal to
|
** directly from the array part. Otherwise, if 'alimit' is not
|
||||||
** the real size of the array, key still can be in the array part. In
|
** the real size of the array, the key still can be in the array part.
|
||||||
** this case, try to avoid a call to 'luaH_realasize' when key is just
|
** In this case, do the "Xmilia trick" to check whether 'key-1' is
|
||||||
** one more than the limit (so that it can be incremented without
|
** smaller than the real size.
|
||||||
** changing the real size of the array).
|
** The trick works as follow: let 'p' be an integer such that
|
||||||
|
** '2^(p+1) >= alimit > 2^p', or '2^(p+1) > alimit-1 >= 2^p'.
|
||||||
|
** That is, 2^(p+1) is the real size of the array, and 'p' is the highest
|
||||||
|
** bit on in 'alimit-1'. What we have to check becomes 'key-1 < 2^(p+1)'.
|
||||||
|
** We compute '(key-1) & ~(alimit-1)', which we call 'res'; it will
|
||||||
|
** have the 'p' bit cleared. If the key is outside the array, that is,
|
||||||
|
** 'key-1 >= 2^(p+1)', then 'res' will have some bit on higher than 'p',
|
||||||
|
** therefore it will be larger or equal to 'alimit', and the check
|
||||||
|
** will fail. If 'key-1 < 2^(p+1)', then 'res' has no bit on higher than
|
||||||
|
** 'p', and as the bit 'p' itself was cleared, 'res' will be smaller
|
||||||
|
** than 2^p, therefore smaller than 'alimit', and the check succeeds.
|
||||||
|
** As special cases, when 'alimit' is 0 the condition is trivially false,
|
||||||
|
** and when 'alimit' is 1 the condition simplifies to 'key-1 < alimit'.
|
||||||
|
** If key is 0 or negative, 'res' will have its higher bit on, so that
|
||||||
|
** if cannot be smaller than alimit.
|
||||||
*/
|
*/
|
||||||
const TValue *luaH_getint (Table *t, lua_Integer key) {
|
const TValue *luaH_getint (Table *t, lua_Integer key) {
|
||||||
if (l_castS2U(key) - 1u < t->alimit) /* 'key' in [1, t->alimit]? */
|
lua_Unsigned alimit = t->alimit;
|
||||||
|
if (l_castS2U(key) - 1u < alimit) /* 'key' in [1, t->alimit]? */
|
||||||
return &t->array[key - 1];
|
return &t->array[key - 1];
|
||||||
else if (!limitequalsasize(t) && /* key still may be in the array part? */
|
else if (!isrealasize(t) && /* key still may be in the array part? */
|
||||||
(l_castS2U(key) == t->alimit + 1 ||
|
(((l_castS2U(key) - 1u) & ~(alimit - 1u)) < alimit)) {
|
||||||
l_castS2U(key) - 1u < luaH_realasize(t))) {
|
|
||||||
t->alimit = cast_uint(key); /* probably '#t' is here now */
|
t->alimit = cast_uint(key); /* probably '#t' is here now */
|
||||||
return &t->array[key - 1];
|
return &t->array[key - 1];
|
||||||
}
|
}
|
||||||
else {
|
else { /* key is not in the array part; check the hash */
|
||||||
Node *n = hashint(t, key);
|
Node *n = hashint(t, key);
|
||||||
for (;;) { /* check whether 'key' is somewhere in the chain */
|
for (;;) { /* check whether 'key' is somewhere in the chain */
|
||||||
if (keyisinteger(n) && keyival(n) == key)
|
if (keyisinteger(n) && keyival(n) == key)
|
||||||
|
@ -41,8 +41,6 @@ LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key,
|
|||||||
LUAI_FUNC const TValue *luaH_getshortstr (Table *t, TString *key);
|
LUAI_FUNC const TValue *luaH_getshortstr (Table *t, TString *key);
|
||||||
LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key);
|
LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key);
|
||||||
LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key);
|
LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key);
|
||||||
LUAI_FUNC void luaH_newkey (lua_State *L, Table *t, const TValue *key,
|
|
||||||
TValue *value);
|
|
||||||
LUAI_FUNC void luaH_set (lua_State *L, Table *t, const TValue *key,
|
LUAI_FUNC void luaH_set (lua_State *L, Table *t, const TValue *key,
|
||||||
TValue *value);
|
TValue *value);
|
||||||
LUAI_FUNC void luaH_finishset (lua_State *L, Table *t, const TValue *key,
|
LUAI_FUNC void luaH_finishset (lua_State *L, Table *t, const TValue *key,
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "lobject.h"
|
#include "lobject.h"
|
||||||
#include "lstate.h"
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -96,8 +95,8 @@ LUAI_FUNC int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2,
|
|||||||
int inv, int isfloat, TMS event);
|
int inv, int isfloat, TMS event);
|
||||||
|
|
||||||
LUAI_FUNC void luaT_adjustvarargs (lua_State *L, int nfixparams,
|
LUAI_FUNC void luaT_adjustvarargs (lua_State *L, int nfixparams,
|
||||||
CallInfo *ci, const Proto *p);
|
struct CallInfo *ci, const Proto *p);
|
||||||
LUAI_FUNC void luaT_getvarargs (lua_State *L, CallInfo *ci,
|
LUAI_FUNC void luaT_getvarargs (lua_State *L, struct CallInfo *ci,
|
||||||
StkId where, int wanted);
|
StkId where, int wanted);
|
||||||
|
|
||||||
|
|
||||||
|
17
src/lua.c
17
src/lua.c
@ -115,12 +115,13 @@ static void l_message (const char *pname, const char *msg) {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
** Check whether 'status' is not OK and, if so, prints the error
|
** Check whether 'status' is not OK and, if so, prints the error
|
||||||
** message on the top of the stack. It assumes that the error object
|
** message on the top of the stack.
|
||||||
** is a string, as it was either generated by Lua or by 'msghandler'.
|
|
||||||
*/
|
*/
|
||||||
static int report (lua_State *L, int status) {
|
static int report (lua_State *L, int status) {
|
||||||
if (status != LUA_OK) {
|
if (status != LUA_OK) {
|
||||||
const char *msg = lua_tostring(L, -1);
|
const char *msg = lua_tostring(L, -1);
|
||||||
|
if (msg == NULL)
|
||||||
|
msg = "(error message not a string)";
|
||||||
l_message(progname, msg);
|
l_message(progname, msg);
|
||||||
lua_pop(L, 1); /* remove message */
|
lua_pop(L, 1); /* remove message */
|
||||||
}
|
}
|
||||||
@ -210,12 +211,17 @@ static int dostring (lua_State *L, const char *s, const char *name) {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
** Receives 'globname[=modname]' and runs 'globname = require(modname)'.
|
** Receives 'globname[=modname]' and runs 'globname = require(modname)'.
|
||||||
|
** If there is no explicit modname and globname contains a '-', cut
|
||||||
|
** the suffix after '-' (the "version") to make the global name.
|
||||||
*/
|
*/
|
||||||
static int dolibrary (lua_State *L, char *globname) {
|
static int dolibrary (lua_State *L, char *globname) {
|
||||||
int status;
|
int status;
|
||||||
|
char *suffix = NULL;
|
||||||
char *modname = strchr(globname, '=');
|
char *modname = strchr(globname, '=');
|
||||||
if (modname == NULL) /* no explicit name? */
|
if (modname == NULL) { /* no explicit name? */
|
||||||
modname = globname; /* module name is equal to global name */
|
modname = globname; /* module name is equal to global name */
|
||||||
|
suffix = strchr(modname, *LUA_IGMARK); /* look for a suffix mark */
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
*modname = '\0'; /* global name ends here */
|
*modname = '\0'; /* global name ends here */
|
||||||
modname++; /* module name starts after the '=' */
|
modname++; /* module name starts after the '=' */
|
||||||
@ -223,8 +229,11 @@ static int dolibrary (lua_State *L, char *globname) {
|
|||||||
lua_getglobal(L, "require");
|
lua_getglobal(L, "require");
|
||||||
lua_pushstring(L, modname);
|
lua_pushstring(L, modname);
|
||||||
status = docall(L, 1, 1); /* call 'require(modname)' */
|
status = docall(L, 1, 1); /* call 'require(modname)' */
|
||||||
if (status == LUA_OK)
|
if (status == LUA_OK) {
|
||||||
|
if (suffix != NULL) /* is there a suffix mark? */
|
||||||
|
*suffix = '\0'; /* remove suffix from global name */
|
||||||
lua_setglobal(L, globname); /* globname = require(modname) */
|
lua_setglobal(L, globname); /* globname = require(modname) */
|
||||||
|
}
|
||||||
return report(L, status);
|
return report(L, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 "6"
|
#define LUA_VERSION_RELEASE "7"
|
||||||
|
|
||||||
#define LUA_VERSION_NUM 504
|
#define LUA_VERSION_NUM 504
|
||||||
#define LUA_VERSION_RELEASE_NUM (LUA_VERSION_NUM * 100 + 6)
|
#define LUA_VERSION_RELEASE_NUM (LUA_VERSION_NUM * 100 + 7)
|
||||||
|
|
||||||
#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-2023 Lua.org, PUC-Rio"
|
#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2024 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"
|
||||||
|
|
||||||
|
|
||||||
@ -497,7 +497,7 @@ struct lua_Debug {
|
|||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* Copyright (C) 1994-2023 Lua.org, PUC-Rio.
|
* Copyright (C) 1994-2024 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
|
||||||
|
@ -257,6 +257,15 @@
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** LUA_IGMARK is a mark to ignore all after it when building the
|
||||||
|
** module name (e.g., used to build the luaopen_ function name).
|
||||||
|
** Typically, the suffix after the mark is the module version,
|
||||||
|
** as in "mod-v1.2.so".
|
||||||
|
*/
|
||||||
|
#define LUA_IGMARK "-"
|
||||||
|
|
||||||
/* }================================================================== */
|
/* }================================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ static size_t loadUnsigned (LoadState *S, size_t limit) {
|
|||||||
|
|
||||||
|
|
||||||
static size_t loadSize (LoadState *S) {
|
static size_t loadSize (LoadState *S) {
|
||||||
return loadUnsigned(S, ~(size_t)0);
|
return loadUnsigned(S, MAX_SIZET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -122,7 +122,7 @@ static TString *loadStringN (LoadState *S, Proto *p) {
|
|||||||
ts = luaS_createlngstrobj(L, size); /* create string */
|
ts = luaS_createlngstrobj(L, size); /* create string */
|
||||||
setsvalue2s(L, L->top.p, ts); /* anchor it ('loadVector' can GC) */
|
setsvalue2s(L, L->top.p, ts); /* anchor it ('loadVector' can GC) */
|
||||||
luaD_inctop(L);
|
luaD_inctop(L);
|
||||||
loadVector(S, getstr(ts), size); /* load directly in final place */
|
loadVector(S, getlngstr(ts), size); /* load directly in final place */
|
||||||
L->top.p--; /* pop string */
|
L->top.p--; /* pop string */
|
||||||
}
|
}
|
||||||
luaC_objbarrier(L, p, ts);
|
luaC_objbarrier(L, p, ts);
|
||||||
|
@ -21,8 +21,7 @@
|
|||||||
/*
|
/*
|
||||||
** Encode major-minor version in one byte, one nibble for each
|
** Encode major-minor version in one byte, one nibble for each
|
||||||
*/
|
*/
|
||||||
#define MYINT(s) (s[0]-'0') /* assume one-digit numerals */
|
#define LUAC_VERSION (((LUA_VERSION_NUM / 100) * 16) + LUA_VERSION_NUM % 100)
|
||||||
#define LUAC_VERSION (MYINT(LUA_VERSION_MAJOR)*16+MYINT(LUA_VERSION_MINOR))
|
|
||||||
|
|
||||||
#define LUAC_FORMAT 0 /* this is the official format */
|
#define LUAC_FORMAT 0 /* this is the official format */
|
||||||
|
|
||||||
|
78
src/lvm.c
78
src/lvm.c
@ -91,8 +91,10 @@ static int l_strton (const TValue *obj, TValue *result) {
|
|||||||
lua_assert(obj != result);
|
lua_assert(obj != result);
|
||||||
if (!cvt2num(obj)) /* is object not a string? */
|
if (!cvt2num(obj)) /* is object not a string? */
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else {
|
||||||
return (luaO_str2num(svalue(obj), result) == vslen(obj) + 1);
|
TString *st = tsvalue(obj);
|
||||||
|
return (luaO_str2num(getstr(st), result) == tsslen(st) + 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -366,30 +368,32 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Compare two strings 'ls' x 'rs', returning an integer less-equal-
|
** Compare two strings 'ts1' x 'ts2', returning an integer less-equal-
|
||||||
** -greater than zero if 'ls' is less-equal-greater than 'rs'.
|
** -greater than zero if 'ts1' is less-equal-greater than 'ts2'.
|
||||||
** The code is a little tricky because it allows '\0' in the strings
|
** The code is a little tricky because it allows '\0' in the strings
|
||||||
** and it uses 'strcoll' (to respect locales) for each segments
|
** and it uses 'strcoll' (to respect locales) for each segment
|
||||||
** of the strings.
|
** of the strings. Note that segments can compare equal but still
|
||||||
|
** have different lengths.
|
||||||
*/
|
*/
|
||||||
static int l_strcmp (const TString *ls, const TString *rs) {
|
static int l_strcmp (const TString *ts1, const TString *ts2) {
|
||||||
const char *l = getstr(ls);
|
const char *s1 = getstr(ts1);
|
||||||
size_t ll = tsslen(ls);
|
size_t rl1 = tsslen(ts1); /* real length */
|
||||||
const char *r = getstr(rs);
|
const char *s2 = getstr(ts2);
|
||||||
size_t lr = tsslen(rs);
|
size_t rl2 = tsslen(ts2);
|
||||||
for (;;) { /* for each segment */
|
for (;;) { /* for each segment */
|
||||||
int temp = strcoll(l, r);
|
int temp = strcoll(s1, s2);
|
||||||
if (temp != 0) /* not equal? */
|
if (temp != 0) /* not equal? */
|
||||||
return temp; /* done */
|
return temp; /* done */
|
||||||
else { /* strings are equal up to a '\0' */
|
else { /* strings are equal up to a '\0' */
|
||||||
size_t len = strlen(l); /* index of first '\0' in both strings */
|
size_t zl1 = strlen(s1); /* index of first '\0' in 's1' */
|
||||||
if (len == lr) /* 'rs' is finished? */
|
size_t zl2 = strlen(s2); /* index of first '\0' in 's2' */
|
||||||
return (len == ll) ? 0 : 1; /* check 'ls' */
|
if (zl2 == rl2) /* 's2' is finished? */
|
||||||
else if (len == ll) /* 'ls' is finished? */
|
return (zl1 == rl1) ? 0 : 1; /* check 's1' */
|
||||||
return -1; /* 'ls' is less than 'rs' ('rs' is not finished) */
|
else if (zl1 == rl1) /* 's1' is finished? */
|
||||||
/* both strings longer than 'len'; go on comparing after the '\0' */
|
return -1; /* 's1' is less than 's2' ('s2' is not finished) */
|
||||||
len++;
|
/* both strings longer than 'zl'; go on comparing after the '\0' */
|
||||||
l += len; ll -= len; r += len; lr -= len;
|
zl1++; zl2++;
|
||||||
|
s1 += zl1; rl1 -= zl1; s2 += zl2; rl2 -= zl2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -624,8 +628,9 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) {
|
|||||||
static void copy2buff (StkId top, int n, char *buff) {
|
static void copy2buff (StkId top, int n, char *buff) {
|
||||||
size_t tl = 0; /* size already copied */
|
size_t tl = 0; /* size already copied */
|
||||||
do {
|
do {
|
||||||
size_t l = vslen(s2v(top - n)); /* length of string being copied */
|
TString *st = tsvalue(s2v(top - n));
|
||||||
memcpy(buff + tl, svalue(s2v(top - n)), l * sizeof(char));
|
size_t l = tsslen(st); /* length of string being copied */
|
||||||
|
memcpy(buff + tl, getstr(st), l * sizeof(char));
|
||||||
tl += l;
|
tl += l;
|
||||||
} while (--n > 0);
|
} while (--n > 0);
|
||||||
}
|
}
|
||||||
@ -651,12 +656,12 @@ void luaV_concat (lua_State *L, int total) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* at least two non-empty string values; get as many as possible */
|
/* at least two non-empty string values; get as many as possible */
|
||||||
size_t tl = vslen(s2v(top - 1));
|
size_t tl = tsslen(tsvalue(s2v(top - 1)));
|
||||||
TString *ts;
|
TString *ts;
|
||||||
/* collect total length and number of strings */
|
/* collect total length and number of strings */
|
||||||
for (n = 1; n < total && tostring(L, s2v(top - n - 1)); n++) {
|
for (n = 1; n < total && tostring(L, s2v(top - n - 1)); n++) {
|
||||||
size_t l = vslen(s2v(top - n - 1));
|
size_t l = tsslen(tsvalue(s2v(top - n - 1)));
|
||||||
if (l_unlikely(l >= (MAX_SIZE/sizeof(char)) - tl)) {
|
if (l_unlikely(l >= MAX_SIZE - sizeof(TString) - tl)) {
|
||||||
L->top.p = top - total; /* pop strings to avoid wasting stack */
|
L->top.p = top - total; /* pop strings to avoid wasting stack */
|
||||||
luaG_runerror(L, "string length overflow");
|
luaG_runerror(L, "string length overflow");
|
||||||
}
|
}
|
||||||
@ -669,7 +674,7 @@ void luaV_concat (lua_State *L, int total) {
|
|||||||
}
|
}
|
||||||
else { /* long string; copy strings directly to final result */
|
else { /* long string; copy strings directly to final result */
|
||||||
ts = luaS_createlngstrobj(L, tl);
|
ts = luaS_createlngstrobj(L, tl);
|
||||||
copy2buff(top, n, getstr(ts));
|
copy2buff(top, n, getlngstr(ts));
|
||||||
}
|
}
|
||||||
setsvalue2s(L, top - n, ts); /* create result */
|
setsvalue2s(L, top - n, ts); /* create result */
|
||||||
}
|
}
|
||||||
@ -1155,18 +1160,11 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|||||||
startfunc:
|
startfunc:
|
||||||
trap = L->hookmask;
|
trap = L->hookmask;
|
||||||
returning: /* trap already set */
|
returning: /* trap already set */
|
||||||
cl = clLvalue(s2v(ci->func.p));
|
cl = ci_func(ci);
|
||||||
k = cl->p->k;
|
k = cl->p->k;
|
||||||
pc = ci->u.l.savedpc;
|
pc = ci->u.l.savedpc;
|
||||||
if (l_unlikely(trap)) {
|
if (l_unlikely(trap))
|
||||||
if (pc == cl->p->code) { /* first instruction (not resuming)? */
|
trap = luaG_tracecall(L);
|
||||||
if (cl->p->is_vararg)
|
|
||||||
trap = 0; /* hooks will start after VARARGPREP instruction */
|
|
||||||
else /* check 'call' hook */
|
|
||||||
luaD_hookcall(L, ci);
|
|
||||||
}
|
|
||||||
ci->u.l.trap = 1; /* assume trap is on, for now */
|
|
||||||
}
|
|
||||||
base = ci->func.p + 1;
|
base = ci->func.p + 1;
|
||||||
/* main loop of interpreter */
|
/* main loop of interpreter */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@ -1253,7 +1251,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|||||||
const TValue *slot;
|
const TValue *slot;
|
||||||
TValue *upval = cl->upvals[GETARG_B(i)]->v.p;
|
TValue *upval = cl->upvals[GETARG_B(i)]->v.p;
|
||||||
TValue *rc = KC(i);
|
TValue *rc = KC(i);
|
||||||
TString *key = tsvalue(rc); /* key must be a string */
|
TString *key = tsvalue(rc); /* key must be a short string */
|
||||||
if (luaV_fastget(L, upval, key, slot, luaH_getshortstr)) {
|
if (luaV_fastget(L, upval, key, slot, luaH_getshortstr)) {
|
||||||
setobj2s(L, ra, slot);
|
setobj2s(L, ra, slot);
|
||||||
}
|
}
|
||||||
@ -1296,7 +1294,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|||||||
const TValue *slot;
|
const TValue *slot;
|
||||||
TValue *rb = vRB(i);
|
TValue *rb = vRB(i);
|
||||||
TValue *rc = KC(i);
|
TValue *rc = KC(i);
|
||||||
TString *key = tsvalue(rc); /* key must be a string */
|
TString *key = tsvalue(rc); /* key must be a short string */
|
||||||
if (luaV_fastget(L, rb, key, slot, luaH_getshortstr)) {
|
if (luaV_fastget(L, rb, key, slot, luaH_getshortstr)) {
|
||||||
setobj2s(L, ra, slot);
|
setobj2s(L, ra, slot);
|
||||||
}
|
}
|
||||||
@ -1309,7 +1307,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|||||||
TValue *upval = cl->upvals[GETARG_A(i)]->v.p;
|
TValue *upval = cl->upvals[GETARG_A(i)]->v.p;
|
||||||
TValue *rb = KB(i);
|
TValue *rb = KB(i);
|
||||||
TValue *rc = RKC(i);
|
TValue *rc = RKC(i);
|
||||||
TString *key = tsvalue(rb); /* key must be a string */
|
TString *key = tsvalue(rb); /* key must be a short string */
|
||||||
if (luaV_fastget(L, upval, key, slot, luaH_getshortstr)) {
|
if (luaV_fastget(L, upval, key, slot, luaH_getshortstr)) {
|
||||||
luaV_finishfastset(L, upval, slot, rc);
|
luaV_finishfastset(L, upval, slot, rc);
|
||||||
}
|
}
|
||||||
@ -1352,7 +1350,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|||||||
const TValue *slot;
|
const TValue *slot;
|
||||||
TValue *rb = KB(i);
|
TValue *rb = KB(i);
|
||||||
TValue *rc = RKC(i);
|
TValue *rc = RKC(i);
|
||||||
TString *key = tsvalue(rb); /* key must be a string */
|
TString *key = tsvalue(rb); /* key must be a short string */
|
||||||
if (luaV_fastget(L, s2v(ra), key, slot, luaH_getshortstr)) {
|
if (luaV_fastget(L, s2v(ra), key, slot, luaH_getshortstr)) {
|
||||||
luaV_finishfastset(L, s2v(ra), slot, rc);
|
luaV_finishfastset(L, s2v(ra), slot, rc);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user