Update LUA to 5.3.3 (nw)

This commit is contained in:
Miodrag Milanovic 2016-09-03 14:34:39 +02:00
parent 9a8964d5d0
commit a6409d692e
33 changed files with 1246 additions and 782 deletions

View File

@ -46,7 +46,7 @@ TO_MAN= lua.1 luac.1
# Lua version and release. # Lua version and release.
V= 5.3 V= 5.3
R= $V.2 R= $V.3
# Targets start here. # Targets start here.
all: $(PLAT) all: $(PLAT)

2
3rdparty/lua/README vendored
View File

@ -1,5 +1,5 @@
This is Lua 5.3.2, released on 25 Nov 2015. This is Lua 5.3.3, released on 30 May 2016.
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.

View File

@ -32,7 +32,7 @@ For a complete introduction to Lua programming, see the book
<P> <P>
<SMALL> <SMALL>
Copyright &copy; 2015 Lua.org, PUC-Rio. Copyright &copy; 2015&ndash;2016 Lua.org, PUC-Rio.
Freely available under the terms of the Freely available under the terms of the
<A HREF="http://www.lua.org/license.html">Lua license</A>. <A HREF="http://www.lua.org/license.html">Lua license</A>.
</SMALL> </SMALL>
@ -608,10 +608,10 @@ Freely available under the terms of the
<P CLASS="footer"> <P CLASS="footer">
Last update: Last update:
Wed Jun 3 08:27:30 BRT 2015 Thu Jan 14 10:14:28 BRST 2016
</P> </P>
<!-- <!--
Last change: revised for Lua 5.3.1 Last change: revised for Lua 5.3.3
--> -->
</BODY> </BODY>

View File

@ -92,6 +92,7 @@ table hr {
.footer { .footer {
color: gray ; color: gray ;
font-size: x-small ; font-size: x-small ;
text-transform: lowercase ;
} }
input[type=text] { input[type=text] {
@ -157,3 +158,7 @@ table.book span {
display: block ; display: block ;
margin-top: 0.25em ; margin-top: 0.25em ;
} }
img {
background-color: white ;
}

View File

@ -19,7 +19,7 @@ by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes
<P> <P>
<SMALL> <SMALL>
Copyright &copy; 2015 Lua.org, PUC-Rio. Copyright &copy; 2015&ndash;2016 Lua.org, PUC-Rio.
Freely available under the terms of the Freely available under the terms of the
<a href="http://www.lua.org/license.html">Lua license</a>. <a href="http://www.lua.org/license.html">Lua license</a>.
</SMALL> </SMALL>
@ -35,7 +35,7 @@ Freely available under the terms of the
<!-- ====================================================================== --> <!-- ====================================================================== -->
<p> <p>
<!-- $Id: manual.of,v 1.153 2015/11/25 16:57:42 roberto Exp $ --> <!-- $Id: manual.of,v 1.162 2016/05/30 15:57:03 roberto Exp $ -->
@ -43,30 +43,47 @@ Freely available under the terms of the
<h1>1 &ndash; <a name="1">Introduction</a></h1> <h1>1 &ndash; <a name="1">Introduction</a></h1>
<p> <p>
Lua is an extension programming language designed to support Lua is a powerful, efficient, lightweight, embeddable scripting language.
general procedural programming with data description It supports procedural programming,
facilities. object-oriented programming, functional programming,
Lua also offers good support for object-oriented programming, data-driven programming, and data description.
functional programming, and data-driven programming.
Lua is intended to be used as a powerful, lightweight,
embeddable scripting language for any program that needs one. <p>
Lua combines simple procedural syntax with powerful data description
constructs based on associative arrays and extensible semantics.
Lua is dynamically typed,
runs by interpreting bytecode with a register-based
virtual machine,
and has automatic memory management with
incremental garbage collection,
making it ideal for configuration, scripting,
and rapid prototyping.
<p>
Lua is implemented as a library, written in <em>clean C</em>, Lua is implemented as a library, written in <em>clean C</em>,
the common subset of Standard&nbsp;C and C++. the common subset of Standard&nbsp;C and C++.
The Lua distribution includes a host program called <code>lua</code>,
which uses the Lua library to offer a complete,
standalone Lua interpreter,
for interactive or batch use.
Lua is intended to be used both as a powerful, lightweight,
embeddable scripting language for any program that needs one,
and as a powerful but lightweight and efficient stand-alone language.
<p> <p>
As an extension language, Lua has no notion of a "main" program: As an extension language, Lua has no notion of a "main" program:
it only works <em>embedded</em> in a host client, it works <em>embedded</em> in a host client,
called the <em>embedding program</em> or simply the <em>host</em>. called the <em>embedding program</em> or simply the <em>host</em>.
(Frequently, this host is the stand-alone <code>lua</code> program.)
The host program can invoke functions to execute a piece of Lua code, The host program can invoke functions to execute a piece of Lua code,
can write and read Lua variables, can write and read Lua variables,
and can register C&nbsp;functions to be called by Lua code. and can register C&nbsp;functions to be called by Lua code.
Through the use of C&nbsp;functions, Lua can be augmented to cope with Through the use of C&nbsp;functions, Lua can be augmented to cope with
a wide range of different domains, a wide range of different domains,
thus creating customized programming languages sharing a syntactical framework. thus creating customized programming languages sharing a syntactical framework.
The Lua distribution includes a sample host program called <code>lua</code>,
which uses the Lua library to offer a complete, standalone Lua interpreter,
for interactive or batch use.
<p> <p>
@ -351,8 +368,8 @@ It is up to the Lua program or its host to handle such error objects.
When you use <a href="#pdf-xpcall"><code>xpcall</code></a> or <a href="#lua_pcall"><code>lua_pcall</code></a>, When you use <a href="#pdf-xpcall"><code>xpcall</code></a> or <a href="#lua_pcall"><code>lua_pcall</code></a>,
you may give a <em>message handler</em> you may 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 message This function is called with the original error object
and returns a new error message. and returns a new error object.
It is called before the error unwinds the stack, It is called before the error unwinds the stack,
so that it can gather more information about the error, so that it can gather more information about the error,
for instance by inspecting the stack and creating a stack traceback. for instance by inspecting the stack and creating a stack traceback.
@ -382,16 +399,23 @@ Lua calls this function to perform the addition.
<p> <p>
The keys in a metatable are derived from the <em>event</em> names; The key for each event in a metatable is a string
with the event name prefixed by two underscores;
the corresponding values are called <em>metamethods</em>. the corresponding values are called <em>metamethods</em>.
In the previous example, the event is <code>"add"</code> In the previous example, the key is "<code>__add</code>"
and the metamethod is the function that performs the addition. and the metamethod is the function that performs the addition.
<p> <p>
You can query the metatable of any value You can query the metatable of any value
using the <a href="#pdf-getmetatable"><code>getmetatable</code></a> function. using the <a href="#pdf-getmetatable"><code>getmetatable</code></a> function.
Lua queries metamethods in metatables using a raw access (see <a href="#pdf-rawget"><code>rawget</code></a>).
So, to retrieve the metamethod for event <code>ev</code> in object <code>o</code>,
Lua does the equivalent to the following code:
<pre>
rawget(getmetatable(<em>o</em>) or {}, "__<em>ev</em>")
</pre>
<p> <p>
You can replace the metatable of tables You can replace the metatable of tables
@ -420,18 +444,7 @@ when a userdata or a table is garbage collected (<a href="#2.5">&sect;2.5</a>).
<p> <p>
A detailed list of events controlled by metatables is given next. For the unary operators (negation, length, and bitwise NOT),
Each operation is identified by its corresponding event name.
The key for each event is a string with its name prefixed by
two underscores, '<code>__</code>';
for instance, the key for operation "add" is the
string "<code>__add</code>".
Note that queries for metamethods are always raw;
the access to a metamethod does not invoke other metamethods.
<p>
For the unary operators (negation, length, and bitwise not),
the metamethod is computed and called with a dummy second operand, the metamethod is computed and called with a dummy second operand,
equal to the first one. equal to the first one.
This extra operand is only to simplify Lua's internals This extra operand is only to simplify Lua's internals
@ -440,17 +453,21 @@ and may be removed in future versions.
(For most uses this extra operand is irrelevant.) (For most uses this extra operand is irrelevant.)
<p>
A detailed list of events controlled by metatables is given next.
Each operation is identified by its corresponding key.
<ul> <ul>
<li><b>"add": </b> <li><b><code>__add</code>: </b>
the <code>+</code> operation. the addition (<code>+</code>) operation.
If any operand for an addition is not a number If any operand for an addition is not a number
(nor a string coercible to a number), (nor a string coercible to a number),
Lua will try to call a metamethod. Lua will try to call a metamethod.
First, Lua will check the first operand (even if it is valid). First, Lua will check the first operand (even if it is valid).
If that operand does not define a metamethod for the "<code>__add</code>" event, If that operand does not define a metamethod for <code>__add</code>,
then Lua will check the second operand. then Lua will check the second operand.
If Lua can find a metamethod, If Lua can find a metamethod,
it calls the metamethod with the two operands as arguments, it calls the metamethod with the two operands as arguments,
@ -461,99 +478,84 @@ Otherwise,
it raises an error. it raises an error.
</li> </li>
<li><b>"sub": </b> <li><b><code>__sub</code>: </b>
the <code>-</code> operation. the subtraction (<code>-</code>) operation.
Behavior similar to the addition operation.
Behavior similar to the "add" operation.
</li> </li>
<li><b>"mul": </b> <li><b><code>__mul</code>: </b>
the <code>*</code> operation. the multiplication (<code>*</code>) operation.
Behavior similar to the addition operation.
Behavior similar to the "add" operation.
</li> </li>
<li><b>"div": </b> <li><b><code>__div</code>: </b>
the <code>/</code> operation. the division (<code>/</code>) operation.
Behavior similar to the addition operation.
Behavior similar to the "add" operation.
</li> </li>
<li><b>"mod": </b> <li><b><code>__mod</code>: </b>
the <code>%</code> operation. the modulo (<code>%</code>) operation.
Behavior similar to the addition operation.
Behavior similar to the "add" operation.
</li> </li>
<li><b>"pow": </b> <li><b><code>__pow</code>: </b>
the <code>^</code> (exponentiation) operation. the exponentiation (<code>^</code>) operation.
Behavior similar to the addition operation.
Behavior similar to the "add" operation.
</li> </li>
<li><b>"unm": </b> <li><b><code>__unm</code>: </b>
the <code>-</code> (unary minus) operation. the negation (unary <code>-</code>) operation.
Behavior similar to the addition operation.
Behavior similar to the "add" operation.
</li> </li>
<li><b>"idiv": </b> <li><b><code>__idiv</code>: </b>
the <code>//</code> (floor division) operation. the floor division (<code>//</code>) operation.
Behavior similar to the addition operation.
Behavior similar to the "add" operation.
</li> </li>
<li><b>"band": </b> <li><b><code>__band</code>: </b>
the <code>&amp;</code> (bitwise and) operation. the bitwise AND (<code>&amp;</code>) operation.
Behavior similar to the addition operation,
Behavior similar to the "add" operation,
except that Lua will try a metamethod except that Lua will try a metamethod
if any operand is neither an integer if any operand is neither an integer
nor a value coercible to an integer (see <a href="#3.4.3">&sect;3.4.3</a>). nor a value coercible to an integer (see <a href="#3.4.3">&sect;3.4.3</a>).
</li> </li>
<li><b>"bor": </b> <li><b><code>__bor</code>: </b>
the <code>|</code> (bitwise or) operation. the bitwise OR (<code>|</code>) operation.
Behavior similar to the bitwise AND operation.
Behavior similar to the "band" operation.
</li> </li>
<li><b>"bxor": </b> <li><b><code>__bxor</code>: </b>
the <code>~</code> (bitwise exclusive or) operation. the bitwise exclusive OR (binary <code>~</code>) operation.
Behavior similar to the bitwise AND operation.
Behavior similar to the "band" operation.
</li> </li>
<li><b>"bnot": </b> <li><b><code>__bnot</code>: </b>
the <code>~</code> (bitwise unary not) operation. the bitwise NOT (unary <code>~</code>) operation.
Behavior similar to the bitwise AND operation.
Behavior similar to the "band" operation.
</li> </li>
<li><b>"shl": </b> <li><b><code>__shl</code>: </b>
the <code>&lt;&lt;</code> (bitwise left shift) operation. the bitwise left shift (<code>&lt;&lt;</code>) operation.
Behavior similar to the bitwise AND operation.
Behavior similar to the "band" operation.
</li> </li>
<li><b>"shr": </b> <li><b><code>__shr</code>: </b>
the <code>&gt;&gt;</code> (bitwise right shift) operation. the bitwise right shift (<code>&gt;&gt;</code>) operation.
Behavior similar to the bitwise AND operation.
Behavior similar to the "band" operation.
</li> </li>
<li><b>"concat": </b> <li><b><code>__concat</code>: </b>
the <code>..</code> (concatenation) operation. the concatenation (<code>..</code>) operation.
Behavior similar to the addition operation,
Behavior similar to the "add" operation,
except that Lua will try a metamethod except that Lua will try a metamethod
if any operand is neither a string nor a number if any operand is neither a string nor a number
(which is always coercible to a string). (which is always coercible to a string).
</li> </li>
<li><b>"len": </b> <li><b><code>__len</code>: </b>
the <code>#</code> (length) operation. the length (<code>#</code>) operation.
If the object is not a string, If the object is not a string,
Lua will try its metamethod. Lua will try its metamethod.
If there is a metamethod, If there is a metamethod,
@ -566,44 +568,40 @@ then Lua uses the table length operation (see <a href="#3.4.7">&sect;3.4.7</a>).
Otherwise, Lua raises an error. Otherwise, Lua raises an error.
</li> </li>
<li><b>"eq": </b> <li><b><code>__eq</code>: </b>
the <code>==</code> (equal) operation. the equal (<code>==</code>) operation.
Behavior similar to the addition operation,
Behavior similar to the "add" operation,
except that Lua will try a metamethod only when the values except that Lua will try a metamethod only when the values
being compared are either both tables or both full userdata being compared are either both tables or both full userdata
and they are not primitively equal. and they are not primitively equal.
The result of the call is always converted to a boolean. The result of the call is always converted to a boolean.
</li> </li>
<li><b>"lt": </b> <li><b><code>__lt</code>: </b>
the <code>&lt;</code> (less than) operation. the less than (<code>&lt;</code>) operation.
Behavior similar to the addition operation,
Behavior similar to the "add" operation,
except that Lua will try a metamethod only when the values except that Lua will try a metamethod only when the values
being compared are neither both numbers nor both strings. being compared are neither both numbers nor both strings.
The result of the call is always converted to a boolean. The result of the call is always converted to a boolean.
</li> </li>
<li><b>"le": </b> <li><b><code>__le</code>: </b>
the <code>&lt;=</code> (less equal) operation. the less equal (<code>&lt;=</code>) operation.
Unlike other operations, Unlike other operations,
the less-equal operation can use two different events. the less-equal operation can use two different events.
First, Lua looks for the "<code>__le</code>" metamethod in both operands, First, Lua looks for the <code>__le</code> metamethod in both operands,
like in the "lt" operation. like in the less than operation.
If it cannot find such a metamethod, If it cannot find such a metamethod,
then it will try the "<code>__lt</code>" event, then it will try the <code>__lt</code> metamethod,
assuming that <code>a &lt;= b</code> is equivalent to <code>not (b &lt; a)</code>. assuming that <code>a &lt;= b</code> is equivalent to <code>not (b &lt; a)</code>.
As with the other comparison operators, As with the other comparison operators,
the result is always a boolean. the result is always a boolean.
(This use of the "<code>__lt</code>" event can be removed in future versions; (This use of the <code>__lt</code> event can be removed in future versions;
it is also slower than a real "<code>__le</code>" metamethod.) it is also slower than a real <code>__le</code> metamethod.)
</li> </li>
<li><b>"index": </b> <li><b><code>__index</code>: </b>
The indexing access <code>table[key]</code>. The indexing access <code>table[key]</code>.
This event happens when <code>table</code> is not a table or This event happens when <code>table</code> is not a table or
when <code>key</code> is not present in <code>table</code>. when <code>key</code> is not present in <code>table</code>.
The metamethod is looked up in <code>table</code>. The metamethod is looked up in <code>table</code>.
@ -613,16 +611,18 @@ The metamethod is looked up in <code>table</code>.
Despite the name, Despite the name,
the metamethod for this event can be either a function or a table. the metamethod for this event can be either a function or a table.
If it is a function, If it is a function,
it is called with <code>table</code> and <code>key</code> as arguments. it is called with <code>table</code> and <code>key</code> as arguments,
and the result of the call
(adjusted to one value)
is the result of the operation.
If it is a table, If it is a table,
the final result is the result of indexing this table with <code>key</code>. the final result is the result of indexing this table with <code>key</code>.
(This indexing is regular, not raw, (This indexing is regular, not raw,
and therefore can trigger another metamethod.) and therefore can trigger another metamethod.)
</li> </li>
<li><b>"newindex": </b> <li><b><code>__newindex</code>: </b>
The indexing assignment <code>table[key] = value</code>. The indexing assignment <code>table[key] = value</code>.
Like the index event, Like the index event,
this event happens when <code>table</code> is not a table or this event happens when <code>table</code> is not a table or
when <code>key</code> is not present in <code>table</code>. when <code>key</code> is not present in <code>table</code>.
@ -641,22 +641,24 @@ and therefore can trigger another metamethod.)
<p> <p>
Whenever there is a "newindex" metamethod, Whenever there is a <code>__newindex</code> metamethod,
Lua does not perform the primitive assignment. Lua does not perform the primitive assignment.
(If necessary, (If necessary,
the metamethod itself can call <a href="#pdf-rawset"><code>rawset</code></a> the metamethod itself can call <a href="#pdf-rawset"><code>rawset</code></a>
to do the assignment.) to do the assignment.)
</li> </li>
<li><b>"call": </b> <li><b><code>__call</code>: </b>
The call operation <code>func(args)</code>. The call operation <code>func(args)</code>.
This event happens when Lua tries to call a non-function value This event happens when Lua tries to call a non-function value
(that is, <code>func</code> is not a function). (that is, <code>func</code> is not a function).
The metamethod is looked up in <code>func</code>. The metamethod is looked up in <code>func</code>.
If present, If present,
the metamethod is called with <code>func</code> as its first argument, the metamethod is called with <code>func</code> as its first argument,
followed by the arguments of the original call (<code>args</code>). followed by the arguments of the original call (<code>args</code>).
All results of the call
are the result of the operation.
(This is the only metamethod that allows multiple results.)
</li> </li>
</ul> </ul>
@ -664,10 +666,19 @@ followed by the arguments of the original call (<code>args</code>).
<p> <p>
It is a good practice to add all needed metamethods to a table It is a good practice to add all needed metamethods to a table
before setting it as a metatable of some object. before setting it as a metatable of some object.
In particular, the "<code>__gc</code>" metamethod works only when this order In particular, the <code>__gc</code> metamethod works only when this order
is followed (see <a href="#2.5.1">&sect;2.5.1</a>). is followed (see <a href="#2.5.1">&sect;2.5.1</a>).
<p>
Because metatables are regular tables,
they can contain arbitrary fields,
not only the event names defined above.
Some functions in the standard library
(e.g., <a href="#pdf-tostring"><code>tostring</code></a>)
use other fields in metatables for their own purposes.
@ -935,7 +946,7 @@ In case of normal termination,
<a href="#pdf-coroutine.resume"><code>coroutine.resume</code></a> returns <b>true</b>, <a href="#pdf-coroutine.resume"><code>coroutine.resume</code></a> returns <b>true</b>,
plus any values returned by the coroutine main function. plus any values returned by the coroutine main function.
In case of errors, <a href="#pdf-coroutine.resume"><code>coroutine.resume</code></a> returns <b>false</b> In case of errors, <a href="#pdf-coroutine.resume"><code>coroutine.resume</code></a> returns <b>false</b>
plus an error message. plus an error object.
<p> <p>
@ -1168,7 +1179,7 @@ and the system file functions may have problems with
some control characters. some control characters.
So, it is safer to represent So, it is safer to represent
non-text data as a quoted literal with non-text data as a quoted literal with
explicit escape sequences for non-text characters. explicit escape sequences for the non-text characters.
<p> <p>
@ -1201,9 +1212,11 @@ which start with <code>0x</code> or <code>0X</code>.
Hexadecimal constants also accept an optional fractional part Hexadecimal constants also accept an optional fractional part
plus an optional binary exponent, plus an optional binary exponent,
marked by a letter '<code>p</code>' or '<code>P</code>'. marked by a letter '<code>p</code>' or '<code>P</code>'.
A numeric constant with a fractional dot or an exponent A numeric constant with a radix point or an exponent
denotes a float; denotes a float;
otherwise it denotes an integer. otherwise,
if its value fits in an integer,
it denotes an integer.
Examples of valid integer constants are Examples of valid integer constants are
<pre> <pre>
@ -1794,7 +1807,7 @@ bitwise operators (see <a href="#3.4.2">&sect;3.4.2</a>),
relational operators (see <a href="#3.4.4">&sect;3.4.4</a>), logical operators (see <a href="#3.4.5">&sect;3.4.5</a>), relational operators (see <a href="#3.4.4">&sect;3.4.4</a>), logical operators (see <a href="#3.4.5">&sect;3.4.5</a>),
and the concatenation operator (see <a href="#3.4.6">&sect;3.4.6</a>). and the concatenation operator (see <a href="#3.4.6">&sect;3.4.6</a>).
Unary operators comprise the unary minus (see <a href="#3.4.1">&sect;3.4.1</a>), Unary operators comprise the unary minus (see <a href="#3.4.1">&sect;3.4.1</a>),
the unary bitwise not (see <a href="#3.4.2">&sect;3.4.2</a>), the unary bitwise NOT (see <a href="#3.4.2">&sect;3.4.2</a>),
the unary logical <b>not</b> (see <a href="#3.4.5">&sect;3.4.5</a>), the unary logical <b>not</b> (see <a href="#3.4.5">&sect;3.4.5</a>),
and the unary <em>length operator</em> (see <a href="#3.4.7">&sect;3.4.7</a>). and the unary <em>length operator</em> (see <a href="#3.4.7">&sect;3.4.7</a>).
@ -1908,12 +1921,12 @@ that is equal modulo <em>2<sup>64</sup></em> to the mathematical result.)
Lua supports the following bitwise operators: Lua supports the following bitwise operators:
<ul> <ul>
<li><b><code>&amp;</code>: </b>bitwise and</li> <li><b><code>&amp;</code>: </b>bitwise AND</li>
<li><b><code>&#124;</code>: </b>bitwise or</li> <li><b><code>&#124;</code>: </b>bitwise OR</li>
<li><b><code>~</code>: </b>bitwise exclusive or</li> <li><b><code>~</code>: </b>bitwise exclusive OR</li>
<li><b><code>&gt;&gt;</code>: </b>right shift</li> <li><b><code>&gt;&gt;</code>: </b>right shift</li>
<li><b><code>&lt;&lt;</code>: </b>left shift</li> <li><b><code>&lt;&lt;</code>: </b>left shift</li>
<li><b><code>~</code>: </b>unary bitwise not</li> <li><b><code>~</code>: </b>unary bitwise NOT</li>
</ul> </ul>
<p> <p>
@ -1983,6 +1996,13 @@ is converted to the type (float or integer) required by the context
(e.g., the operation that forced the conversion). (e.g., the operation that forced the conversion).
<p>
All conversions from strings to numbers
accept both a dot and the current locale mark
as the radix character.
(The Lua lexer, however, accepts only a dot.)
<p> <p>
The conversion from numbers to strings uses a The conversion from numbers to strings uses a
non-specified human-readable format. non-specified human-readable format.
@ -2792,7 +2812,7 @@ never returning
<p> <p>
The panic function runs as if it were a message handler (see <a href="#2.3">&sect;2.3</a>); The panic function runs as if it were a message handler (see <a href="#2.3">&sect;2.3</a>);
in particular, the error message is at the top of the stack. in particular, the error object is at the top of the stack.
However, there is no guarantee about stack space. However, there is no guarantee about stack space.
To push anything on the stack, To push anything on the stack,
the panic function must first check the available space (see <a href="#4.2">&sect;4.2</a>). the panic function must first check the available space (see <a href="#4.2">&sect;4.2</a>).
@ -2974,8 +2994,11 @@ by looking only at its arguments
The third field, <code>x</code>, The third field, <code>x</code>,
tells whether the function may raise errors: tells whether the function may raise errors:
'<code>-</code>' means the function never raises any error; '<code>-</code>' means the function never raises any error;
'<code>m</code>' means the function may raise memory errors; '<code>m</code>' means the function may raise out-of-memory errors
'<code>e</code>' means the function may raise errors; and errors running a <code>__gc</code> metamethod;
'<code>e</code>' means the function may raise any errors
(it can run arbitrary Lua code,
either directly or through metamethods);
'<code>v</code>' means the function may raise an error on purpose. '<code>v</code>' means the function may raise an error on purpose.
@ -3102,10 +3125,10 @@ The value of <code>op</code> must be one of the following constants:
<li><b><a name="pdf-LUA_OPMOD"><code>LUA_OPMOD</code></a>: </b> performs modulo (<code>%</code>)</li> <li><b><a name="pdf-LUA_OPMOD"><code>LUA_OPMOD</code></a>: </b> performs modulo (<code>%</code>)</li>
<li><b><a name="pdf-LUA_OPPOW"><code>LUA_OPPOW</code></a>: </b> performs exponentiation (<code>^</code>)</li> <li><b><a name="pdf-LUA_OPPOW"><code>LUA_OPPOW</code></a>: </b> performs exponentiation (<code>^</code>)</li>
<li><b><a name="pdf-LUA_OPUNM"><code>LUA_OPUNM</code></a>: </b> performs mathematical negation (unary <code>-</code>)</li> <li><b><a name="pdf-LUA_OPUNM"><code>LUA_OPUNM</code></a>: </b> performs mathematical negation (unary <code>-</code>)</li>
<li><b><a name="pdf-LUA_OPBNOT"><code>LUA_OPBNOT</code></a>: </b> performs bitwise negation (<code>~</code>)</li> <li><b><a name="pdf-LUA_OPBNOT"><code>LUA_OPBNOT</code></a>: </b> performs bitwise NOT (<code>~</code>)</li>
<li><b><a name="pdf-LUA_OPBAND"><code>LUA_OPBAND</code></a>: </b> performs bitwise and (<code>&amp;</code>)</li> <li><b><a name="pdf-LUA_OPBAND"><code>LUA_OPBAND</code></a>: </b> performs bitwise AND (<code>&amp;</code>)</li>
<li><b><a name="pdf-LUA_OPBOR"><code>LUA_OPBOR</code></a>: </b> performs bitwise or (<code>|</code>)</li> <li><b><a name="pdf-LUA_OPBOR"><code>LUA_OPBOR</code></a>: </b> performs bitwise OR (<code>|</code>)</li>
<li><b><a name="pdf-LUA_OPBXOR"><code>LUA_OPBXOR</code></a>: </b> performs bitwise exclusive or (<code>~</code>)</li> <li><b><a name="pdf-LUA_OPBXOR"><code>LUA_OPBXOR</code></a>: </b> performs bitwise exclusive OR (<code>~</code>)</li>
<li><b><a name="pdf-LUA_OPSHL"><code>LUA_OPSHL</code></a>: </b> performs left shift (<code>&lt;&lt;</code>)</li> <li><b><a name="pdf-LUA_OPSHL"><code>LUA_OPSHL</code></a>: </b> performs left shift (<code>&lt;&lt;</code>)</li>
<li><b><a name="pdf-LUA_OPSHR"><code>LUA_OPSHR</code></a>: </b> performs right shift (<code>&gt;&gt;</code>)</li> <li><b><a name="pdf-LUA_OPSHR"><code>LUA_OPSHR</code></a>: </b> performs right shift (<code>&gt;&gt;</code>)</li>
@ -3424,7 +3447,7 @@ and therefore never returns
<hr><h3><a name="lua_gc"><code>lua_gc</code></a></h3><p> <hr><h3><a name="lua_gc"><code>lua_gc</code></a></h3><p>
<span class="apii">[-0, +0, <em>e</em>]</span> <span class="apii">[-0, +0, <em>m</em>]</span>
<pre>int lua_gc (lua_State *L, int what, int data);</pre> <pre>int lua_gc (lua_State *L, int what, int data);</pre>
<p> <p>
@ -3919,7 +3942,7 @@ The return values of <code>lua_load</code> are:
syntax error during precompilation;</li> syntax error during precompilation;</li>
<li><b><a href="#pdf-LUA_ERRMEM"><code>LUA_ERRMEM</code></a>: </b> <li><b><a href="#pdf-LUA_ERRMEM"><code>LUA_ERRMEM</code></a>: </b>
memory allocation error;</li> memory allocation (out-of-memory) error;</li>
<li><b><a href="#pdf-LUA_ERRGCMM"><code>LUA_ERRGCMM</code></a>: </b> <li><b><a href="#pdf-LUA_ERRGCMM"><code>LUA_ERRGCMM</code></a>: </b>
error while running a <code>__gc</code> metamethod. error while running a <code>__gc</code> metamethod.
@ -4128,7 +4151,7 @@ If there are no errors during the call,
<a href="#lua_pcall"><code>lua_pcall</code></a> behaves exactly like <a href="#lua_call"><code>lua_call</code></a>. <a href="#lua_pcall"><code>lua_pcall</code></a> behaves exactly like <a href="#lua_call"><code>lua_call</code></a>.
However, if there is any error, However, if there is any error,
<a href="#lua_pcall"><code>lua_pcall</code></a> catches it, <a href="#lua_pcall"><code>lua_pcall</code></a> catches it,
pushes a single value on the stack (the error message), pushes a single value on the stack (the error object),
and returns an error code. and returns an error code.
Like <a href="#lua_call"><code>lua_call</code></a>, Like <a href="#lua_call"><code>lua_call</code></a>,
<a href="#lua_pcall"><code>lua_pcall</code></a> always removes the function <a href="#lua_pcall"><code>lua_pcall</code></a> always removes the function
@ -4137,20 +4160,20 @@ and its arguments from the stack.
<p> <p>
If <code>msgh</code> is 0, If <code>msgh</code> is 0,
then the error message returned on the stack then the error object returned on the stack
is exactly the original error message. is exactly the original error object.
Otherwise, <code>msgh</code> is the stack index of a Otherwise, <code>msgh</code> is the stack index of a
<em>message handler</em>. <em>message handler</em>.
(This index cannot be a pseudo-index.) (This index cannot be a pseudo-index.)
In case of runtime errors, In case of runtime errors,
this function will be called with the error message this function will be called with the error object
and its return value will be the message and its return value will be the object
returned on the stack by <a href="#lua_pcall"><code>lua_pcall</code></a>. returned on the stack by <a href="#lua_pcall"><code>lua_pcall</code></a>.
<p> <p>
Typically, the message handler is used to add more debug Typically, the message handler is used to add more debug
information to the error message, such as a stack traceback. information to the error object, such as a stack traceback.
Such information cannot be gathered after the return of <a href="#lua_pcall"><code>lua_pcall</code></a>, Such information cannot be gathered after the return of <a href="#lua_pcall"><code>lua_pcall</code></a>,
since by then the stack has unwound. since by then the stack has unwound.
@ -4284,7 +4307,7 @@ and return its results (see <a href="#lua_CFunction"><code>lua_CFunction</code><
<hr><h3><a name="lua_pushfstring"><code>lua_pushfstring</code></a></h3><p> <hr><h3><a name="lua_pushfstring"><code>lua_pushfstring</code></a></h3><p>
<span class="apii">[-0, +1, <em>m</em>]</span> <span class="apii">[-0, +1, <em>e</em>]</span>
<pre>const char *lua_pushfstring (lua_State *L, const char *fmt, ...);</pre> <pre>const char *lua_pushfstring (lua_State *L, const char *fmt, ...);</pre>
<p> <p>
@ -4317,6 +4340,12 @@ The conversion specifiers can only be
</ul> </ul>
<p>
Unlike other push functions,
this function checks for the stack space it needs,
including the slot for its result.
@ -4486,7 +4515,7 @@ instead of a variable number of arguments.
<p> <p>
Returns 1 if the two values in indices <code>index1</code> and Returns 1 if the two values in indices <code>index1</code> and
<code>index2</code> are primitively equal <code>index2</code> are primitively equal
(that is, without calling metamethods). (that is, without calling the <code>__eq</code> metamethod).
Otherwise returns&nbsp;0. Otherwise returns&nbsp;0.
Also returns&nbsp;0 if any of the indices are not valid. Also returns&nbsp;0 if any of the indices are not valid.
@ -4513,8 +4542,8 @@ Similar to <a href="#lua_gettable"><code>lua_gettable</code></a>, but does a raw
<p> <p>
Pushes onto the stack the value <code>t[n]</code>, Pushes onto the stack the value <code>t[n]</code>,
where <code>t</code> is the table at the given index. where <code>t</code> is the table at the given index.
The access is raw; The access is raw,
that is, it does not invoke metamethods. that is, it does not invoke the <code>__index</code> metamethod.
<p> <p>
@ -4533,7 +4562,7 @@ Pushes onto the stack the value <code>t[k]</code>,
where <code>t</code> is the table at the given index and where <code>t</code> is the table at the given index and
<code>k</code> is the pointer <code>p</code> represented as a light userdata. <code>k</code> is the pointer <code>p</code> represented as a light userdata.
The access is raw; The access is raw;
that is, it does not invoke metamethods. that is, it does not invoke the <code>__index</code> metamethod.
<p> <p>
@ -4584,8 +4613,8 @@ and <code>v</code> is the value at the top of the stack.
<p> <p>
This function pops the value from the stack. This function pops the value from the stack.
The assignment is raw; The assignment is raw,
that is, it does not invoke metamethods. that is, it does not invoke the <code>__newindex</code> metamethod.
@ -4604,8 +4633,8 @@ and <code>v</code> is the value at the top of the stack.
<p> <p>
This function pops the value from the stack. This function pops the value from the stack.
The assignment is raw; The assignment is raw,
that is, it does not invoke metamethods. that is, it does not invoke <code>__newindex</code> metamethod.
@ -4704,7 +4733,7 @@ or an error code in case of errors (see <a href="#lua_pcall"><code>lua_pcall</co
In case of errors, In case of errors,
the stack is not unwound, the stack is not unwound,
so you can use the debug API over it. so you can use the debug API over it.
The error message is on the top of the stack. The error object is on the top of the stack.
<p> <p>
@ -5179,11 +5208,13 @@ the running function (see <a href="#4.4">&sect;4.4</a>).
<hr><h3><a name="lua_version"><code>lua_version</code></a></h3><p> <hr><h3><a name="lua_version"><code>lua_version</code></a></h3><p>
<span class="apii">[-0, +0, <em>v</em>]</span> <span class="apii">[-0, +0, &ndash;]</span>
<pre>const lua_Number *lua_version (lua_State *L);</pre> <pre>const lua_Number *lua_version (lua_State *L);</pre>
<p> <p>
Returns the address of the version number stored in the Lua core. Returns the address of the version number
(a C static variable)
stored in the Lua core.
When called with a valid <a href="#lua_State"><code>lua_State</code></a>, When called with a valid <a href="#lua_State"><code>lua_State</code></a>,
returns the address of the version used to create that state. returns the address of the version used to create that state.
When called with <code>NULL</code>, When called with <code>NULL</code>,
@ -5287,9 +5318,9 @@ when the coroutine eventually resumes,
it continues executing the continuation function. it continues executing the continuation function.
However, there is one special case, However, there is one special case,
which is when this function is called which is when this function is called
from inside a line hook (see <a href="#4.9">&sect;4.9</a>). from inside a line or a count hook (see <a href="#4.9">&sect;4.9</a>).
In that case, <code>lua_yieldk</code> should be called with no continuation In that case, <code>lua_yieldk</code> should be called with no continuation
(probably in the form of <a href="#lua_yield"><code>lua_yield</code></a>), (probably in the form of <a href="#lua_yield"><code>lua_yield</code></a>) and no results,
and the hook should return immediately after the call. and the hook should return immediately after the call.
Lua will yield and, Lua will yield and,
when the coroutine resumes again, when the coroutine resumes again,
@ -5704,7 +5735,7 @@ Sets the debugging hook function.
<p> <p>
Argument <code>f</code> is the hook function. Argument <code>f</code> is the hook function.
<code>mask</code> specifies on which events the hook will be called: <code>mask</code> specifies on which events the hook will be called:
it is formed by a bitwise or of the constants it is formed by a bitwise OR of the constants
<a name="pdf-LUA_MASKCALL"><code>LUA_MASKCALL</code></a>, <a name="pdf-LUA_MASKCALL"><code>LUA_MASKCALL</code></a>,
<a name="pdf-LUA_MASKRET"><code>LUA_MASKRET</code></a>, <a name="pdf-LUA_MASKRET"><code>LUA_MASKRET</code></a>,
<a name="pdf-LUA_MASKLINE"><code>LUA_MASKLINE</code></a>, <a name="pdf-LUA_MASKLINE"><code>LUA_MASKLINE</code></a>,
@ -6256,7 +6287,7 @@ returns the userdata address (see <a href="#lua_touserdata"><code>lua_touserdata
<hr><h3><a name="luaL_checkversion"><code>luaL_checkversion</code></a></h3><p> <hr><h3><a name="luaL_checkversion"><code>luaL_checkversion</code></a></h3><p>
<span class="apii">[-0, +0, &ndash;]</span> <span class="apii">[-0, +0, <em>v</em>]</span>
<pre>void luaL_checkversion (lua_State *L);</pre> <pre>void luaL_checkversion (lua_State *L);</pre>
<p> <p>
@ -6472,7 +6503,7 @@ The string <code>mode</code> works as in function <a href="#lua_load"><code>lua_
<hr><h3><a name="luaL_loadfile"><code>luaL_loadfile</code></a></h3><p> <hr><h3><a name="luaL_loadfile"><code>luaL_loadfile</code></a></h3><p>
<span class="apii">[-0, +1, <em>e</em>]</span> <span class="apii">[-0, +1, <em>m</em>]</span>
<pre>int luaL_loadfile (lua_State *L, const char *filename);</pre> <pre>int luaL_loadfile (lua_State *L, const char *filename);</pre>
<p> <p>
@ -6483,7 +6514,7 @@ Equivalent to <a href="#luaL_loadfilex"><code>luaL_loadfilex</code></a> with <co
<hr><h3><a name="luaL_loadfilex"><code>luaL_loadfilex</code></a></h3><p> <hr><h3><a name="luaL_loadfilex"><code>luaL_loadfilex</code></a></h3><p>
<span class="apii">[-0, +1, <em>e</em>]</span> <span class="apii">[-0, +1, <em>m</em>]</span>
<pre>int luaL_loadfilex (lua_State *L, const char *filename, <pre>int luaL_loadfilex (lua_State *L, const char *filename,
const char *mode);</pre> const char *mode);</pre>
@ -6634,6 +6665,27 @@ Opens all standard Lua libraries into the given state.
<hr><h3><a name="luaL_opt"><code>luaL_opt</code></a></h3><p>
<span class="apii">[-0, +0, <em>e</em>]</span>
<pre>T luaL_opt (L, func, arg, dflt);</pre>
<p>
This macro is defined as follows:
<pre>
(lua_isnoneornil(L,(arg)) ? (dflt) : func(L,(arg)))
</pre><p>
In words, if the argument <code>arg</code> is nil or absent,
the macro results in the default <code>dflt</code>.
Otherwise, it results in the result of calling <code>func</code>
with the state <code>L</code> and the argument index <code>arg</code> as
parameters.
Note that it evaluates the expression <code>dflt</code> only if needed.
<hr><h3><a name="luaL_optinteger"><code>luaL_optinteger</code></a></h3><p> <hr><h3><a name="luaL_optinteger"><code>luaL_optinteger</code></a></h3><p>
<span class="apii">[-0, +0, <em>v</em>]</span> <span class="apii">[-0, +0, <em>v</em>]</span>
<pre>lua_Integer luaL_optinteger (lua_State *L, <pre>lua_Integer luaL_optinteger (lua_State *L,
@ -6931,7 +6983,7 @@ the function also sets <code>*len</code> with the string length.
<p> <p>
If the value has a metatable with a <code>"__tostring"</code> field, If the value has a metatable with a <code>__tostring</code> field,
then <code>luaL_tolstring</code> calls the corresponding metamethod then <code>luaL_tolstring</code> calls the corresponding metamethod
with the value as argument, with the value as argument,
and uses the result of the call as its result. and uses the result of the call as its result.
@ -7220,7 +7272,7 @@ nor vice versa.
<p> <p>
If <code>object</code> does not have a metatable, returns <b>nil</b>. If <code>object</code> does not have a metatable, returns <b>nil</b>.
Otherwise, Otherwise,
if the object's metatable has a <code>"__metatable"</code> field, if the object's metatable has a <code>__metatable</code> field,
returns the associated value. returns the associated value.
Otherwise, returns the metatable of the given object. Otherwise, returns the metatable of the given object.
@ -7424,7 +7476,7 @@ use <a href="#pdf-string.format"><code>string.format</code></a> and <a href="#pd
<p> <p>
<hr><h3><a name="pdf-rawequal"><code>rawequal (v1, v2)</code></a></h3> <hr><h3><a name="pdf-rawequal"><code>rawequal (v1, v2)</code></a></h3>
Checks whether <code>v1</code> is equal to <code>v2</code>, Checks whether <code>v1</code> is equal to <code>v2</code>,
without invoking any metamethod. without invoking the <code>__eq</code> metamethod.
Returns a boolean. Returns a boolean.
@ -7433,7 +7485,7 @@ Returns a boolean.
<p> <p>
<hr><h3><a name="pdf-rawget"><code>rawget (table, index)</code></a></h3> <hr><h3><a name="pdf-rawget"><code>rawget (table, index)</code></a></h3>
Gets the real value of <code>table[index]</code>, Gets the real value of <code>table[index]</code>,
without invoking any metamethod. without invoking the <code>__index</code> metamethod.
<code>table</code> must be a table; <code>table</code> must be a table;
<code>index</code> may be any value. <code>index</code> may be any value.
@ -7444,7 +7496,7 @@ without invoking any metamethod.
<hr><h3><a name="pdf-rawlen"><code>rawlen (v)</code></a></h3> <hr><h3><a name="pdf-rawlen"><code>rawlen (v)</code></a></h3>
Returns the length of the object <code>v</code>, Returns the length of the object <code>v</code>,
which must be a table or a string, which must be a table or a string,
without invoking any metamethod. without invoking the <code>__len</code> metamethod.
Returns an integer. Returns an integer.
@ -7453,7 +7505,7 @@ Returns an integer.
<p> <p>
<hr><h3><a name="pdf-rawset"><code>rawset (table, index, value)</code></a></h3> <hr><h3><a name="pdf-rawset"><code>rawset (table, index, value)</code></a></h3>
Sets the real value of <code>table[index]</code> to <code>value</code>, Sets the real value of <code>table[index]</code> to <code>value</code>,
without invoking any metamethod. without invoking the <code>__newindex</code> metamethod.
<code>table</code> must be a table, <code>table</code> must be a table,
<code>index</code> any value different from <b>nil</b> and NaN, <code>index</code> any value different from <b>nil</b> and NaN,
and <code>value</code> any Lua value. and <code>value</code> any Lua value.
@ -7489,7 +7541,7 @@ Sets the metatable for the given table.
you must use the debug library (<a href="#6.10">&sect;6.10</a>).) you must use the debug library (<a href="#6.10">&sect;6.10</a>).)
If <code>metatable</code> is <b>nil</b>, If <code>metatable</code> is <b>nil</b>,
removes the metatable of the given table. removes the metatable of the given table.
If the original metatable has a <code>"__metatable"</code> field, If the original metatable has a <code>__metatable</code> field,
raises an error. raises an error.
@ -7541,7 +7593,7 @@ use <a href="#pdf-string.format"><code>string.format</code></a>.)
<p> <p>
If the metatable of <code>v</code> has a <code>"__tostring"</code> field, If the metatable of <code>v</code> has a <code>__tostring</code> field,
then <code>tostring</code> calls the corresponding value then <code>tostring</code> calls the corresponding value
with <code>v</code> as argument, with <code>v</code> as argument,
and uses the result of the call as its result. and uses the result of the call as its result.
@ -8184,6 +8236,9 @@ The only differences are that the options/modifiers
<code>*</code>, <code>h</code>, <code>L</code>, <code>l</code>, <code>n</code>, <code>*</code>, <code>h</code>, <code>L</code>, <code>l</code>, <code>n</code>,
and <code>p</code> are not supported and <code>p</code> are not supported
and that there is an extra option, <code>q</code>. and that there is an extra option, <code>q</code>.
<p>
The <code>q</code> option formats a string between double quotes, The <code>q</code> option formats a string between double quotes,
using escape sequences when necessary to ensure that using escape sequences when necessary to ensure that
it can safely be read back by the Lua interpreter. it can safely be read back by the Lua interpreter.
@ -8206,7 +8261,12 @@ Options
Options <code>c</code>, <code>d</code>, Options <code>c</code>, <code>d</code>,
<code>i</code>, <code>o</code>, <code>u</code>, <code>X</code>, and <code>x</code> <code>i</code>, <code>o</code>, <code>u</code>, <code>X</code>, and <code>x</code>
expect an integer. expect an integer.
Option <code>q</code> expects a string. When Lua is compiled with a C89 compiler,
options <code>A</code> and <code>a</code> (hexadecimal floats)
do not support any modifier (flags, width, length).
<p>
Option <code>s</code> expects a string; Option <code>s</code> expects a string;
if its argument is not a string, if its argument is not a string,
it is converted to one following the same rules of <a href="#pdf-tostring"><code>tostring</code></a>. it is converted to one following the same rules of <a href="#pdf-tostring"><code>tostring</code></a>.
@ -8214,12 +8274,6 @@ If the option has any modifier (flags, width, length),
the string argument should not contain embedded zeros. the string argument should not contain embedded zeros.
<p>
When Lua is compiled with a non-C99 compiler,
options <code>A</code> and <code>a</code> (hexadecimal floats)
do not support any modifier (flags, width, length).
<p> <p>
@ -8547,6 +8601,14 @@ and <code>[0-7%l%-]</code> represents the octal digits plus
the lowercase letters plus the '<code>-</code>' character. the lowercase letters plus the '<code>-</code>' character.
<p>
You can put a closing square bracket in a set
by positioning it as the first character in the set.
You can put an hyphen in a set
by positioning it as the first or the last character in the set.
(You can also use an escape for both cases.)
<p> <p>
The interaction between ranges and classes is not defined. The interaction between ranges and classes is not defined.
Therefore, patterns like <code>[%a-z]</code> or <code>[a-%%]</code> Therefore, patterns like <code>[%a-z]</code> or <code>[a-%%]</code>
@ -8925,8 +8987,8 @@ of list <code>t</code>.
<p> <p>
Moves elements from table <code>a1</code> to table <code>a2</code>. Moves elements from table <code>a1</code> to table <code>a2</code>,
This function performs the equivalent to the following performing the equivalent to the following
multiple assignment: multiple assignment:
<code>a2[t],&middot;&middot;&middot; = a1[f],&middot;&middot;&middot;,a1[e]</code>. <code>a2[t],&middot;&middot;&middot; = a1[f],&middot;&middot;&middot;,a1[e]</code>.
The default for <code>a2</code> is <code>a1</code>. The default for <code>a2</code> is <code>a1</code>.
@ -8934,6 +8996,10 @@ The destination range can overlap with the source range.
The number of elements to be moved must fit in a Lua integer. The number of elements to be moved must fit in a Lua integer.
<p>
Returns the destination table <code>a2</code>.
<p> <p>
@ -9457,8 +9523,8 @@ instead of returning an error code.
<p> <p>
This function opens a file, This function opens a file,
in the mode specified in the string <code>mode</code>. in the mode specified in the string <code>mode</code>.
It returns a new file handle, In case of success,
or, in case of errors, <b>nil</b> plus an error message. it returns a new file handle.
<p> <p>
@ -9523,7 +9589,8 @@ Equivalent to <code>io.input():read(&middot;&middot;&middot;)</code>.
<p> <p>
Returns a handle for a temporary file. In case of success,
returns a handle for a temporary file.
This file is opened in update mode This file is opened in update mode
and it is automatically removed when the program ends. and it is automatically removed when the program ends.
@ -9801,8 +9868,8 @@ if <code>format</code> is the string "<code>*t</code>",
then <code>date</code> returns a table with the following fields: then <code>date</code> returns a table with the following fields:
<code>year</code>, <code>month</code> (1&ndash;12), <code>day</code> (1&ndash;31), <code>year</code>, <code>month</code> (1&ndash;12), <code>day</code> (1&ndash;31),
<code>hour</code> (0&ndash;23), <code>min</code> (0&ndash;59), <code>sec</code> (0&ndash;61), <code>hour</code> (0&ndash;23), <code>min</code> (0&ndash;59), <code>sec</code> (0&ndash;61),
<code>wday</code> (weekday, Sunday is&nbsp;1), <code>wday</code> (weekday, 1&ndash;7, Sunday is&nbsp;1),
<code>yday</code> (day of the year), <code>yday</code> (day of the year, 1&ndash;366),
and <code>isdst</code> (daylight saving flag, a boolean). and <code>isdst</code> (daylight saving flag, a boolean).
This last field may be absent This last field may be absent
if the information is not available. if the information is not available.
@ -10504,6 +10571,14 @@ the interpreter waits for its completion
by issuing a different prompt. by issuing a different prompt.
<p>
If the global variable <a name="pdf-_PROMPT"><code>_PROMPT</code></a> contains a string,
then its value is used as the prompt.
Similarly, if the global variable <a name="pdf-_PROMPT2"><code>_PROMPT2</code></a> contains a string,
its value is used as the secondary prompt
(issued during incomplete statements).
<p> <p>
In case of unprotected errors in the script, In case of unprotected errors in the script,
the interpreter reports the error to the standard error stream. the interpreter reports the error to the standard error stream.
@ -10825,10 +10900,10 @@ and LiteralString, see <a href="#3.1">&sect;3.1</a>.)
<P CLASS="footer"> <P CLASS="footer">
Last update: Last update:
Wed Nov 25 15:19:10 BRST 2015 Mon May 30 13:11:08 BRT 2016
</P> </P>
<!-- <!--
Last change: revised for Lua 5.3.2 Last change: revised for Lua 5.3.3
--> -->
</body></html> </body></html>

View File

@ -276,7 +276,7 @@ Here are the other changes introduced in Lua 5.3:
<H3>Language</H3> <H3>Language</H3>
<UL> <UL>
<LI> userdata can have any Lua value as uservalue <LI> userdata can have any Lua value as uservalue
<LI> integer division <LI> floor division
<LI> more flexible rules for some metamethods <LI> more flexible rules for some metamethods
</UL> </UL>
@ -328,7 +328,7 @@ For details, see
<A HREF="http://www.lua.org/license.html">this</A>. <A HREF="http://www.lua.org/license.html">this</A>.
<BLOCKQUOTE STYLE="padding-bottom: 0em"> <BLOCKQUOTE STYLE="padding-bottom: 0em">
Copyright &copy; 1994&ndash;2015 Lua.org, PUC-Rio. Copyright &copy; 1994&ndash;2016 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
@ -355,10 +355,10 @@ THE SOFTWARE.
<P CLASS="footer"> <P CLASS="footer">
Last update: Last update:
Mon Jun 1 21:48:24 BRT 2015 Tue Feb 2 22:25:27 BRST 2016
</P> </P>
<!-- <!--
Last change: revised for Lua 5.3.1 Last change: revised for Lua 5.3.3
--> -->
</BODY> </BODY>

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lapi.c,v 2.257 2015/11/02 18:48:07 roberto Exp $ ** $Id: lapi.c,v 2.259 2016/02/29 14:27:14 roberto Exp $
** Lua API ** Lua API
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -378,9 +378,9 @@ LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) {
return NULL; return NULL;
} }
lua_lock(L); /* 'luaO_tostring' may create a new string */ lua_lock(L); /* 'luaO_tostring' may create a new string */
luaO_tostring(L, o);
luaC_checkGC(L); luaC_checkGC(L);
o = index2addr(L, idx); /* previous call may reallocate the stack */ o = index2addr(L, idx); /* previous call may reallocate the stack */
luaO_tostring(L, o);
lua_unlock(L); lua_unlock(L);
} }
if (len != NULL) if (len != NULL)
@ -479,10 +479,10 @@ LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) {
LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) { LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) {
TString *ts; TString *ts;
lua_lock(L); lua_lock(L);
luaC_checkGC(L);
ts = (len == 0) ? luaS_new(L, "") : luaS_newlstr(L, s, len); ts = (len == 0) ? luaS_new(L, "") : luaS_newlstr(L, s, len);
setsvalue2s(L, L->top, ts); setsvalue2s(L, L->top, ts);
api_incr_top(L); api_incr_top(L);
luaC_checkGC(L);
lua_unlock(L); lua_unlock(L);
return getstr(ts); return getstr(ts);
} }
@ -494,12 +494,12 @@ LUA_API const char *lua_pushstring (lua_State *L, const char *s) {
setnilvalue(L->top); setnilvalue(L->top);
else { else {
TString *ts; TString *ts;
luaC_checkGC(L);
ts = luaS_new(L, s); ts = luaS_new(L, s);
setsvalue2s(L, L->top, ts); setsvalue2s(L, L->top, ts);
s = getstr(ts); /* internal copy's address */ s = getstr(ts); /* internal copy's address */
} }
api_incr_top(L); api_incr_top(L);
luaC_checkGC(L);
lua_unlock(L); lua_unlock(L);
return s; return s;
} }
@ -509,8 +509,8 @@ LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt,
va_list argp) { va_list argp) {
const char *ret; const char *ret;
lua_lock(L); lua_lock(L);
luaC_checkGC(L);
ret = luaO_pushvfstring(L, fmt, argp); ret = luaO_pushvfstring(L, fmt, argp);
luaC_checkGC(L);
lua_unlock(L); lua_unlock(L);
return ret; return ret;
} }
@ -520,10 +520,10 @@ LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) {
const char *ret; const char *ret;
va_list argp; va_list argp;
lua_lock(L); lua_lock(L);
luaC_checkGC(L);
va_start(argp, fmt); va_start(argp, fmt);
ret = luaO_pushvfstring(L, fmt, argp); ret = luaO_pushvfstring(L, fmt, argp);
va_end(argp); va_end(argp);
luaC_checkGC(L);
lua_unlock(L); lua_unlock(L);
return ret; return ret;
} }
@ -538,7 +538,6 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
CClosure *cl; CClosure *cl;
api_checknelems(L, n); api_checknelems(L, n);
api_check(L, n <= MAXUPVAL, "upvalue index too large"); api_check(L, n <= MAXUPVAL, "upvalue index too large");
luaC_checkGC(L);
cl = luaF_newCclosure(L, n); cl = luaF_newCclosure(L, n);
cl->f = fn; cl->f = fn;
L->top -= n; L->top -= n;
@ -549,6 +548,7 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
setclCvalue(L, L->top, cl); setclCvalue(L, L->top, cl);
} }
api_incr_top(L); api_incr_top(L);
luaC_checkGC(L);
lua_unlock(L); lua_unlock(L);
} }
@ -585,16 +585,16 @@ LUA_API int lua_pushthread (lua_State *L) {
static int auxgetstr (lua_State *L, const TValue *t, const char *k) { static int auxgetstr (lua_State *L, const TValue *t, const char *k) {
const TValue *aux; const TValue *slot;
TString *str = luaS_new(L, k); TString *str = luaS_new(L, k);
if (luaV_fastget(L, t, str, aux, luaH_getstr)) { if (luaV_fastget(L, t, str, slot, luaH_getstr)) {
setobj2s(L, L->top, aux); setobj2s(L, L->top, slot);
api_incr_top(L); api_incr_top(L);
} }
else { else {
setsvalue2s(L, L->top, str); setsvalue2s(L, L->top, str);
api_incr_top(L); api_incr_top(L);
luaV_finishget(L, t, L->top - 1, L->top - 1, aux); luaV_finishget(L, t, L->top - 1, L->top - 1, slot);
} }
lua_unlock(L); lua_unlock(L);
return ttnov(L->top - 1); return ttnov(L->top - 1);
@ -626,17 +626,17 @@ LUA_API int lua_getfield (lua_State *L, int idx, const char *k) {
LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) { LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) {
StkId t; StkId t;
const TValue *aux; const TValue *slot;
lua_lock(L); lua_lock(L);
t = index2addr(L, idx); t = index2addr(L, idx);
if (luaV_fastget(L, t, n, aux, luaH_getint)) { if (luaV_fastget(L, t, n, slot, luaH_getint)) {
setobj2s(L, L->top, aux); setobj2s(L, L->top, slot);
api_incr_top(L); api_incr_top(L);
} }
else { else {
setivalue(L->top, n); setivalue(L->top, n);
api_incr_top(L); api_incr_top(L);
luaV_finishget(L, t, L->top - 1, L->top - 1, aux); luaV_finishget(L, t, L->top - 1, L->top - 1, slot);
} }
lua_unlock(L); lua_unlock(L);
return ttnov(L->top - 1); return ttnov(L->top - 1);
@ -683,12 +683,12 @@ LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) {
LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { LUA_API void lua_createtable (lua_State *L, int narray, int nrec) {
Table *t; Table *t;
lua_lock(L); lua_lock(L);
luaC_checkGC(L);
t = luaH_new(L); t = luaH_new(L);
sethvalue(L, L->top, t); sethvalue(L, L->top, t);
api_incr_top(L); api_incr_top(L);
if (narray > 0 || nrec > 0) if (narray > 0 || nrec > 0)
luaH_resize(L, t, narray, nrec); luaH_resize(L, t, narray, nrec);
luaC_checkGC(L);
lua_unlock(L); lua_unlock(L);
} }
@ -740,15 +740,15 @@ LUA_API int lua_getuservalue (lua_State *L, int idx) {
** t[k] = value at the top of the stack (where 'k' is a string) ** t[k] = value at the top of the stack (where 'k' is a string)
*/ */
static void auxsetstr (lua_State *L, const TValue *t, const char *k) { static void auxsetstr (lua_State *L, const TValue *t, const char *k) {
const TValue *aux; const TValue *slot;
TString *str = luaS_new(L, k); TString *str = luaS_new(L, k);
api_checknelems(L, 1); api_checknelems(L, 1);
if (luaV_fastset(L, t, str, aux, luaH_getstr, L->top - 1)) if (luaV_fastset(L, t, str, slot, luaH_getstr, L->top - 1))
L->top--; /* pop value */ L->top--; /* pop value */
else { else {
setsvalue2s(L, L->top, str); /* push 'str' (to make it a TValue) */ setsvalue2s(L, L->top, str); /* push 'str' (to make it a TValue) */
api_incr_top(L); api_incr_top(L);
luaV_finishset(L, t, L->top - 1, L->top - 2, aux); luaV_finishset(L, t, L->top - 1, L->top - 2, slot);
L->top -= 2; /* pop value and key */ L->top -= 2; /* pop value and key */
} }
lua_unlock(L); /* lock done by caller */ lua_unlock(L); /* lock done by caller */
@ -781,16 +781,16 @@ LUA_API void lua_setfield (lua_State *L, int idx, const char *k) {
LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) { LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) {
StkId t; StkId t;
const TValue *aux; const TValue *slot;
lua_lock(L); lua_lock(L);
api_checknelems(L, 1); api_checknelems(L, 1);
t = index2addr(L, idx); t = index2addr(L, idx);
if (luaV_fastset(L, t, n, aux, luaH_getint, L->top - 1)) if (luaV_fastset(L, t, n, slot, luaH_getint, L->top - 1))
L->top--; /* pop value */ L->top--; /* pop value */
else { else {
setivalue(L->top, n); setivalue(L->top, n);
api_incr_top(L); api_incr_top(L);
luaV_finishset(L, t, L->top - 1, L->top - 2, aux); luaV_finishset(L, t, L->top - 1, L->top - 2, slot);
L->top -= 2; /* pop value and key */ L->top -= 2; /* pop value and key */
} }
lua_unlock(L); lua_unlock(L);
@ -1140,7 +1140,6 @@ LUA_API void lua_concat (lua_State *L, int n) {
lua_lock(L); lua_lock(L);
api_checknelems(L, n); api_checknelems(L, n);
if (n >= 2) { if (n >= 2) {
luaC_checkGC(L);
luaV_concat(L, n); luaV_concat(L, n);
} }
else if (n == 0) { /* push empty string */ else if (n == 0) { /* push empty string */
@ -1148,6 +1147,7 @@ LUA_API void lua_concat (lua_State *L, int n) {
api_incr_top(L); api_incr_top(L);
} }
/* else n == 1; nothing to do */ /* else n == 1; nothing to do */
luaC_checkGC(L);
lua_unlock(L); lua_unlock(L);
} }
@ -1183,10 +1183,10 @@ LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) {
LUA_API void *lua_newuserdata (lua_State *L, size_t size) { LUA_API void *lua_newuserdata (lua_State *L, size_t size) {
Udata *u; Udata *u;
lua_lock(L); lua_lock(L);
luaC_checkGC(L);
u = luaS_newudata(L, size); u = luaS_newudata(L, size);
setuvalue(L, L->top, u); setuvalue(L, L->top, u);
api_incr_top(L); api_incr_top(L);
luaC_checkGC(L);
lua_unlock(L); lua_unlock(L);
return getudatamem(u); return getudatamem(u);
} }

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lauxlib.c,v 1.284 2015/11/19 19:16:22 roberto Exp $ ** $Id: lauxlib.c,v 1.286 2016/01/08 15:33:09 roberto Exp $
** Auxiliary functions for building Lua libraries ** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -17,7 +17,8 @@
#include <string.h> #include <string.h>
/* This file uses only the official API of Lua. /*
** This file uses only the official API of Lua.
** Any function declared here could be written as an application function. ** Any function declared here could be written as an application function.
*/ */
@ -198,6 +199,10 @@ static void tag_error (lua_State *L, int arg, int tag) {
} }
/*
** The use of 'lua_pushfstring' ensures this function does not
** need reserved stack space when called.
*/
LUALIB_API void luaL_where (lua_State *L, int level) { LUALIB_API void luaL_where (lua_State *L, int level) {
lua_Debug ar; lua_Debug ar;
if (lua_getstack(L, level, &ar)) { /* check function at level */ if (lua_getstack(L, level, &ar)) { /* check function at level */
@ -207,10 +212,15 @@ LUALIB_API void luaL_where (lua_State *L, int level) {
return; return;
} }
} }
lua_pushliteral(L, ""); /* else, no information available... */ lua_pushfstring(L, ""); /* else, no information available... */
} }
/*
** Again, the use of 'lua_pushvfstring' ensures this function does
** not need reserved stack space when called. (At worst, it generates
** an error with "stack overflow" instead of the given message.)
*/
LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) {
va_list argp; va_list argp;
va_start(argp, fmt); va_start(argp, fmt);
@ -349,10 +359,15 @@ LUALIB_API int luaL_checkoption (lua_State *L, int arg, const char *def,
} }
/*
** Ensures the stack has at least 'space' extra slots, raising an error
** if it cannot fulfill the request. (The error handling needs a few
** extra slots to format the error message. In case of an error without
** this extra space, Lua will generate the same 'stack overflow' error,
** but without 'msg'.)
*/
LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg) { LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg) {
/* keep some extra space to run error routines, if needed */ if (!lua_checkstack(L, space)) {
const int extra = LUA_MINSTACK;
if (!lua_checkstack(L, space + extra)) {
if (msg) if (msg)
luaL_error(L, "stack overflow (%s)", msg); luaL_error(L, "stack overflow (%s)", msg);
else else
@ -678,7 +693,7 @@ static int skipcomment (LoadF *lf, int *cp) {
if (c == '#') { /* first line is a comment (Unix exec. file)? */ if (c == '#') { /* first line is a comment (Unix exec. file)? */
do { /* skip first line */ do { /* skip first line */
c = getc(lf->f); c = getc(lf->f);
} while (c != EOF && c != '\n') ; } while (c != EOF && c != '\n');
*cp = getc(lf->f); /* skip end-of-line, if present */ *cp = getc(lf->f); /* skip end-of-line, if present */
return 1; /* there was a comment */ return 1; /* there was a comment */
} }

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lbaselib.c,v 1.312 2015/10/29 15:21:04 roberto Exp $ ** $Id: lbaselib.c,v 1.313 2016/04/11 19:18:40 roberto Exp $
** Basic library ** Basic library
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -102,8 +102,8 @@ static int luaB_tonumber (lua_State *L) {
static int luaB_error (lua_State *L) { static int luaB_error (lua_State *L) {
int level = (int)luaL_optinteger(L, 2, 1); int level = (int)luaL_optinteger(L, 2, 1);
lua_settop(L, 1); lua_settop(L, 1);
if (lua_isstring(L, 1) && level > 0) { /* add extra information? */ if (lua_type(L, 1) == LUA_TSTRING && level > 0) {
luaL_where(L, level); luaL_where(L, level); /* add extra information */
lua_pushvalue(L, 1); lua_pushvalue(L, 1);
lua_concat(L, 2); lua_concat(L, 2);
} }
@ -251,9 +251,8 @@ static int ipairsaux (lua_State *L) {
/* /*
** This function will use either 'ipairsaux' or 'ipairsaux_raw' to ** 'ipairs' function. Returns 'ipairsaux', given "table", 0.
** traverse a table, depending on whether the table has metamethods ** (The given "table" may not be a table.)
** that can affect the traversal.
*/ */
static int luaB_ipairs (lua_State *L) { static int luaB_ipairs (lua_State *L) {
#if defined(LUA_COMPAT_IPAIRS) #if defined(LUA_COMPAT_IPAIRS)

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lcode.h,v 1.63 2013/12/30 20:47:58 roberto Exp $ ** $Id: lcode.h,v 1.64 2016/01/05 16:22:37 roberto Exp $
** Code generator for Lua ** Code generator for Lua
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -40,7 +40,8 @@ typedef enum BinOpr {
typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;
#define getcode(fs,e) ((fs)->f->code[(e)->u.info]) /* get (pointer to) instruction of given 'expdesc' */
#define getinstruction(fs,e) ((fs)->f->code[(e)->u.info])
#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) #define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx)

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lcorolib.c,v 1.9 2014/11/02 19:19:04 roberto Exp $ ** $Id: lcorolib.c,v 1.10 2016/04/11 19:19:55 roberto Exp $
** Coroutine Library ** Coroutine Library
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -75,7 +75,7 @@ static int luaB_auxwrap (lua_State *L) {
lua_State *co = lua_tothread(L, lua_upvalueindex(1)); lua_State *co = lua_tothread(L, lua_upvalueindex(1));
int r = auxresume(L, co, lua_gettop(L)); int r = auxresume(L, co, lua_gettop(L));
if (r < 0) { if (r < 0) {
if (lua_isstring(L, -1)) { /* error object is a string? */ if (lua_type(L, -1) == LUA_TSTRING) { /* error object is a string? */
luaL_where(L, 1); /* add extra info */ luaL_where(L, 1); /* add extra info */
lua_insert(L, -2); lua_insert(L, -2);
lua_concat(L, 2); lua_concat(L, 2);

View File

@ -1,5 +1,5 @@
/* /*
** $Id: ldebug.c,v 2.117 2015/11/02 18:48:07 roberto Exp $ ** $Id: ldebug.c,v 2.120 2016/03/31 19:01:21 roberto Exp $
** Debug Interface ** Debug Interface
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -69,7 +69,13 @@ static void swapextra (lua_State *L) {
/* /*
** this function can be called asynchronous (e.g. during a signal) ** This function can be called asynchronously (e.g. during a signal).
** Fields 'oldpc', 'basehookcount', and 'hookcount' (set by
** 'resethookcount') are for debug only, and it is no problem if they
** get arbitrary values (causes at most one wrong hook call). 'hookmask'
** is an atomic value. We assume that pointers are atomic too (e.g., gcc
** ensures that for all platforms where it runs). Moreover, 'hook' is
** always checked before being called (see 'luaD_hook').
*/ */
LUA_API void lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { LUA_API void lua_sethook (lua_State *L, lua_Hook func, int mask, int count) {
if (func == NULL || mask == 0) { /* turn off hooks? */ if (func == NULL || mask == 0) { /* turn off hooks? */
@ -558,7 +564,7 @@ static const char *varinfo (lua_State *L, const TValue *o) {
l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) { l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
const char *t = objtypename(o); const char *t = luaT_objtypename(L, o);
luaG_runerror(L, "attempt to %s a %s value%s", op, t, varinfo(L, o)); luaG_runerror(L, "attempt to %s a %s value%s", op, t, varinfo(L, o));
} }
@ -590,9 +596,9 @@ l_noret luaG_tointerror (lua_State *L, const TValue *p1, const TValue *p2) {
l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) {
const char *t1 = objtypename(p1); const char *t1 = luaT_objtypename(L, p1);
const char *t2 = objtypename(p2); const char *t2 = luaT_objtypename(L, p2);
if (t1 == t2) if (strcmp(t1, t2) == 0)
luaG_runerror(L, "attempt to compare two %s values", t1); luaG_runerror(L, "attempt to compare two %s values", t1);
else else
luaG_runerror(L, "attempt to compare %s with %s", t1, t2); luaG_runerror(L, "attempt to compare %s with %s", t1, t2);

View File

@ -1,5 +1,5 @@
/* /*
** $Id: ldo.c,v 2.150 2015/11/19 19:16:22 roberto Exp $ ** $Id: ldo.c,v 2.151 2015/12/16 16:40:07 roberto Exp $
** Stack and Call structure of Lua ** Stack and Call structure of Lua
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -242,9 +242,14 @@ void luaD_inctop (lua_State *L) {
/* }================================================================== */ /* }================================================================== */
/*
** Call a hook for the given event. Make sure there is a hook to be
** called. (Both 'L->hook' and 'L->hookmask', which triggers this
** function, can be changed asynchronously by signals.)
*/
void luaD_hook (lua_State *L, int event, int line) { void luaD_hook (lua_State *L, int event, int line) {
lua_Hook hook = L->hook; lua_Hook hook = L->hook;
if (hook && L->allowhook) { if (hook && L->allowhook) { /* make sure there is a hook */
CallInfo *ci = L->ci; CallInfo *ci = L->ci;
ptrdiff_t top = savestack(L, L->top); ptrdiff_t top = savestack(L, L->top);
ptrdiff_t ci_top = savestack(L, ci->top); ptrdiff_t ci_top = savestack(L, ci->top);

View File

@ -1,5 +1,5 @@
/* /*
** $Id: ldo.h,v 2.28 2015/11/23 11:29:43 roberto Exp $ ** $Id: ldo.h,v 2.29 2015/12/21 13:02:14 roberto Exp $
** Stack and Call structure of Lua ** Stack and Call structure of Lua
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -25,7 +25,7 @@
{ pre; luaD_growstack(L, n); pos; } else { condmovestack(L,pre,pos); } { pre; luaD_growstack(L, n); pos; } else { condmovestack(L,pre,pos); }
/* In general, 'pre'/'pos' are empty (nothing to save) */ /* In general, 'pre'/'pos' are empty (nothing to save) */
#define luaD_checkstack(L,n) luaD_checkstackaux(L,n,,) #define luaD_checkstack(L,n) luaD_checkstackaux(L,n,(void)0,(void)0)

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lgc.c,v 2.210 2015/11/03 18:10:44 roberto Exp $ ** $Id: lgc.c,v 2.212 2016/03/31 19:02:03 roberto Exp $
** Garbage Collector ** Garbage Collector
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -754,14 +754,11 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
/* /*
** sweep a list until a live object (or end of list) ** sweep a list until a live object (or end of list)
*/ */
static GCObject **sweeptolive (lua_State *L, GCObject **p, int *n) { static GCObject **sweeptolive (lua_State *L, GCObject **p) {
GCObject **old = p; GCObject **old = p;
int i = 0;
do { do {
i++;
p = sweeplist(L, p, 1); p = sweeplist(L, p, 1);
} while (p == old); } while (p == old);
if (n) *n += i;
return p; return p;
} }
@ -856,10 +853,10 @@ static int runafewfinalizers (lua_State *L) {
/* /*
** call all pending finalizers ** call all pending finalizers
*/ */
static void callallpendingfinalizers (lua_State *L, int propagateerrors) { static void callallpendingfinalizers (lua_State *L) {
global_State *g = G(L); global_State *g = G(L);
while (g->tobefnz) while (g->tobefnz)
GCTM(L, propagateerrors); GCTM(L, 0);
} }
@ -909,7 +906,7 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
if (issweepphase(g)) { if (issweepphase(g)) {
makewhite(g, o); /* "sweep" object 'o' */ makewhite(g, o); /* "sweep" object 'o' */
if (g->sweepgc == &o->next) /* should not remove 'sweepgc' object */ if (g->sweepgc == &o->next) /* should not remove 'sweepgc' object */
g->sweepgc = sweeptolive(L, g->sweepgc, NULL); /* change 'sweepgc' */ g->sweepgc = sweeptolive(L, g->sweepgc); /* change 'sweepgc' */
} }
/* search for pointer pointing to 'o' */ /* search for pointer pointing to 'o' */
for (p = &g->allgc; *p != o; p = &(*p)->next) { /* empty */ } for (p = &g->allgc; *p != o; p = &(*p)->next) { /* empty */ }
@ -951,19 +948,16 @@ static void setpause (global_State *g) {
/* /*
** Enter first sweep phase. ** Enter first sweep phase.
** The call to 'sweeptolive' makes pointer point to an object inside ** The call to 'sweeplist' tries to make pointer point to an object
** the list (instead of to the header), so that the real sweep do not ** inside the list (instead of to the header), so that the real sweep do
** need to skip objects created between "now" and the start of the real ** not need to skip objects created between "now" and the start of the
** sweep. ** real sweep.
** Returns how many objects it swept.
*/ */
static int entersweep (lua_State *L) { static void entersweep (lua_State *L) {
global_State *g = G(L); global_State *g = G(L);
int n = 0;
g->gcstate = GCSswpallgc; g->gcstate = GCSswpallgc;
lua_assert(g->sweepgc == NULL); lua_assert(g->sweepgc == NULL);
g->sweepgc = sweeptolive(L, &g->allgc, &n); g->sweepgc = sweeplist(L, &g->allgc, 1);
return n;
} }
@ -971,7 +965,7 @@ void luaC_freeallobjects (lua_State *L) {
global_State *g = G(L); global_State *g = G(L);
separatetobefnz(g, 1); /* separate all objects with finalizers */ separatetobefnz(g, 1); /* separate all objects with finalizers */
lua_assert(g->finobj == NULL); lua_assert(g->finobj == NULL);
callallpendingfinalizers(L, 0); callallpendingfinalizers(L);
lua_assert(g->tobefnz == NULL); lua_assert(g->tobefnz == NULL);
g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */ g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */
g->gckind = KGC_NORMAL; g->gckind = KGC_NORMAL;
@ -1064,12 +1058,11 @@ static lu_mem singlestep (lua_State *L) {
} }
case GCSatomic: { case GCSatomic: {
lu_mem work; lu_mem work;
int sw;
propagateall(g); /* make sure gray list is empty */ propagateall(g); /* make sure gray list is empty */
work = atomic(L); /* work is what was traversed by 'atomic' */ work = atomic(L); /* work is what was traversed by 'atomic' */
sw = entersweep(L); entersweep(L);
g->GCestimate = gettotalbytes(g); /* first estimate */; g->GCestimate = gettotalbytes(g); /* first estimate */;
return work + sw * GCSWEEPCOST; return work;
} }
case GCSswpallgc: { /* sweep "regular" objects */ case GCSswpallgc: { /* sweep "regular" objects */
return sweepstep(L, g, GCSswpfinobj, &g->finobj); return sweepstep(L, g, GCSswpfinobj, &g->finobj);

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lgc.h,v 2.90 2015/10/21 18:15:15 roberto Exp $ ** $Id: lgc.h,v 2.91 2015/12/21 13:02:14 roberto Exp $
** Garbage Collector ** Garbage Collector
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -112,7 +112,7 @@
condchangemem(L,pre,pos); } condchangemem(L,pre,pos); }
/* more often than not, 'pre'/'pos' are empty */ /* more often than not, 'pre'/'pos' are empty */
#define luaC_checkGC(L) luaC_condGC(L,,) #define luaC_checkGC(L) luaC_condGC(L,(void)0,(void)0)
#define luaC_barrier(L,p,v) ( \ #define luaC_barrier(L,p,v) ( \

View File

@ -1,5 +1,5 @@
/* /*
** $Id: liolib.c,v 2.148 2015/11/23 11:36:11 roberto Exp $ ** $Id: liolib.c,v 2.149 2016/05/02 14:03:19 roberto Exp $
** Standard I/O (and system) library ** Standard I/O (and system) library
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -81,7 +81,7 @@
#if !defined(l_getc) /* { */ #if !defined(l_getc) /* { */
#if defined(LUA_USE_POSIX) && !defined(__native_client__) #if defined(LUA_USE_POSIX)
#define l_getc(f) getc_unlocked(f) #define l_getc(f) getc_unlocked(f)
#define l_lockfile(f) flockfile(f) #define l_lockfile(f) flockfile(f)
#define l_unlockfile(f) funlockfile(f) #define l_unlockfile(f) funlockfile(f)
@ -375,14 +375,17 @@ static int io_lines (lua_State *L) {
/* maximum length of a numeral */ /* maximum length of a numeral */
#define MAXRN 200 #if !defined (L_MAXLENNUM)
#define L_MAXLENNUM 200
#endif
/* auxiliary structure used by 'read_number' */ /* auxiliary structure used by 'read_number' */
typedef struct { typedef struct {
FILE *f; /* file being read */ FILE *f; /* file being read */
int c; /* current character (look ahead) */ int c; /* current character (look ahead) */
int n; /* number of elements in buffer 'buff' */ int n; /* number of elements in buffer 'buff' */
char buff[MAXRN + 1]; /* +1 for ending '\0' */ char buff[L_MAXLENNUM + 1]; /* +1 for ending '\0' */
} RN; } RN;
@ -390,7 +393,7 @@ typedef struct {
** Add current char to buffer (if not out of space) and read next one ** Add current char to buffer (if not out of space) and read next one
*/ */
static int nextc (RN *rn) { static int nextc (RN *rn) {
if (rn->n >= MAXRN) { /* buffer overflow? */ if (rn->n >= L_MAXLENNUM) { /* buffer overflow? */
rn->buff[0] = '\0'; /* invalidate result */ rn->buff[0] = '\0'; /* invalidate result */
return 0; /* fail */ return 0; /* fail */
} }
@ -403,10 +406,10 @@ static int nextc (RN *rn) {
/* /*
** Accept current char if it is in 'set' (of size 1 or 2) ** Accept current char if it is in 'set' (of size 2)
*/ */
static int test2 (RN *rn, const char *set) { static int test2 (RN *rn, const char *set) {
if (rn->c == set[0] || (rn->c == set[1] && rn->c != '\0')) if (rn->c == set[0] || rn->c == set[1])
return nextc(rn); return nextc(rn);
else return 0; else return 0;
} }
@ -435,11 +438,11 @@ static int read_number (lua_State *L, FILE *f) {
char decp[2]; char decp[2];
rn.f = f; rn.n = 0; rn.f = f; rn.n = 0;
decp[0] = lua_getlocaledecpoint(); /* get decimal point from locale */ decp[0] = lua_getlocaledecpoint(); /* get decimal point from locale */
decp[1] = '\0'; decp[1] = '.'; /* always accept a dot */
l_lockfile(rn.f); l_lockfile(rn.f);
do { rn.c = l_getc(rn.f); } while (isspace(rn.c)); /* skip spaces */ do { rn.c = l_getc(rn.f); } while (isspace(rn.c)); /* skip spaces */
test2(&rn, "-+"); /* optional signal */ test2(&rn, "-+"); /* optional signal */
if (test2(&rn, "0")) { if (test2(&rn, "00")) {
if (test2(&rn, "xX")) hex = 1; /* numeral is hexadecimal */ if (test2(&rn, "xX")) hex = 1; /* numeral is hexadecimal */
else count = 1; /* count initial '0' as a valid digit */ else count = 1; /* count initial '0' as a valid digit */
} }

View File

@ -1,5 +1,5 @@
/* /*
** $Id: llex.c,v 2.95 2015/11/19 19:16:22 roberto Exp $ ** $Id: llex.c,v 2.96 2016/05/02 14:02:12 roberto Exp $
** Lexical Analyzer ** Lexical Analyzer
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -162,7 +162,6 @@ static void inclinenumber (LexState *ls) {
void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source, void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source,
int firstchar) { int firstchar) {
ls->t.token = 0; ls->t.token = 0;
ls->decpoint = '.';
ls->L = L; ls->L = L;
ls->current = firstchar; ls->current = firstchar;
ls->lookahead.token = TK_EOS; /* no look-ahead token */ ls->lookahead.token = TK_EOS; /* no look-ahead token */
@ -207,35 +206,6 @@ static int check_next2 (LexState *ls, const char *set) {
} }
/*
** change all characters 'from' in buffer to 'to'
*/
static void buffreplace (LexState *ls, char from, char to) {
if (from != to) {
size_t n = luaZ_bufflen(ls->buff);
char *p = luaZ_buffer(ls->buff);
while (n--)
if (p[n] == from) p[n] = to;
}
}
/*
** in case of format error, try to change decimal point separator to
** the one defined in the current locale and check again
*/
static void trydecpoint (LexState *ls, TValue *o) {
char old = ls->decpoint;
ls->decpoint = lua_getlocaledecpoint();
buffreplace(ls, old, ls->decpoint); /* try new decimal separator */
if (luaO_str2num(luaZ_buffer(ls->buff), o) == 0) {
/* format error with correct decimal point: no more options */
buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */
lexerror(ls, "malformed number", TK_FLT);
}
}
/* LUA_NUMBER */ /* LUA_NUMBER */
/* /*
** this function is quite liberal in what it accepts, as 'luaO_str2num' ** this function is quite liberal in what it accepts, as 'luaO_str2num'
@ -259,9 +229,8 @@ static int read_numeral (LexState *ls, SemInfo *seminfo) {
else break; else break;
} }
save(ls, '\0'); save(ls, '\0');
buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */
if (luaO_str2num(luaZ_buffer(ls->buff), &obj) == 0) /* format error? */ if (luaO_str2num(luaZ_buffer(ls->buff), &obj) == 0) /* format error? */
trydecpoint(ls, &obj); /* try to update decimal point separator */ lexerror(ls, "malformed number", TK_FLT);
if (ttisinteger(&obj)) { if (ttisinteger(&obj)) {
seminfo->i = ivalue(&obj); seminfo->i = ivalue(&obj);
return TK_INT; return TK_INT;

View File

@ -1,5 +1,5 @@
/* /*
** $Id: llex.h,v 1.78 2014/10/29 15:38:24 roberto Exp $ ** $Id: llex.h,v 1.79 2016/05/02 14:02:12 roberto Exp $
** Lexical Analyzer ** Lexical Analyzer
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -69,7 +69,6 @@ typedef struct LexState {
struct Dyndata *dyd; /* dynamic structures used by the parser */ struct Dyndata *dyd; /* dynamic structures used by the parser */
TString *source; /* current source name */ TString *source; /* current source name */
TString *envn; /* environment variable name */ TString *envn; /* environment variable name */
char decpoint; /* locale decimal point */
} LexState; } LexState;

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lobject.c,v 2.108 2015/11/02 16:09:30 roberto Exp $ ** $Id: lobject.c,v 2.111 2016/05/20 14:07:48 roberto Exp $
** Some generic functions over Lua objects ** Some generic functions over Lua objects
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -243,20 +243,59 @@ static lua_Number lua_strx2number (const char *s, char **endptr) {
/* }====================================================== */ /* }====================================================== */
static const char *l_str2d (const char *s, lua_Number *result) { /* maximum length of a numeral */
#if !defined (L_MAXLENNUM)
#define L_MAXLENNUM 200
#endif
static const char *l_str2dloc (const char *s, lua_Number *result, int mode) {
char *endptr; char *endptr;
if (strpbrk(s, "nN")) /* reject 'inf' and 'nan' */ *result = (mode == 'x') ? lua_strx2number(s, &endptr) /* try to convert */
return NULL; : lua_str2number(s, &endptr);
else if (strpbrk(s, "xX")) /* hex? */ if (endptr == s) return NULL; /* nothing recognized? */
*result = lua_strx2number(s, &endptr); while (lisspace(cast_uchar(*endptr))) endptr++; /* skip trailing spaces */
else return (*endptr == '\0') ? endptr : NULL; /* OK if no trailing characters */
*result = lua_str2number(s, &endptr);
if (endptr == s) return NULL; /* nothing recognized */
while (lisspace(cast_uchar(*endptr))) endptr++;
return (*endptr == '\0' ? endptr : NULL); /* OK if no trailing characters */
} }
/*
** Convert string 's' to a Lua number (put in 'result'). Return NULL
** on fail or the address of the ending '\0' on success.
** 'pmode' points to (and 'mode' contains) special things in the string:
** - 'x'/'X' means an hexadecimal numeral
** - 'n'/'N' means 'inf' or 'nan' (which should be rejected)
** - '.' just optimizes the search for the common case (nothing special)
** This function accepts both the current locale or a dot as the radix
** mark. If the convertion fails, it may mean number has a dot but
** locale accepts something else. In that case, the code copies 's'
** to a buffer (because 's' is read-only), changes the dot to the
** current locale radix mark, and tries to convert again.
*/
static const char *l_str2d (const char *s, lua_Number *result) {
const char *endptr;
const char *pmode = strpbrk(s, ".xXnN");
int mode = pmode ? ltolower(cast_uchar(*pmode)) : 0;
if (mode == 'n') /* reject 'inf' and 'nan' */
return NULL;
endptr = l_str2dloc(s, result, mode); /* try to convert */
if (endptr == NULL) { /* failed? may be a different locale */
char buff[L_MAXLENNUM + 1];
char *pdot = strchr(s, '.');
if (strlen(s) > L_MAXLENNUM || pdot == NULL)
return NULL; /* string too long or no dot; fail */
strcpy(buff, s); /* copy string to buffer */
buff[pdot - s] = lua_getlocaledecpoint(); /* correct decimal point */
endptr = l_str2dloc(buff, result, mode); /* try again */
if (endptr != NULL)
endptr = s + (endptr - buff); /* make relative to 's' */
}
return endptr;
}
#define MAXBY10 cast(lua_Unsigned, LUA_MAXINTEGER / 10)
#define MAXLASTD cast_int(LUA_MAXINTEGER % 10)
static const char *l_str2int (const char *s, lua_Integer *result) { static const char *l_str2int (const char *s, lua_Integer *result) {
lua_Unsigned a = 0; lua_Unsigned a = 0;
int empty = 1; int empty = 1;
@ -273,7 +312,10 @@ static const char *l_str2int (const char *s, lua_Integer *result) {
} }
else { /* decimal */ else { /* decimal */
for (; lisdigit(cast_uchar(*s)); s++) { for (; lisdigit(cast_uchar(*s)); s++) {
a = a * 10 + *s - '0'; int d = *s - '0';
if (a >= MAXBY10 && (a > MAXBY10 || d > MAXLASTD + neg)) /* overflow? */
return NULL; /* do not accept it (as integer) */
a = a * 10 + d;
empty = 0; empty = 0;
} }
} }
@ -351,8 +393,10 @@ static void pushstr (lua_State *L, const char *str, size_t l) {
} }
/* this function handles only '%d', '%c', '%f', '%p', and '%s' /*
conventional formats, plus Lua-specific '%I' and '%U' */ ** this function handles only '%d', '%c', '%f', '%p', and '%s'
conventional formats, plus Lua-specific '%I' and '%U'
*/
const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
int n = 0; int n = 0;
for (;;) { for (;;) {
@ -360,13 +404,13 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
if (e == NULL) break; if (e == NULL) break;
pushstr(L, fmt, e - fmt); pushstr(L, fmt, e - fmt);
switch (*(e+1)) { switch (*(e+1)) {
case 's': { case 's': { /* zero-terminated string */
const char *s = va_arg(argp, char *); const char *s = va_arg(argp, char *);
if (s == NULL) s = "(null)"; if (s == NULL) s = "(null)";
pushstr(L, s, strlen(s)); pushstr(L, s, strlen(s));
break; break;
} }
case 'c': { case 'c': { /* an 'int' as a character */
char buff = cast(char, va_arg(argp, int)); char buff = cast(char, va_arg(argp, int));
if (lisprint(cast_uchar(buff))) if (lisprint(cast_uchar(buff)))
pushstr(L, &buff, 1); pushstr(L, &buff, 1);
@ -374,28 +418,28 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
luaO_pushfstring(L, "<\\%d>", cast_uchar(buff)); luaO_pushfstring(L, "<\\%d>", cast_uchar(buff));
break; break;
} }
case 'd': { case 'd': { /* an 'int' */
setivalue(L->top, va_arg(argp, int)); setivalue(L->top, va_arg(argp, int));
goto top2str; goto top2str;
} }
case 'I': { case 'I': { /* a 'lua_Integer' */
setivalue(L->top, cast(lua_Integer, va_arg(argp, l_uacInt))); setivalue(L->top, cast(lua_Integer, va_arg(argp, l_uacInt)));
goto top2str; goto top2str;
} }
case 'f': { case 'f': { /* a 'lua_Number' */
setfltvalue(L->top, cast_num(va_arg(argp, l_uacNumber))); setfltvalue(L->top, cast_num(va_arg(argp, l_uacNumber)));
top2str: top2str: /* convert the top element to a string */
luaD_inctop(L); luaD_inctop(L);
luaO_tostring(L, L->top - 1); luaO_tostring(L, L->top - 1);
break; break;
} }
case 'p': { case 'p': { /* a pointer */
char buff[4*sizeof(void *) + 8]; /* should be enough space for a '%p' */ char buff[4*sizeof(void *) + 8]; /* should be enough space for a '%p' */
int l = l_sprintf(buff, sizeof(buff), "%p", va_arg(argp, void *)); int l = l_sprintf(buff, sizeof(buff), "%p", va_arg(argp, void *));
pushstr(L, buff, l); pushstr(L, buff, l);
break; break;
} }
case 'U': { case 'U': { /* an 'int' as a UTF-8 sequence */
char buff[UTF8BUFFSZ]; char buff[UTF8BUFFSZ];
int l = luaO_utf8esc(buff, cast(long, va_arg(argp, long))); int l = luaO_utf8esc(buff, cast(long, va_arg(argp, long)));
pushstr(L, buff + UTF8BUFFSZ - l, l); pushstr(L, buff + UTF8BUFFSZ - l, l);

View File

@ -1,5 +1,5 @@
/* /*
** $Id: loslib.c,v 1.60 2015/11/19 19:16:22 roberto Exp $ ** $Id: loslib.c,v 1.64 2016/04/18 13:06:55 roberto Exp $
** Standard Operating System library ** Standard Operating System library
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -24,18 +24,29 @@
/* /*
** {================================================================== ** {==================================================================
** list of valid conversion specifiers for the 'strftime' function ** List of valid conversion specifiers for the 'strftime' function;
** options are grouped by length; group of length 2 start with '||'.
** =================================================================== ** ===================================================================
*/ */
#if !defined(LUA_STRFTIMEOPTIONS) /* { */ #if !defined(LUA_STRFTIMEOPTIONS) /* { */
#if defined(LUA_USE_C89) /* options for ANSI C 89 */
#define LUA_STRFTIMEOPTIONS { "aAbBcdHIjmMpSUwWxXyYz%", "" } #define L_STRFTIMEC89 "aAbBcdHIjmMpSUwWxXyYZ%"
/* options for ISO C 99 and POSIX */
#define L_STRFTIMEC99 "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%" \
"||" "EcECExEXEyEY" "OdOeOHOIOmOMOSOuOUOVOwOWOy"
/* options for Windows */
#define L_STRFTIMEWIN "aAbBcdHIjmMpSUwWxXyYzZ%" \
"||" "#c#x#d#H#I#j#m#M#S#U#w#W#y#Y"
#if defined(LUA_USE_WINDOWS)
#define LUA_STRFTIMEOPTIONS L_STRFTIMEWIN
#elif defined(LUA_USE_C89)
#define LUA_STRFTIMEOPTIONS L_STRFTIMEC89
#else /* C99 specification */ #else /* C99 specification */
#define LUA_STRFTIMEOPTIONS \ #define LUA_STRFTIMEOPTIONS L_STRFTIMEC99
{ "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%", "", \
"E", "cCxXyY", \
"O", "deHImMSuUVwWy" }
#endif #endif
#endif /* } */ #endif /* } */
@ -195,6 +206,23 @@ static void setboolfield (lua_State *L, const char *key, int value) {
lua_setfield(L, -2, key); lua_setfield(L, -2, key);
} }
/*
** Set all fields from structure 'tm' in the table on top of the stack
*/
static void setallfields (lua_State *L, struct tm *stm) {
setfield(L, "sec", stm->tm_sec);
setfield(L, "min", stm->tm_min);
setfield(L, "hour", stm->tm_hour);
setfield(L, "day", stm->tm_mday);
setfield(L, "month", stm->tm_mon + 1);
setfield(L, "year", stm->tm_year + 1900);
setfield(L, "wday", stm->tm_wday + 1);
setfield(L, "yday", stm->tm_yday + 1);
setboolfield(L, "isdst", stm->tm_isdst);
}
static int getboolfield (lua_State *L, const char *key) { static int getboolfield (lua_State *L, const char *key) {
int res; int res;
res = (lua_getfield(L, -1, key) == LUA_TNIL) ? -1 : lua_toboolean(L, -1); res = (lua_getfield(L, -1, key) == LUA_TNIL) ? -1 : lua_toboolean(L, -1);
@ -210,18 +238,18 @@ static int getboolfield (lua_State *L, const char *key) {
static int getfield (lua_State *L, const char *key, int d, int delta) { static int getfield (lua_State *L, const char *key, int d, int delta) {
int isnum; int isnum;
int t = lua_getfield(L, -1, key); int t = lua_getfield(L, -1, key); /* get field and its type */
lua_Integer res = lua_tointegerx(L, -1, &isnum); lua_Integer res = lua_tointegerx(L, -1, &isnum);
if (!isnum) { /* field is not a number? */ if (!isnum) { /* field is not an integer? */
if (t != LUA_TNIL) /* some other value? */ if (t != LUA_TNIL) /* some other value? */
return luaL_error(L, "field '%s' not an integer", key); return luaL_error(L, "field '%s' is not an integer", key);
else if (d < 0) /* absent field; no default? */ else if (d < 0) /* absent field; no default? */
return luaL_error(L, "field '%s' missing in date table", key); return luaL_error(L, "field '%s' missing in date table", key);
res = d; res = d;
} }
else { else {
if (!(-L_MAXDATEFIELD <= res && res <= L_MAXDATEFIELD)) if (!(-L_MAXDATEFIELD <= res && res <= L_MAXDATEFIELD))
return luaL_error(L, "field '%s' out-of-bounds", key); return luaL_error(L, "field '%s' is out-of-bound", key);
res -= delta; res -= delta;
} }
lua_pop(L, 1); lua_pop(L, 1);
@ -230,21 +258,15 @@ static int getfield (lua_State *L, const char *key, int d, int delta) {
static const char *checkoption (lua_State *L, const char *conv, char *buff) { static const char *checkoption (lua_State *L, const char *conv, char *buff) {
static const char *const options[] = LUA_STRFTIMEOPTIONS; const char *option;
unsigned int i; int oplen = 1;
for (i = 0; i < sizeof(options)/sizeof(options[0]); i += 2) { for (option = LUA_STRFTIMEOPTIONS; *option != '\0'; option += oplen) {
if (*conv != '\0' && strchr(options[i], *conv) != NULL) { if (*option == '|') /* next block? */
buff[1] = *conv; oplen++; /* next length */
if (*options[i + 1] == '\0') { /* one-char conversion specifier? */ else if (memcmp(conv, option, oplen) == 0) { /* match? */
buff[2] = '\0'; /* end buffer */ memcpy(buff, conv, oplen); /* copy valid option to buffer */
return conv + 1; buff[oplen] = '\0';
} return conv + oplen; /* return next item */
else if (*(conv + 1) != '\0' &&
strchr(options[i + 1], *(conv + 1)) != NULL) {
buff[2] = *(conv + 1); /* valid two-char conversion specifier */
buff[3] = '\0'; /* end buffer */
return conv + 2;
}
} }
} }
luaL_argerror(L, 1, luaL_argerror(L, 1,
@ -271,18 +293,10 @@ static int os_date (lua_State *L) {
luaL_error(L, "time result cannot be represented in this installation"); luaL_error(L, "time result cannot be represented in this installation");
if (strcmp(s, "*t") == 0) { if (strcmp(s, "*t") == 0) {
lua_createtable(L, 0, 9); /* 9 = number of fields */ lua_createtable(L, 0, 9); /* 9 = number of fields */
setfield(L, "sec", stm->tm_sec); setallfields(L, stm);
setfield(L, "min", stm->tm_min);
setfield(L, "hour", stm->tm_hour);
setfield(L, "day", stm->tm_mday);
setfield(L, "month", stm->tm_mon+1);
setfield(L, "year", stm->tm_year+1900);
setfield(L, "wday", stm->tm_wday+1);
setfield(L, "yday", stm->tm_yday+1);
setboolfield(L, "isdst", stm->tm_isdst);
} }
else { else {
char cc[4]; char cc[4]; /* buffer for individual conversion specifiers */
luaL_Buffer b; luaL_Buffer b;
cc[0] = '%'; cc[0] = '%';
luaL_buffinit(L, &b); luaL_buffinit(L, &b);
@ -292,7 +306,7 @@ static int os_date (lua_State *L) {
else { else {
size_t reslen; size_t reslen;
char *buff = luaL_prepbuffsize(&b, SIZETIMEFMT); char *buff = luaL_prepbuffsize(&b, SIZETIMEFMT);
s = checkoption(L, s + 1, cc); s = checkoption(L, s + 1, cc + 1); /* copy specifier to 'cc' */
reslen = strftime(buff, SIZETIMEFMT, cc, stm); reslen = strftime(buff, SIZETIMEFMT, cc, stm);
luaL_addsize(&b, reslen); luaL_addsize(&b, reslen);
} }
@ -319,6 +333,7 @@ static int os_time (lua_State *L) {
ts.tm_year = getfield(L, "year", -1, 1900); ts.tm_year = getfield(L, "year", -1, 1900);
ts.tm_isdst = getboolfield(L, "isdst"); ts.tm_isdst = getboolfield(L, "isdst");
t = mktime(&ts); t = mktime(&ts);
setallfields(L, &ts); /* update fields with normalized values */
} }
if (t != (time_t)(l_timet)t || t == (time_t)(-1)) if (t != (time_t)(l_timet)t || t == (time_t)(-1))
luaL_error(L, "time result cannot be represented in this installation"); luaL_error(L, "time result cannot be represented in this installation");

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lparser.c,v 2.149 2015/11/02 16:09:30 roberto Exp $ ** $Id: lparser.c,v 2.153 2016/05/13 19:10:16 roberto Exp $
** Lua Parser ** Lua Parser
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -164,7 +164,8 @@ static int registerlocalvar (LexState *ls, TString *varname) {
int oldsize = f->sizelocvars; int oldsize = f->sizelocvars;
luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars,
LocVar, SHRT_MAX, "local variables"); LocVar, SHRT_MAX, "local variables");
while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL; while (oldsize < f->sizelocvars)
f->locvars[oldsize++].varname = NULL;
f->locvars[fs->nlocvars].varname = varname; f->locvars[fs->nlocvars].varname = varname;
luaC_objbarrier(ls->L, f, varname); luaC_objbarrier(ls->L, f, varname);
return fs->nlocvars++; return fs->nlocvars++;
@ -230,7 +231,8 @@ static int newupvalue (FuncState *fs, TString *name, expdesc *v) {
checklimit(fs, fs->nups + 1, MAXUPVAL, "upvalues"); checklimit(fs, fs->nups + 1, MAXUPVAL, "upvalues");
luaM_growvector(fs->ls->L, f->upvalues, fs->nups, f->sizeupvalues, luaM_growvector(fs->ls->L, f->upvalues, fs->nups, f->sizeupvalues,
Upvaldesc, MAXUPVAL, "upvalues"); Upvaldesc, MAXUPVAL, "upvalues");
while (oldsize < f->sizeupvalues) f->upvalues[oldsize++].name = NULL; while (oldsize < f->sizeupvalues)
f->upvalues[oldsize++].name = NULL;
f->upvalues[fs->nups].instack = (v->k == VLOCAL); f->upvalues[fs->nups].instack = (v->k == VLOCAL);
f->upvalues[fs->nups].idx = cast_byte(v->u.info); f->upvalues[fs->nups].idx = cast_byte(v->u.info);
f->upvalues[fs->nups].name = name; f->upvalues[fs->nups].name = name;
@ -255,7 +257,8 @@ static int searchvar (FuncState *fs, TString *n) {
*/ */
static void markupval (FuncState *fs, int level) { static void markupval (FuncState *fs, int level) {
BlockCnt *bl = fs->bl; BlockCnt *bl = fs->bl;
while (bl->nactvar > level) bl = bl->previous; while (bl->nactvar > level)
bl = bl->previous;
bl->upval = 1; bl->upval = 1;
} }
@ -264,27 +267,26 @@ static void markupval (FuncState *fs, int level) {
Find variable with given name 'n'. If it is an upvalue, add this Find variable with given name 'n'. If it is an upvalue, add this
upvalue into all intermediate functions. upvalue into all intermediate functions.
*/ */
static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
if (fs == NULL) /* no more levels? */ if (fs == NULL) /* no more levels? */
return VVOID; /* default is global */ init_exp(var, VVOID, 0); /* default is global */
else { else {
int v = searchvar(fs, n); /* look up locals at current level */ int v = searchvar(fs, n); /* look up locals at current level */
if (v >= 0) { /* found? */ if (v >= 0) { /* found? */
init_exp(var, VLOCAL, v); /* variable is local */ init_exp(var, VLOCAL, v); /* variable is local */
if (!base) if (!base)
markupval(fs, v); /* local will be used as an upval */ markupval(fs, v); /* local will be used as an upval */
return VLOCAL;
} }
else { /* not found as local at current level; try upvalues */ else { /* not found as local at current level; try upvalues */
int idx = searchupvalue(fs, n); /* try existing upvalues */ int idx = searchupvalue(fs, n); /* try existing upvalues */
if (idx < 0) { /* not found? */ if (idx < 0) { /* not found? */
if (singlevaraux(fs->prev, n, var, 0) == VVOID) /* try upper levels */ singlevaraux(fs->prev, n, var, 0); /* try upper levels */
return VVOID; /* not found; is a global */ if (var->k == VVOID) /* not found? */
return; /* it is a global */
/* else was LOCAL or UPVAL */ /* else was LOCAL or UPVAL */
idx = newupvalue(fs, n, var); /* will be a new upvalue */ idx = newupvalue(fs, n, var); /* will be a new upvalue */
} }
init_exp(var, VUPVAL, idx); init_exp(var, VUPVAL, idx); /* new or old upvalue */
return VUPVAL;
} }
} }
} }
@ -293,10 +295,11 @@ static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
static void singlevar (LexState *ls, expdesc *var) { static void singlevar (LexState *ls, expdesc *var) {
TString *varname = str_checkname(ls); TString *varname = str_checkname(ls);
FuncState *fs = ls->fs; FuncState *fs = ls->fs;
if (singlevaraux(fs, varname, var, 1) == VVOID) { /* global name? */ singlevaraux(fs, varname, var, 1);
if (var->k == VVOID) { /* global name? */
expdesc key; expdesc key;
singlevaraux(fs, ls->envn, var, 1); /* get environment variable */ singlevaraux(fs, ls->envn, var, 1); /* get environment variable */
lua_assert(var->k == VLOCAL || var->k == VUPVAL); lua_assert(var->k != VVOID); /* this one must exist */
codestring(ls, &key, varname); /* key is variable name */ codestring(ls, &key, varname); /* key is variable name */
luaK_indexed(fs, var, &key); /* env[varname] */ luaK_indexed(fs, var, &key); /* env[varname] */
} }
@ -499,7 +502,8 @@ static Proto *addprototype (LexState *ls) {
if (fs->np >= f->sizep) { if (fs->np >= f->sizep) {
int oldsize = f->sizep; int oldsize = f->sizep;
luaM_growvector(L, f->p, fs->np, f->sizep, Proto *, MAXARG_Bx, "functions"); luaM_growvector(L, f->p, fs->np, f->sizep, Proto *, MAXARG_Bx, "functions");
while (oldsize < f->sizep) f->p[oldsize++] = NULL; while (oldsize < f->sizep)
f->p[oldsize++] = NULL;
} }
f->p[fs->np++] = clp = luaF_newproto(L); f->p[fs->np++] = clp = luaF_newproto(L);
luaC_objbarrier(L, f, clp); luaC_objbarrier(L, f, clp);
@ -1226,7 +1230,7 @@ static void labelstat (LexState *ls, TString *label, int line) {
checkrepeated(fs, ll, label); /* check for repeated labels */ checkrepeated(fs, ll, label); /* check for repeated labels */
checknext(ls, TK_DBCOLON); /* skip double colon */ checknext(ls, TK_DBCOLON); /* skip double colon */
/* create new entry for this label */ /* create new entry for this label */
l = newlabelentry(ls, ll, label, line, fs->pc); l = newlabelentry(ls, ll, label, line, luaK_getlabel(fs));
skipnoopstat(ls); /* skip other no-op statements */ skipnoopstat(ls); /* skip other no-op statements */
if (block_follow(ls, 0)) { /* label is last no-op statement in the block? */ if (block_follow(ls, 0)) { /* label is last no-op statement in the block? */
/* assume that locals are already out of scope */ /* assume that locals are already out of scope */
@ -1494,7 +1498,7 @@ static void exprstat (LexState *ls) {
} }
else { /* stat -> func */ else { /* stat -> func */
check_condition(ls, v.v.k == VCALL, "syntax error"); check_condition(ls, v.v.k == VCALL, "syntax error");
SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */ SETARG_C(getinstruction(fs, &v.v), 1); /* call statement uses no results */
} }
} }
@ -1511,8 +1515,8 @@ static void retstat (LexState *ls) {
if (hasmultret(e.k)) { if (hasmultret(e.k)) {
luaK_setmultret(fs, &e); luaK_setmultret(fs, &e);
if (e.k == VCALL && nret == 1) { /* tail call? */ if (e.k == VCALL && nret == 1) { /* tail call? */
SET_OPCODE(getcode(fs,&e), OP_TAILCALL); SET_OPCODE(getinstruction(fs,&e), OP_TAILCALL);
lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar); lua_assert(GETARG_A(getinstruction(fs,&e)) == fs->nactvar);
} }
first = fs->nactvar; first = fs->nactvar;
nret = LUA_MULTRET; /* return all values */ nret = LUA_MULTRET; /* return all values */

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lparser.h,v 1.74 2014/10/25 11:50:46 roberto Exp $ ** $Id: lparser.h,v 1.76 2015/12/30 18:16:13 roberto Exp $
** Lua Parser ** Lua Parser
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -13,25 +13,38 @@
/* /*
** Expression descriptor ** Expression and variable descriptor.
** Code generation for variables and expressions can be delayed to allow
** optimizations; An 'expdesc' structure describes a potentially-delayed
** variable/expression. It has a description of its "main" value plus a
** list of conditional jumps that can also produce its value (generated
** by short-circuit operators 'and'/'or').
*/ */
/* kinds of variables/expressions */
typedef enum { typedef enum {
VVOID, /* no value */ VVOID, /* when 'expdesc' describes the last expression a list,
VNIL, this kind means an empty list (so, no expression) */
VTRUE, VNIL, /* constant nil */
VFALSE, VTRUE, /* constant true */
VK, /* info = index of constant in 'k' */ VFALSE, /* constant false */
VKFLT, /* nval = numerical float value */ VK, /* constant in 'k'; info = index of constant in 'k' */
VKINT, /* nval = numerical integer value */ VKFLT, /* floating constant; nval = numerical float value */
VNONRELOC, /* info = result register */ VKINT, /* integer constant; nval = numerical integer value */
VLOCAL, /* info = local register */ VNONRELOC, /* expression has its value in a fixed register;
VUPVAL, /* info = index of upvalue in 'upvalues' */ info = result register */
VINDEXED, /* t = table register/upvalue; idx = index R/K */ VLOCAL, /* local variable; info = local register */
VJMP, /* info = instruction pc */ VUPVAL, /* upvalue variable; info = index of upvalue in 'upvalues' */
VRELOCABLE, /* info = instruction pc */ VINDEXED, /* indexed variable;
VCALL, /* info = instruction pc */ ind.vt = whether 't' is register or upvalue;
VVARARG /* info = instruction pc */ ind.t = table register or upvalue;
ind.idx = key's R/K index */
VJMP, /* expression is a test/comparison;
info = pc of corresponding jump instruction */
VRELOCABLE, /* expression can put result in any register;
info = instruction pc */
VCALL, /* expression is a function call; info = instruction pc */
VVARARG /* vararg expression; info = instruction pc */
} expkind; } expkind;
@ -41,14 +54,14 @@ typedef enum {
typedef struct expdesc { typedef struct expdesc {
expkind k; expkind k;
union { union {
lua_Integer ival; /* for VKINT */
lua_Number nval; /* for VKFLT */
int info; /* for generic use */
struct { /* for indexed variables (VINDEXED) */ struct { /* for indexed variables (VINDEXED) */
short idx; /* index (R/K) */ short idx; /* index (R/K) */
lu_byte t; /* table (register or upvalue) */ lu_byte t; /* table (register or upvalue) */
lu_byte vt; /* whether 't' is register (VLOCAL) or upvalue (VUPVAL) */ lu_byte vt; /* whether 't' is register (VLOCAL) or upvalue (VUPVAL) */
} ind; } ind;
int info; /* for generic use */
lua_Number nval; /* for VKFLT */
lua_Integer ival; /* for VKINT */
} u; } u;
int t; /* patch list of 'exit when true' */ int t; /* patch list of 'exit when true' */
int f; /* patch list of 'exit when false' */ int f; /* patch list of 'exit when false' */

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lstate.h,v 2.128 2015/11/13 12:16:51 roberto Exp $ ** $Id: lstate.h,v 2.130 2015/12/16 16:39:38 roberto Exp $
** Global State ** Global State
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -33,6 +33,15 @@
struct lua_longjmp; /* defined in ldo.c */ struct lua_longjmp; /* defined in ldo.c */
/*
** Atomic type (relative to signals) to better ensure that 'lua_sethook'
** is thread safe
*/
#if !defined(l_signalT)
#include <signal.h>
#define l_signalT sig_atomic_t
#endif
/* extra stack space to handle TM calls and some other extras */ /* extra stack space to handle TM calls and some other extras */
#define EXTRA_STACK 5 #define EXTRA_STACK 5
@ -162,14 +171,14 @@ struct lua_State {
struct lua_State *twups; /* list of threads with open upvalues */ struct lua_State *twups; /* list of threads with open upvalues */
struct lua_longjmp *errorJmp; /* current error recover point */ struct lua_longjmp *errorJmp; /* current error recover point */
CallInfo base_ci; /* CallInfo for first level (C calling Lua) */ CallInfo base_ci; /* CallInfo for first level (C calling Lua) */
lua_Hook hook; volatile lua_Hook hook;
ptrdiff_t errfunc; /* current error handling function (stack index) */ ptrdiff_t errfunc; /* current error handling function (stack index) */
int stacksize; int stacksize;
int basehookcount; int basehookcount;
int hookcount; int hookcount;
unsigned short nny; /* number of non-yieldable calls in stack */ unsigned short nny; /* number of non-yieldable calls in stack */
unsigned short nCcalls; /* number of nested C calls */ unsigned short nCcalls; /* number of nested C calls */
lu_byte hookmask; l_signalT hookmask;
lu_byte allowhook; lu_byte allowhook;
}; };

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lstrlib.c,v 1.239 2015/11/25 16:28:17 roberto Exp $ ** $Id: lstrlib.c,v 1.251 2016/05/20 14:13:21 roberto Exp $
** Standard library for string operations and pattern-matching ** Standard library for string operations and pattern-matching
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -13,6 +13,7 @@
#include <ctype.h> #include <ctype.h>
#include <float.h> #include <float.h>
#include <limits.h> #include <limits.h>
#include <locale.h>
#include <stddef.h> #include <stddef.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -26,7 +27,8 @@
/* /*
** maximum number of captures that a pattern can do during ** maximum number of captures that a pattern can do during
** pattern-matching. This limit is arbitrary. ** pattern-matching. This limit is arbitrary, but must fit in
** an unsigned char.
*/ */
#if !defined(LUA_MAXCAPTURES) #if !defined(LUA_MAXCAPTURES)
#define LUA_MAXCAPTURES 32 #define LUA_MAXCAPTURES 32
@ -214,9 +216,8 @@ typedef struct MatchState {
const char *src_end; /* end ('\0') of source string */ const char *src_end; /* end ('\0') of source string */
const char *p_end; /* end ('\0') of pattern */ const char *p_end; /* end ('\0') of pattern */
lua_State *L; lua_State *L;
size_t nrep; /* limit to avoid non-linear complexity */
int matchdepth; /* control for recursive depth (to avoid C stack overflow) */ int matchdepth; /* control for recursive depth (to avoid C stack overflow) */
int level; /* total number of captures (finished or unfinished) */ unsigned char level; /* total number of captures (finished or unfinished) */
struct { struct {
const char *init; const char *init;
ptrdiff_t len; ptrdiff_t len;
@ -234,17 +235,6 @@ static const char *match (MatchState *ms, const char *s, const char *p);
#endif #endif
/*
** parameters to control the maximum number of operators handled in
** a match (to avoid non-linear complexity). The maximum will be:
** (subject length) * A_REPS + B_REPS
*/
#if !defined(A_REPS)
#define A_REPS 4
#define B_REPS 100000
#endif
#define L_ESC '%' #define L_ESC '%'
#define SPECIALS "^$*+?.([%-" #define SPECIALS "^$*+?.([%-"
@ -502,8 +492,6 @@ static const char *match (MatchState *ms, const char *s, const char *p) {
s = NULL; /* fail */ s = NULL; /* fail */
} }
else { /* matched once */ else { /* matched once */
if (ms->nrep-- == 0)
luaL_error(ms->L, "pattern too complex");
switch (*ep) { /* handle optional suffix */ switch (*ep) { /* handle optional suffix */
case '?': { /* optional */ case '?': { /* optional */
const char *res; const char *res;
@ -607,10 +595,6 @@ static void prepstate (MatchState *ms, lua_State *L,
ms->src_init = s; ms->src_init = s;
ms->src_end = s + ls; ms->src_end = s + ls;
ms->p_end = p + lp; ms->p_end = p + lp;
if (ls < (MAX_SIZET - B_REPS) / A_REPS)
ms->nrep = A_REPS * ls + B_REPS;
else /* overflow (very long subject) */
ms->nrep = MAX_SIZET; /* no limit */
} }
@ -681,6 +665,7 @@ static int str_match (lua_State *L) {
typedef struct GMatchState { typedef struct GMatchState {
const char *src; /* current position */ const char *src; /* current position */
const char *p; /* pattern */ const char *p; /* pattern */
const char *lastmatch; /* end of last match */
MatchState ms; /* match state */ MatchState ms; /* match state */
} GMatchState; } GMatchState;
@ -688,14 +673,12 @@ typedef struct GMatchState {
static int gmatch_aux (lua_State *L) { static int gmatch_aux (lua_State *L) {
GMatchState *gm = (GMatchState *)lua_touserdata(L, lua_upvalueindex(3)); GMatchState *gm = (GMatchState *)lua_touserdata(L, lua_upvalueindex(3));
const char *src; const char *src;
gm->ms.L = L;
for (src = gm->src; src <= gm->ms.src_end; src++) { for (src = gm->src; src <= gm->ms.src_end; src++) {
const char *e; const char *e;
reprepstate(&gm->ms); reprepstate(&gm->ms);
if ((e = match(&gm->ms, src, gm->p)) != NULL) { if ((e = match(&gm->ms, src, gm->p)) != NULL && e != gm->lastmatch) {
if (e == src) /* empty match? */ gm->src = gm->lastmatch = e;
gm->src =src + 1; /* go at least one position */
else
gm->src = e;
return push_captures(&gm->ms, src, e); return push_captures(&gm->ms, src, e);
} }
} }
@ -711,7 +694,7 @@ static int gmatch (lua_State *L) {
lua_settop(L, 2); /* keep them on closure to avoid being collected */ lua_settop(L, 2); /* keep them on closure to avoid being collected */
gm = (GMatchState *)lua_newuserdata(L, sizeof(GMatchState)); gm = (GMatchState *)lua_newuserdata(L, sizeof(GMatchState));
prepstate(&gm->ms, L, s, ls, p, lp); prepstate(&gm->ms, L, s, ls, p, lp);
gm->src = s; gm->p = p; gm->src = s; gm->p = p; gm->lastmatch = NULL;
lua_pushcclosure(L, gmatch_aux, 3); lua_pushcclosure(L, gmatch_aux, 3);
return 1; return 1;
} }
@ -778,12 +761,13 @@ static void add_value (MatchState *ms, luaL_Buffer *b, const char *s,
static int str_gsub (lua_State *L) { static int str_gsub (lua_State *L) {
size_t srcl, lp; size_t srcl, lp;
const char *src = luaL_checklstring(L, 1, &srcl); const char *src = luaL_checklstring(L, 1, &srcl); /* subject */
const char *p = luaL_checklstring(L, 2, &lp); const char *p = luaL_checklstring(L, 2, &lp); /* pattern */
int tr = lua_type(L, 3); const char *lastmatch = NULL; /* end of last match */
lua_Integer max_s = luaL_optinteger(L, 4, srcl + 1); int tr = lua_type(L, 3); /* replacement type */
lua_Integer max_s = luaL_optinteger(L, 4, srcl + 1); /* max replacements */
int anchor = (*p == '^'); int anchor = (*p == '^');
lua_Integer n = 0; lua_Integer n = 0; /* replacement count */
MatchState ms; MatchState ms;
luaL_Buffer b; luaL_Buffer b;
luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING ||
@ -796,16 +780,15 @@ static int str_gsub (lua_State *L) {
prepstate(&ms, L, src, srcl, p, lp); prepstate(&ms, L, src, srcl, p, lp);
while (n < max_s) { while (n < max_s) {
const char *e; const char *e;
reprepstate(&ms); reprepstate(&ms); /* (re)prepare state for new match */
if ((e = match(&ms, src, p)) != NULL) { if ((e = match(&ms, src, p)) != NULL && e != lastmatch) { /* match? */
n++; n++;
add_value(&ms, &b, src, e, tr); add_value(&ms, &b, src, e, tr); /* add replacement to buffer */
src = lastmatch = e;
} }
if (e && e>src) /* non empty match? */ else if (src < ms.src_end) /* otherwise, skip one character */
src = e; /* skip it */
else if (src < ms.src_end)
luaL_addchar(&b, *src++); luaL_addchar(&b, *src++);
else break; else break; /* end of subject */
if (anchor) break; if (anchor) break;
} }
luaL_addlstring(&b, src, ms.src_end-src); luaL_addlstring(&b, src, ms.src_end-src);
@ -830,7 +813,6 @@ static int str_gsub (lua_State *L) {
** Hexadecimal floating-point formatter ** Hexadecimal floating-point formatter
*/ */
#include <locale.h>
#include <math.h> #include <math.h>
#define SIZELENMOD (sizeof(LUA_NUMBER_FRMLEN)/sizeof(char)) #define SIZELENMOD (sizeof(LUA_NUMBER_FRMLEN)/sizeof(char))
@ -922,16 +904,14 @@ static int lua_number2strx (lua_State *L, char *buff, int sz,
#define MAX_FORMAT 32 #define MAX_FORMAT 32
static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { static void addquoted (luaL_Buffer *b, const char *s, size_t len) {
size_t l;
const char *s = luaL_checklstring(L, arg, &l);
luaL_addchar(b, '"'); luaL_addchar(b, '"');
while (l--) { while (len--) {
if (*s == '"' || *s == '\\' || *s == '\n') { if (*s == '"' || *s == '\\' || *s == '\n') {
luaL_addchar(b, '\\'); luaL_addchar(b, '\\');
luaL_addchar(b, *s); luaL_addchar(b, *s);
} }
else if (*s == '\0' || iscntrl(uchar(*s))) { else if (iscntrl(uchar(*s))) {
char buff[10]; char buff[10];
if (!isdigit(uchar(*(s+1)))) if (!isdigit(uchar(*(s+1))))
l_sprintf(buff, sizeof(buff), "\\%d", (int)uchar(*s)); l_sprintf(buff, sizeof(buff), "\\%d", (int)uchar(*s));
@ -946,6 +926,57 @@ static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
luaL_addchar(b, '"'); luaL_addchar(b, '"');
} }
/*
** Ensures the 'buff' string uses a dot as the radix character.
*/
static void checkdp (char *buff, int nb) {
if (memchr(buff, '.', nb) == NULL) { /* no dot? */
char point = lua_getlocaledecpoint(); /* try locale point */
char *ppoint = memchr(buff, point, nb);
if (ppoint) *ppoint = '.'; /* change it to a dot */
}
}
static void addliteral (lua_State *L, luaL_Buffer *b, int arg) {
switch (lua_type(L, arg)) {
case LUA_TSTRING: {
size_t len;
const char *s = lua_tolstring(L, arg, &len);
addquoted(b, s, len);
break;
}
case LUA_TNUMBER: {
char *buff = luaL_prepbuffsize(b, MAX_ITEM);
int nb;
if (!lua_isinteger(L, arg)) { /* float? */
lua_Number n = lua_tonumber(L, arg); /* write as hexa ('%a') */
nb = lua_number2strx(L, buff, MAX_ITEM, "%" LUA_NUMBER_FRMLEN "a", n);
checkdp(buff, nb); /* ensure it uses a dot */
}
else { /* integers */
lua_Integer n = lua_tointeger(L, arg);
const char *format = (n == LUA_MININTEGER) /* corner case? */
? "0x%" LUA_INTEGER_FRMLEN "x" /* use hexa */
: LUA_INTEGER_FMT; /* else use default format */
nb = l_sprintf(buff, MAX_ITEM, format, n);
}
luaL_addsize(b, nb);
break;
}
case LUA_TNIL: case LUA_TBOOLEAN: {
luaL_tolstring(L, arg, NULL);
luaL_addvalue(b);
break;
}
default: {
luaL_argerror(L, arg, "value has no literal form");
}
}
}
static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { static const char *scanformat (lua_State *L, const char *strfrmt, char *form) {
const char *p = strfrmt; const char *p = strfrmt;
while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */ while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */
@ -1025,7 +1056,7 @@ static int str_format (lua_State *L) {
break; break;
} }
case 'q': { case 'q': {
addquoted(L, &b, arg); addliteral(L, &b, arg);
break; break;
} }
case 's': { case 's': {
@ -1070,8 +1101,8 @@ static int str_format (lua_State *L) {
/* value used for padding */ /* value used for padding */
#if !defined(LUA_PACKPADBYTE) #if !defined(LUAL_PACKPADBYTE)
#define LUA_PACKPADBYTE 0x00 #define LUAL_PACKPADBYTE 0x00
#endif #endif
/* maximum size for the binary representation of an integer */ /* maximum size for the binary representation of an integer */
@ -1308,7 +1339,7 @@ static int str_pack (lua_State *L) {
KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign); KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign);
totalsize += ntoalign + size; totalsize += ntoalign + size;
while (ntoalign-- > 0) while (ntoalign-- > 0)
luaL_addchar(&b, LUA_PACKPADBYTE); /* fill alignment */ luaL_addchar(&b, LUAL_PACKPADBYTE); /* fill alignment */
arg++; arg++;
switch (opt) { switch (opt) {
case Kint: { /* signed integers */ case Kint: { /* signed integers */
@ -1343,13 +1374,11 @@ static int str_pack (lua_State *L) {
case Kchar: { /* fixed-size string */ case Kchar: { /* fixed-size string */
size_t len; size_t len;
const char *s = luaL_checklstring(L, arg, &len); const char *s = luaL_checklstring(L, arg, &len);
if ((size_t)size <= len) /* string larger than (or equal to) needed? */ luaL_argcheck(L, len <= (size_t)size, arg,
luaL_addlstring(&b, s, size); /* truncate string to asked size */ "string longer than given size");
else { /* string smaller than needed */ luaL_addlstring(&b, s, len); /* add string */
luaL_addlstring(&b, s, len); /* add it all */ while (len++ < (size_t)size) /* pad extra space */
while (len++ < (size_t)size) /* pad extra space */ luaL_addchar(&b, LUAL_PACKPADBYTE);
luaL_addchar(&b, LUA_PACKPADBYTE);
}
break; break;
} }
case Kstring: { /* strings with length count */ case Kstring: { /* strings with length count */
@ -1372,7 +1401,7 @@ static int str_pack (lua_State *L) {
totalsize += len + 1; totalsize += len + 1;
break; break;
} }
case Kpadding: luaL_addchar(&b, LUA_PACKPADBYTE); /* FALLTHROUGH */ case Kpadding: luaL_addchar(&b, LUAL_PACKPADBYTE); /* FALLTHROUGH */
case Kpaddalign: case Knop: case Kpaddalign: case Knop:
arg--; /* undo increment */ arg--; /* undo increment */
break; break;

View File

@ -1,5 +1,5 @@
/* /*
** $Id: ltablib.c,v 1.90 2015/11/25 12:48:57 roberto Exp $ ** $Id: ltablib.c,v 1.93 2016/02/25 19:41:54 roberto Exp $
** Library for Table Manipulation ** Library for Table Manipulation
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -53,7 +53,7 @@ static void checktab (lua_State *L, int arg, int what) {
lua_pop(L, n); /* pop metatable and tested metamethods */ lua_pop(L, n); /* pop metatable and tested metamethods */
} }
else else
luaL_argerror(L, arg, "table expected"); /* force an error */ luaL_checktype(L, arg, LUA_TTABLE); /* force an error */
} }
} }
@ -139,7 +139,7 @@ static int tmove (lua_State *L) {
n = e - f + 1; /* number of elements to move */ n = e - f + 1; /* number of elements to move */
luaL_argcheck(L, t <= LUA_MAXINTEGER - n + 1, 4, luaL_argcheck(L, t <= LUA_MAXINTEGER - n + 1, 4,
"destination wrap around"); "destination wrap around");
if (t > e || t <= f || tt != 1) { if (t > e || t <= f || (tt != 1 && !lua_compare(L, 1, tt, LUA_OPEQ))) {
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
lua_geti(L, 1, f + i); lua_geti(L, 1, f + i);
lua_seti(L, tt, t + i); lua_seti(L, tt, t + i);
@ -152,7 +152,7 @@ static int tmove (lua_State *L) {
} }
} }
} }
lua_pushvalue(L, tt); /* return "to table" */ lua_pushvalue(L, tt); /* return destination table */
return 1; return 1;
} }
@ -172,7 +172,7 @@ static int tconcat (lua_State *L) {
size_t lsep; size_t lsep;
const char *sep = luaL_optlstring(L, 2, "", &lsep); const char *sep = luaL_optlstring(L, 2, "", &lsep);
lua_Integer i = luaL_optinteger(L, 3, 1); lua_Integer i = luaL_optinteger(L, 3, 1);
last = luaL_opt(L, luaL_checkinteger, 4, last); last = luaL_optinteger(L, 4, last);
luaL_buffinit(L, &b); luaL_buffinit(L, &b);
for (; i < last; i++) { for (; i < last; i++) {
addfield(L, &b, i); addfield(L, &b, i);
@ -232,6 +232,10 @@ static int unpack (lua_State *L) {
*/ */
/* type for array indices */
typedef unsigned int IdxT;
/* /*
** Produce a "random" 'unsigned int' to randomize pivot choice. This ** Produce a "random" 'unsigned int' to randomize pivot choice. This
** macro is used only when 'sort' detects a big imbalance in the result ** macro is used only when 'sort' detects a big imbalance in the result
@ -270,7 +274,7 @@ static unsigned int l_randomizePivot (void) {
#define RANLIMIT 100u #define RANLIMIT 100u
static void set2 (lua_State *L, unsigned int i, unsigned int j) { static void set2 (lua_State *L, IdxT i, IdxT j) {
lua_seti(L, 1, i); lua_seti(L, 1, i);
lua_seti(L, 1, j); lua_seti(L, 1, j);
} }
@ -303,10 +307,9 @@ static int sort_comp (lua_State *L, int a, int b) {
** Pos-condition: a[lo .. i - 1] <= a[i] == P <= a[i + 1 .. up] ** Pos-condition: a[lo .. i - 1] <= a[i] == P <= a[i + 1 .. up]
** returns 'i'. ** returns 'i'.
*/ */
static unsigned int partition (lua_State *L, unsigned int lo, static IdxT partition (lua_State *L, IdxT lo, IdxT up) {
unsigned int up) { IdxT i = lo; /* will be incremented before first use */
unsigned int i = lo; /* will be incremented before first use */ IdxT j = up - 1; /* will be decremented before first use */
unsigned int j = up - 1; /* will be decremented before first use */
/* loop invariant: a[lo .. i] <= P <= a[j .. up] */ /* loop invariant: a[lo .. i] <= P <= a[j .. up] */
for (;;) { for (;;) {
/* next loop: repeat ++i while a[i] < P */ /* next loop: repeat ++i while a[i] < P */
@ -340,10 +343,9 @@ static unsigned int partition (lua_State *L, unsigned int lo,
** Choose an element in the middle (2nd-3th quarters) of [lo,up] ** Choose an element in the middle (2nd-3th quarters) of [lo,up]
** "randomized" by 'rnd' ** "randomized" by 'rnd'
*/ */
static unsigned int choosePivot (unsigned int lo, unsigned int up, static IdxT choosePivot (IdxT lo, IdxT up, unsigned int rnd) {
unsigned int rnd) { IdxT r4 = (up - lo) / 4; /* range/4 */
unsigned int r4 = (unsigned int)(up - lo) / 4u; /* range/4 */ IdxT p = rnd % (r4 * 2) + (lo + r4);
unsigned int p = rnd % (r4 * 2) + (lo + r4);
lua_assert(lo + r4 <= p && p <= up - r4); lua_assert(lo + r4 <= p && p <= up - r4);
return p; return p;
} }
@ -352,11 +354,11 @@ static unsigned int choosePivot (unsigned int lo, unsigned int up,
/* /*
** QuickSort algorithm (recursive function) ** QuickSort algorithm (recursive function)
*/ */
static void auxsort (lua_State *L, unsigned int lo, unsigned int up, static void auxsort (lua_State *L, IdxT lo, IdxT up,
unsigned int rnd) { unsigned int rnd) {
while (lo < up) { /* loop for tail recursion */ while (lo < up) { /* loop for tail recursion */
unsigned int p; /* Pivot index */ IdxT p; /* Pivot index */
unsigned int n; /* to be used later */ IdxT n; /* to be used later */
/* sort elements 'lo', 'p', and 'up' */ /* sort elements 'lo', 'p', and 'up' */
lua_geti(L, 1, lo); lua_geti(L, 1, lo);
lua_geti(L, 1, up); lua_geti(L, 1, up);
@ -400,7 +402,7 @@ static void auxsort (lua_State *L, unsigned int lo, unsigned int up,
n = up - p; /* size of smaller interval */ n = up - p; /* size of smaller interval */
up = p - 1; /* tail call for [lo .. p - 1] (lower interval) */ up = p - 1; /* tail call for [lo .. p - 1] (lower interval) */
} }
if ((up - lo) / 128u > n) /* partition too imbalanced? */ if ((up - lo) / 128 > n) /* partition too imbalanced? */
rnd = l_randomizePivot(); /* try a new randomization */ rnd = l_randomizePivot(); /* try a new randomization */
} /* tail call auxsort(L, lo, up, rnd) */ } /* tail call auxsort(L, lo, up, rnd) */
} }
@ -410,11 +412,10 @@ static int sort (lua_State *L) {
lua_Integer n = aux_getn(L, 1, TAB_RW); lua_Integer n = aux_getn(L, 1, TAB_RW);
if (n > 1) { /* non-trivial interval? */ if (n > 1) { /* non-trivial interval? */
luaL_argcheck(L, n < INT_MAX, 1, "array too big"); luaL_argcheck(L, n < INT_MAX, 1, "array too big");
luaL_checkstack(L, 40, ""); /* assume array is smaller than 2^40 */
if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */ if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */
luaL_checktype(L, 2, LUA_TFUNCTION); /* must be a function */ luaL_checktype(L, 2, LUA_TFUNCTION); /* must be a function */
lua_settop(L, 2); /* make sure there are two arguments */ lua_settop(L, 2); /* make sure there are two arguments */
auxsort(L, 1, (unsigned int)n, 0u); auxsort(L, 1, (IdxT)n, 0);
} }
return 0; return 0;
} }

View File

@ -1,5 +1,5 @@
/* /*
** $Id: ltm.c,v 2.36 2015/11/03 15:47:30 roberto Exp $ ** $Id: ltm.c,v 2.37 2016/02/26 19:20:15 roberto Exp $
** Tag methods ** Tag methods
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -83,6 +83,22 @@ const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) {
} }
/*
** Return the name of the type of an object. For tables and userdata
** with metatable, use their '__name' metafield, if present.
*/
const char *luaT_objtypename (lua_State *L, const TValue *o) {
Table *mt;
if ((ttistable(o) && (mt = hvalue(o)->metatable) != NULL) ||
(ttisfulluserdata(o) && (mt = uvalue(o)->metatable) != NULL)) {
const TValue *name = luaH_getshortstr(mt, luaS_new(L, "__name"));
if (ttisstring(name)) /* is '__name' a string? */
return getstr(tsvalue(name)); /* use it as type name */
}
return ttypename(ttnov(o)); /* else use standard type name */
}
void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1,
const TValue *p2, TValue *p3, int hasres) { const TValue *p2, TValue *p3, int hasres) {
ptrdiff_t result = savestack(L, p3); ptrdiff_t result = savestack(L, p3);

View File

@ -1,5 +1,5 @@
/* /*
** $Id: ltm.h,v 2.21 2014/10/25 11:50:46 roberto Exp $ ** $Id: ltm.h,v 2.22 2016/02/26 19:20:15 roberto Exp $
** Tag methods ** Tag methods
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -51,11 +51,12 @@ typedef enum {
#define fasttm(l,et,e) gfasttm(G(l), et, e) #define fasttm(l,et,e) gfasttm(G(l), et, e)
#define ttypename(x) luaT_typenames_[(x) + 1] #define ttypename(x) luaT_typenames_[(x) + 1]
#define objtypename(x) ttypename(ttnov(x))
LUAI_DDEC const char *const luaT_typenames_[LUA_TOTALTAGS]; LUAI_DDEC const char *const luaT_typenames_[LUA_TOTALTAGS];
LUAI_FUNC const char *luaT_objtypename (lua_State *L, const TValue *o);
LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename); LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename);
LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o,
TMS event); TMS event);

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lua.h,v 1.329 2015/11/13 17:18:42 roberto Exp $ ** $Id: lua.h,v 1.331 2016/05/30 15:53:28 roberto Exp $
** Lua - A Scripting Language ** Lua - A Scripting Language
** Lua.org, PUC-Rio, Brazil (http://www.lua.org) ** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
** See Copyright Notice at the end of this file ** See Copyright Notice at the end of this file
@ -19,11 +19,11 @@
#define LUA_VERSION_MAJOR "5" #define LUA_VERSION_MAJOR "5"
#define LUA_VERSION_MINOR "3" #define LUA_VERSION_MINOR "3"
#define LUA_VERSION_NUM 503 #define LUA_VERSION_NUM 503
#define LUA_VERSION_RELEASE "2" #define LUA_VERSION_RELEASE "3"
#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-2015 Lua.org, PUC-Rio" #define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2016 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"
@ -361,7 +361,7 @@ LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud);
#define lua_pushliteral(L, s) lua_pushstring(L, "" s) #define lua_pushliteral(L, s) lua_pushstring(L, "" s)
#define lua_pushglobaltable(L) \ #define lua_pushglobaltable(L) \
lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS) ((void)lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS))
#define lua_tostring(L,i) lua_tolstring(L, (i), NULL) #define lua_tostring(L,i) lua_tolstring(L, (i), NULL)
@ -460,7 +460,7 @@ struct lua_Debug {
/****************************************************************************** /******************************************************************************
* Copyright (C) 1994-2015 Lua.org, PUC-Rio. * Copyright (C) 1994-2016 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

View File

@ -1,5 +1,5 @@
/* /*
** $Id: luaconf.h,v 1.254 2015/10/21 18:17:40 roberto Exp $ ** $Id: luaconf.h,v 1.255 2016/05/01 20:06:09 roberto Exp $
** Configuration file for Lua ** Configuration file for Lua
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -612,7 +612,7 @@
** provide its own implementation. ** provide its own implementation.
*/ */
#if !defined(LUA_USE_C89) #if !defined(LUA_USE_C89)
#define lua_number2strx(L,b,sz,f,n) l_sprintf(b,sz,f,n) #define lua_number2strx(L,b,sz,f,n) ((void)L, l_sprintf(b,sz,f,n))
#endif #endif

105
3rdparty/lua/src/lvm.c vendored
View File

@ -1,5 +1,5 @@
/* /*
** $Id: lvm.c,v 2.265 2015/11/23 11:30:45 roberto Exp $ ** $Id: lvm.c,v 2.268 2016/02/05 19:59:14 roberto Exp $
** Lua virtual machine ** Lua virtual machine
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -153,55 +153,69 @@ static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step,
/* /*
** Complete a table access: if 't' is a table, 'tm' has its metamethod; ** Finish the table access 'val = t[key]'.
** otherwise, 'tm' is NULL. ** if 'slot' is NULL, 't' is not a table; otherwise, 'slot' points to
** t[k] entry (which must be nil).
*/ */
void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val, void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val,
const TValue *tm) { const TValue *slot) {
int loop; /* counter to avoid infinite loops */ int loop; /* counter to avoid infinite loops */
lua_assert(tm != NULL || !ttistable(t)); const TValue *tm; /* metamethod */
for (loop = 0; loop < MAXTAGLOOP; loop++) { for (loop = 0; loop < MAXTAGLOOP; loop++) {
if (tm == NULL) { /* no metamethod (from a table)? */ if (slot == NULL) { /* 't' is not a table? */
if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) lua_assert(!ttistable(t));
tm = luaT_gettmbyobj(L, t, TM_INDEX);
if (ttisnil(tm))
luaG_typeerror(L, t, "index"); /* no metamethod */ luaG_typeerror(L, t, "index"); /* no metamethod */
/* else will try the metamethod */
} }
if (ttisfunction(tm)) { /* metamethod is a function */ else { /* 't' is a table */
lua_assert(ttisnil(slot));
tm = fasttm(L, hvalue(t)->metatable, TM_INDEX); /* table's metamethod */
if (tm == NULL) { /* no metamethod? */
setnilvalue(val); /* result is nil */
return;
}
/* else will try the metamethod */
}
if (ttisfunction(tm)) { /* is metamethod a function? */
luaT_callTM(L, tm, t, key, val, 1); /* call it */ luaT_callTM(L, tm, t, key, val, 1); /* call it */
return; return;
} }
t = tm; /* else repeat access over 'tm' */ t = tm; /* else try to access 'tm[key]' */
if (luaV_fastget(L,t,key,tm,luaH_get)) { /* try fast track */ if (luaV_fastget(L,t,key,slot,luaH_get)) { /* fast track? */
setobj2s(L, val, tm); /* done */ setobj2s(L, val, slot); /* done */
return; return;
} }
/* else repeat */ /* else repeat (tail call 'luaV_finishget') */
} }
luaG_runerror(L, "gettable chain too long; possible loop"); luaG_runerror(L, "'__index' chain too long; possible loop");
} }
/* /*
** Main function for table assignment (invoking metamethods if needed). ** Finish a table assignment 't[key] = val'.
** Compute 't[key] = val' ** If 'slot' is NULL, 't' is not a table. Otherwise, 'slot' points
** to the entry 't[key]', or to 'luaO_nilobject' if there is no such
** entry. (The value at 'slot' must be nil, otherwise 'luaV_fastset'
** would have done the job.)
*/ */
void luaV_finishset (lua_State *L, const TValue *t, TValue *key, void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
StkId val, const TValue *oldval) { StkId val, const TValue *slot) {
int loop; /* counter to avoid infinite loops */ int loop; /* counter to avoid infinite loops */
for (loop = 0; loop < MAXTAGLOOP; loop++) { for (loop = 0; loop < MAXTAGLOOP; loop++) {
const TValue *tm; const TValue *tm; /* '__newindex' metamethod */
if (oldval != NULL) { if (slot != NULL) { /* is 't' a table? */
lua_assert(ttistable(t) && ttisnil(oldval)); Table *h = hvalue(t); /* save 't' table */
/* must check the metamethod */ lua_assert(ttisnil(slot)); /* old value must be nil */
if ((tm = fasttm(L, hvalue(t)->metatable, TM_NEWINDEX)) == NULL && tm = fasttm(L, h->metatable, TM_NEWINDEX); /* get metamethod */
/* no metamethod; is there a previous entry in the table? */ if (tm == NULL) { /* no metamethod? */
(oldval != luaO_nilobject || if (slot == luaO_nilobject) /* no previous entry? */
/* no previous entry; must create one. (The next test is slot = luaH_newkey(L, h, key); /* create one */
always true; we only need the assignment.) */
(oldval = luaH_newkey(L, hvalue(t), key), 1))) {
/* no metamethod and (now) there is an entry with given key */ /* no metamethod and (now) there is an entry with given key */
setobj2t(L, cast(TValue *, oldval), val); setobj2t(L, cast(TValue *, slot), val); /* set its new value */
invalidateTMcache(hvalue(t)); invalidateTMcache(h);
luaC_barrierback(L, hvalue(t), val); luaC_barrierback(L, h, val);
return; return;
} }
/* else will try the metamethod */ /* else will try the metamethod */
@ -216,11 +230,11 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
return; return;
} }
t = tm; /* else repeat assignment over 'tm' */ t = tm; /* else repeat assignment over 'tm' */
if (luaV_fastset(L, t, key, oldval, luaH_get, val)) if (luaV_fastset(L, t, key, slot, luaH_get, val))
return; /* done */ return; /* done */
/* else loop */ /* else loop */
} }
luaG_runerror(L, "settable chain too long; possible loop"); luaG_runerror(L, "'__newindex' chain too long; possible loop");
} }
@ -738,18 +752,28 @@ void luaV_finishOp (lua_State *L) {
luai_threadyield(L); } luai_threadyield(L); }
/* fetch an instruction and prepare its execution */
#define vmfetch() { \
i = *(ci->u.l.savedpc++); \
if (L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) \
Protect(luaG_traceexec(L)); \
ra = RA(i); /* WARNING: any stack reallocation invalidates 'ra' */ \
lua_assert(base == ci->u.l.base); \
lua_assert(base <= L->top && L->top < L->stack + L->stacksize); \
}
#define vmdispatch(o) switch(o) #define vmdispatch(o) switch(o)
#define vmcase(l) case l: #define vmcase(l) case l:
#define vmbreak break #define vmbreak break
/* /*
** copy of 'luaV_gettable', but protecting call to potential metamethod ** copy of 'luaV_gettable', but protecting the call to potential
** (which can reallocate the stack) ** metamethod (which can reallocate the stack)
*/ */
#define gettableProtected(L,t,k,v) { const TValue *aux; \ #define gettableProtected(L,t,k,v) { const TValue *slot; \
if (luaV_fastget(L,t,k,aux,luaH_get)) { setobj2s(L, v, aux); } \ if (luaV_fastget(L,t,k,slot,luaH_get)) { setobj2s(L, v, slot); } \
else Protect(luaV_finishget(L,t,k,v,aux)); } else Protect(luaV_finishget(L,t,k,v,slot)); }
/* same for 'luaV_settable' */ /* same for 'luaV_settable' */
@ -772,14 +796,9 @@ void luaV_execute (lua_State *L) {
base = ci->u.l.base; /* local copy of function's base */ base = ci->u.l.base; /* local copy of function's base */
/* main loop of interpreter */ /* main loop of interpreter */
for (;;) { for (;;) {
Instruction i = *(ci->u.l.savedpc++); Instruction i;
StkId ra; StkId ra;
if (L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) vmfetch();
Protect(luaG_traceexec(L));
/* WARNING: several calls may realloc the stack and invalidate 'ra' */
ra = RA(i);
lua_assert(base == ci->u.l.base);
lua_assert(base <= L->top && L->top < L->stack + L->stacksize);
vmdispatch (GET_OPCODE(i)) { vmdispatch (GET_OPCODE(i)) {
vmcase(OP_MOVE) { vmcase(OP_MOVE) {
setobjs2s(L, ra, RB(i)); setobjs2s(L, ra, RB(i));

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lvm.h,v 2.39 2015/09/09 13:44:07 roberto Exp $ ** $Id: lvm.h,v 2.40 2016/01/05 16:07:21 roberto Exp $
** Lua virtual machine ** Lua virtual machine
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -49,25 +49,24 @@
/* /*
** fast track for 'gettable': 1 means 'aux' points to resulted value; ** fast track for 'gettable': if 't' is a table and 't[k]' is not nil,
** 0 means 'aux' is metamethod (if 't' is a table) or NULL. 'f' is ** return 1 with 'slot' pointing to 't[k]' (final result). Otherwise,
** the raw get function to use. ** return 0 (meaning it will have to check metamethod) with 'slot'
** pointing to a nil 't[k]' (if 't' is a table) or NULL (otherwise).
** 'f' is the raw get function to use.
*/ */
#define luaV_fastget(L,t,k,aux,f) \ #define luaV_fastget(L,t,k,slot,f) \
(!ttistable(t) \ (!ttistable(t) \
? (aux = NULL, 0) /* not a table; 'aux' is NULL and result is 0 */ \ ? (slot = NULL, 0) /* not a table; 'slot' is NULL and result is 0 */ \
: (aux = f(hvalue(t), k), /* else, do raw access */ \ : (slot = f(hvalue(t), k), /* else, do raw access */ \
!ttisnil(aux) ? 1 /* result not nil? 'aux' has it */ \ !ttisnil(slot))) /* result not nil? */
: (aux = fasttm(L, hvalue(t)->metatable, TM_INDEX), /* get metamethod */\
aux != NULL ? 0 /* has metamethod? must call it */ \
: (aux = luaO_nilobject, 1)))) /* else, final result is nil */
/* /*
** standard implementation for 'gettable' ** standard implementation for 'gettable'
*/ */
#define luaV_gettable(L,t,k,v) { const TValue *aux; \ #define luaV_gettable(L,t,k,v) { const TValue *slot; \
if (luaV_fastget(L,t,k,aux,luaH_get)) { setobj2s(L, v, aux); } \ if (luaV_fastget(L,t,k,slot,luaH_get)) { setobj2s(L, v, slot); } \
else luaV_finishget(L,t,k,v,aux); } else luaV_finishget(L,t,k,v,slot); }
/* /*
@ -100,9 +99,9 @@ LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r);
LUAI_FUNC int luaV_tonumber_ (const TValue *obj, lua_Number *n); LUAI_FUNC int luaV_tonumber_ (const TValue *obj, lua_Number *n);
LUAI_FUNC int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode); LUAI_FUNC int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode);
LUAI_FUNC void luaV_finishget (lua_State *L, const TValue *t, TValue *key, LUAI_FUNC void luaV_finishget (lua_State *L, const TValue *t, TValue *key,
StkId val, const TValue *tm); StkId val, const TValue *slot);
LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key, LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
StkId val, const TValue *oldval); StkId val, const TValue *slot);
LUAI_FUNC void luaV_finishOp (lua_State *L); LUAI_FUNC void luaV_finishOp (lua_State *L);
LUAI_FUNC void luaV_execute (lua_State *L); LUAI_FUNC void luaV_execute (lua_State *L);
LUAI_FUNC void luaV_concat (lua_State *L, int total); LUAI_FUNC void luaV_concat (lua_State *L, int total);