summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLua Team <team@lua.org>2014-06-19 12:00:00 +0000
committerrepogen <>2014-06-19 12:00:00 +0000
commit3907bda05b0e73eba86487ad703e832ca14b64ce (patch)
treede1e8d9b34ad2fc2241dc971f27ee4158df5dbd0
parent05a6ab2dd30e7707c7d5424b905eb93a1dd5c5b2 (diff)
downloadlua-github-3907bda05b0e73eba86487ad703e832ca14b64ce.tar.gz
Lua 5.3.0-work35.3.0-work3
-rw-r--r--README2
-rw-r--r--doc/contents.html33
-rw-r--r--doc/manual.html954
-rw-r--r--doc/readme.html35
-rw-r--r--src/.fix2
-rw-r--r--src/Makefile4
-rw-r--r--src/lapi.c100
-rw-r--r--src/lauxlib.c17
-rw-r--r--src/lauxlib.h4
-rw-r--r--src/lbaselib.c92
-rw-r--r--src/lbitlib.c5
-rw-r--r--src/lcode.c21
-rw-r--r--src/lcorolib.c22
-rw-r--r--src/ldblib.c187
-rw-r--r--src/ldo.c106
-rw-r--r--src/ldump.c27
-rw-r--r--src/lfunc.c23
-rw-r--r--src/lfunc.h6
-rw-r--r--src/lgc.c146
-rw-r--r--src/linit.c8
-rw-r--r--src/liolib.c113
-rw-r--r--src/llex.c122
-rw-r--r--src/llimits.h33
-rw-r--r--src/lmathlib.c281
-rw-r--r--src/lobject.c54
-rw-r--r--src/lobject.h84
-rw-r--r--src/loslib.c10
-rw-r--r--src/lparser.c10
-rw-r--r--src/lparser.h6
-rw-r--r--src/lstate.h28
-rw-r--r--src/lstring.c12
-rw-r--r--src/lstrlib.c101
-rw-r--r--src/ltable.c48
-rw-r--r--src/ltablib.c55
-rw-r--r--src/ltm.c21
-rw-r--r--src/ltm.h3
-rw-r--r--src/lua.c376
-rw-r--r--src/lua.h39
-rw-r--r--src/luac.c23
-rw-r--r--src/luaconf.h172
-rw-r--r--src/lundump.c46
-rw-r--r--src/lundump.h8
-rw-r--r--src/lutf8lib.c87
-rw-r--r--src/lvm.c378
-rw-r--r--src/lvm.h9
45 files changed, 2323 insertions, 1590 deletions
diff --git a/README b/README
index 2d5ee2c9..1e7fa3ac 100644
--- a/README
+++ b/README
@@ -1,5 +1,5 @@
-This is Lua 5.3.0 (work2), released on 21 Mar 2014.
+This is Lua 5.3.0 (work3), released on 19 Jul 2014.
For installation instructions, license details, and
further information about Lua, see doc/readme.html.
diff --git a/doc/contents.html b/doc/contents.html
index f157545d..af3142b5 100644
--- a/doc/contents.html
+++ b/doc/contents.html
@@ -174,6 +174,7 @@ Freely available under the terms of the
<P>
<A HREF="manual.html#pdf-coroutine.create">coroutine.create</A><BR>
+<A HREF="manual.html#pdf-coroutine.isyieldable">coroutine.isyieldable</A><BR>
<A HREF="manual.html#pdf-coroutine.resume">coroutine.resume</A><BR>
<A HREF="manual.html#pdf-coroutine.running">coroutine.running</A><BR>
<A HREF="manual.html#pdf-coroutine.status">coroutine.status</A><BR>
@@ -182,6 +183,7 @@ Freely available under the terms of the
<P>
<A HREF="manual.html#pdf-debug.debug">debug.debug</A><BR>
+<A HREF="manual.html#pdf-debug.Csize">debug.Csize</A><BR>
<A HREF="manual.html#pdf-debug.gethook">debug.gethook</A><BR>
<A HREF="manual.html#pdf-debug.getinfo">debug.getinfo</A><BR>
<A HREF="manual.html#pdf-debug.getlocal">debug.getlocal</A><BR>
@@ -189,7 +191,6 @@ Freely available under the terms of the
<A HREF="manual.html#pdf-debug.getregistry">debug.getregistry</A><BR>
<A HREF="manual.html#pdf-debug.getupvalue">debug.getupvalue</A><BR>
<A HREF="manual.html#pdf-debug.getuservalue">debug.getuservalue</A><BR>
-<A HREF="manual.html#pdf-debug.numbits">debug.numbits</A><BR>
<A HREF="manual.html#pdf-debug.sethook">debug.sethook</A><BR>
<A HREF="manual.html#pdf-debug.setlocal">debug.setlocal</A><BR>
<A HREF="manual.html#pdf-debug.setmetatable">debug.setmetatable</A><BR>
@@ -228,40 +229,33 @@ Freely available under the terms of the
<TD>
<H3>&nbsp;</H3>
<P>
+<A HREF="manual.html#pdf-math">math</A><BR>
<A HREF="manual.html#pdf-math.abs">math.abs</A><BR>
<A HREF="manual.html#pdf-math.acos">math.acos</A><BR>
<A HREF="manual.html#pdf-math.asin">math.asin</A><BR>
<A HREF="manual.html#pdf-math.atan">math.atan</A><BR>
-<A HREF="manual.html#pdf-math.atan2">math.atan2</A><BR>
<A HREF="manual.html#pdf-math.ceil">math.ceil</A><BR>
<A HREF="manual.html#pdf-math.cos">math.cos</A><BR>
-<A HREF="manual.html#pdf-math.cosh">math.cosh</A><BR>
<A HREF="manual.html#pdf-math.deg">math.deg</A><BR>
-<A HREF="manual.html#pdf-math.exp">math.exp</A><BR>
<A HREF="manual.html#pdf-math.floor">math.floor</A><BR>
<A HREF="manual.html#pdf-math.fmod">math.fmod</A><BR>
-<A HREF="manual.html#pdf-math.frexp">math.frexp</A><BR>
<A HREF="manual.html#pdf-math.huge">math.huge</A><BR>
<A HREF="manual.html#pdf-math.ifloor">math.ifloor</A><BR>
-<A HREF="manual.html#pdf-math.isfloat">math.isfloat</A><BR>
-<A HREF="manual.html#pdf-math.ldexp">math.ldexp</A><BR>
<A HREF="manual.html#pdf-math.log">math.log</A><BR>
<A HREF="manual.html#pdf-math.max">math.max</A><BR>
+<A HREF="manual.html#pdf-math.maxinteger">math.maxinteger</A><BR>
<A HREF="manual.html#pdf-math.min">math.min</A><BR>
+<A HREF="manual.html#pdf-math.mininteger">math.mininteger</A><BR>
<A HREF="manual.html#pdf-math.modf">math.modf</A><BR>
<A HREF="manual.html#pdf-math.pi">math.pi</A><BR>
-<A HREF="manual.html#pdf-math.pow">math.pow</A><BR>
<A HREF="manual.html#pdf-math.rad">math.rad</A><BR>
<A HREF="manual.html#pdf-math.random">math.random</A><BR>
<A HREF="manual.html#pdf-math.randomseed">math.randomseed</A><BR>
<A HREF="manual.html#pdf-math.sin">math.sin</A><BR>
-<A HREF="manual.html#pdf-math.sinh">math.sinh</A><BR>
<A HREF="manual.html#pdf-math.sqrt">math.sqrt</A><BR>
<A HREF="manual.html#pdf-math.tan">math.tan</A><BR>
-<A HREF="manual.html#pdf-math.tanh">math.tanh</A><BR>
<A HREF="manual.html#pdf-math.type">math.type</A><BR>
-
<P>
<A HREF="manual.html#pdf-os.clock">os.clock</A><BR>
<A HREF="manual.html#pdf-os.date">os.date</A><BR>
@@ -289,6 +283,8 @@ Freely available under the terms of the
<A HREF="manual.html#pdf-string.byte">string.byte</A><BR>
<A HREF="manual.html#pdf-string.char">string.char</A><BR>
<A HREF="manual.html#pdf-string.dump">string.dump</A><BR>
+<A HREF="manual.html#pdf-string.dumpfloat">string.dumpfloat</A><BR>
+<A HREF="manual.html#pdf-string.dumpint">string.dumpint</A><BR>
<A HREF="manual.html#pdf-string.find">string.find</A><BR>
<A HREF="manual.html#pdf-string.format">string.format</A><BR>
<A HREF="manual.html#pdf-string.gmatch">string.gmatch</A><BR>
@@ -296,13 +292,11 @@ Freely available under the terms of the
<A HREF="manual.html#pdf-string.len">string.len</A><BR>
<A HREF="manual.html#pdf-string.lower">string.lower</A><BR>
<A HREF="manual.html#pdf-string.match">string.match</A><BR>
-<A HREF="manual.html#pdf-string.packfloat">string.packfloat</A><BR>
-<A HREF="manual.html#pdf-string.packint">string.packint</A><BR>
<A HREF="manual.html#pdf-string.rep">string.rep</A><BR>
<A HREF="manual.html#pdf-string.reverse">string.reverse</A><BR>
<A HREF="manual.html#pdf-string.sub">string.sub</A><BR>
-<A HREF="manual.html#pdf-string.unpackfloat">string.unpackfloat</A><BR>
-<A HREF="manual.html#pdf-string.unpackint">string.unpackint</A><BR>
+<A HREF="manual.html#pdf-string.undumpfloat">string.undumpfloat</A><BR>
+<A HREF="manual.html#pdf-string.undumpint">string.undumpint</A><BR>
<A HREF="manual.html#pdf-string.upper">string.upper</A><BR>
<P>
@@ -330,6 +324,7 @@ Freely available under the terms of the
<A HREF="manual.html#lua_Debug">lua_Debug</A><BR>
<A HREF="manual.html#lua_Hook">lua_Hook</A><BR>
<A HREF="manual.html#lua_Integer">lua_Integer</A><BR>
+<A HREF="manual.html#lua_KFunction">lua_KFunction</A><BR>
<A HREF="manual.html#lua_Number">lua_Number</A><BR>
<A HREF="manual.html#lua_Reader">lua_Reader</A><BR>
<A HREF="manual.html#lua_State">lua_State</A><BR>
@@ -352,7 +347,6 @@ Freely available under the terms of the
<A HREF="manual.html#lua_error">lua_error</A><BR>
<A HREF="manual.html#lua_gc">lua_gc</A><BR>
<A HREF="manual.html#lua_getallocf">lua_getallocf</A><BR>
-<A HREF="manual.html#lua_getctx">lua_getctx</A><BR>
<A HREF="manual.html#lua_getfield">lua_getfield</A><BR>
<A HREF="manual.html#lua_getglobal">lua_getglobal</A><BR>
<A HREF="manual.html#lua_gethook">lua_gethook</A><BR>
@@ -380,6 +374,7 @@ Freely available under the terms of the
<A HREF="manual.html#lua_istable">lua_istable</A><BR>
<A HREF="manual.html#lua_isthread">lua_isthread</A><BR>
<A HREF="manual.html#lua_isuserdata">lua_isuserdata</A><BR>
+<A HREF="manual.html#lua_isyieldable">lua_isyieldable</A><BR>
<A HREF="manual.html#lua_len">lua_len</A><BR>
<A HREF="manual.html#lua_load">lua_load</A><BR>
<A HREF="manual.html#lua_newstate">lua_newstate</A><BR>
@@ -387,6 +382,7 @@ Freely available under the terms of the
<A HREF="manual.html#lua_newthread">lua_newthread</A><BR>
<A HREF="manual.html#lua_newuserdata">lua_newuserdata</A><BR>
<A HREF="manual.html#lua_next">lua_next</A><BR>
+<A HREF="manual.html#lua_numtointeger">lua_numtointeger</A><BR>
<A HREF="manual.html#lua_pcall">lua_pcall</A><BR>
<A HREF="manual.html#lua_pcallk">lua_pcallk</A><BR>
<A HREF="manual.html#lua_pop">lua_pop</A><BR>
@@ -418,6 +414,7 @@ Freely available under the terms of the
<A HREF="manual.html#lua_remove">lua_remove</A><BR>
<A HREF="manual.html#lua_replace">lua_replace</A><BR>
<A HREF="manual.html#lua_resume">lua_resume</A><BR>
+<A HREF="manual.html#lua_rotate">lua_rotate</A><BR>
<A HREF="manual.html#lua_setallocf">lua_setallocf</A><BR>
<A HREF="manual.html#lua_setfield">lua_setfield</A><BR>
<A HREF="manual.html#lua_setglobal">lua_setglobal</A><BR>
@@ -534,10 +531,10 @@ Freely available under the terms of the
<HR>
<SMALL CLASS="footer">
Last update:
-Fri Mar 21 17:34:12 BRT 2014
+Thu Jun 19 17:09:46 BRT 2014
</SMALL>
<!--
-Last change: updated for Lua 5.3.0 (work2)
+Last change: updated for Lua 5.3.0 (work3)
-->
</BODY>
diff --git a/doc/manual.html b/doc/manual.html
index aa1afa28..de2dc5f6 100644
--- a/doc/manual.html
+++ b/doc/manual.html
@@ -38,7 +38,7 @@ Freely available under the terms of the
<!-- ====================================================================== -->
<p>
-<!-- $Id: manual.of,v 1.114 2014/03/21 18:32:52 roberto Exp $ -->
+<!-- $Id: manual.of,v 1.121 2014/06/18 19:12:23 roberto Exp $ -->
@@ -139,9 +139,9 @@ one called <em>integer</em> and the other called <em>float</em>.
Lua has explicit rules about when each representation is used,
but it also converts between them automatically as needed (see <a href="#3.4.3">&sect;3.4.3</a>).
Therefore,
-the programmer has the option of mostly ignore the difference
+the programmer has the option of mostly ignoring the difference
between integers and floats
-or assume complete control about the representation of each value.
+or assuming complete control over the representation of each value.
Standard Lua uses 64-bit integers and double-precision (64-bit) floats,
but you can also compile Lua so that it
uses 32-bit integers and/or single-precision (32-bit) floats.
@@ -437,7 +437,7 @@ with the following code:
</pre>
<p>
-For the unary minus and the bitwise not operators,
+For the unary operators (negation, length, and bitwise not),
the metamethod is computed and called with a dummy second operand,
equal to the first one.
This extra operand is only to simplify Lua's internals
@@ -575,9 +575,9 @@ Otherwise, Lua raises an error.
<li><b>"eq": </b>
the <code>==</code> (equal) operation.
-Lua will try a metamethod only when the values
-being compared are both either tables or full userdata,
-both have the same metamethod,
+Behavior similar to the "add" operation,
+except that Lua will try a metamethod only when the values
+being compared are either both tables or both full userdata
and they are not primitively equal.
The result of the call is always converted to a boolean.
</li>
@@ -586,7 +586,9 @@ The result of the call is always converted to a boolean.
the <code>&lt;</code> (less than) operation.
Behavior similar to the "add" operation,
-except that the result of the call is always converted to a boolean.
+except that Lua will try a metamethod only when the values
+being compared are neither both numbers nor both strings.
+The result of the call is always converted to a boolean.
</li>
<li><b>"le": </b>
@@ -595,7 +597,7 @@ the <code>&lt;=</code> (less equal) operation.
Unlike other operations,
The less-equal operation can use two different events.
First, Lua looks for the "<code>__le</code>" metamethod in both operands,
-like in the "add" operation.
+like in the "lt" operation.
If it cannot find such a metamethod,
then it will try the "<code>__lt</code>" event,
assuming that <code>a &lt;= b</code> is equivalent to <code>not (b &lt; a)</code>.
@@ -775,7 +777,7 @@ Lua simply ignores it.)
<p>
At the end of each garbage-collection cycle,
the finalizers for objects are called in
-the reverse order that they were marked for collection,
+the reverse order that they were marked for finalization,
among those collected in that cycle;
that is, the first finalizer to be called is the one associated
with the object marked last in the program.
@@ -792,17 +794,20 @@ and the object memory is freed in the next garbage-collection cycle.
However, if the finalizer stores the object in some global place
(e.g., a global variable),
then there is a permanent resurrection.
+Moreover, if the finalizer marks a finalizing object for finalization again,
+its finalizer will be called again in the next cycle where the
+object is unreachable.
In any case,
-the object memory is freed only when it becomes completely inaccessible;
-its finalizer will never be called twice.
+the object memory is freed only in the GC cycle where
+the object is unreachable and not marked for finalization.
<p>
When you close a state (see <a href="#lua_close"><code>lua_close</code></a>),
Lua calls the finalizers of all objects marked for finalization,
following the reverse order that they were marked.
-If any finalizer marks new objects for collection during that phase,
-these new objects will not be finalized.
+If any finalizer marks objects for collection during that phase,
+these marks have no effect.
@@ -1064,9 +1069,10 @@ and cannot be used as names:
Lua is a case-sensitive language:
<code>and</code> is a reserved word, but <code>And</code> and <code>AND</code>
are two different, valid names.
-As a convention, names starting with an underscore followed by
-uppercase letters (such as <a href="#pdf-_VERSION"><code>_VERSION</code></a>)
-are reserved for variables used by Lua.
+As a convention,
+programs should avoid creating
+names that start with an underscore followed by
+one or more uppercase letters (such as <a href="#pdf-_VERSION"><code>_VERSION</code></a>).
<p>
@@ -1074,6 +1080,7 @@ The following strings denote other tokens:
<pre>
+ - * / % ^ #
+ &amp; ~ | &lt;&lt; &gt;&gt; //
== ~= &lt;= &gt;= &lt; &gt; =
( ) { } [ ] ::
; : , . .. ...
@@ -1130,11 +1137,12 @@ enclosed by <em>long brackets</em>.
We define an <em>opening long bracket of level <em>n</em></em> as an opening
square bracket followed by <em>n</em> equal signs followed by another
opening square bracket.
-So, an opening long bracket of level&nbsp;0 is written as <code>[[</code>,
-an opening long bracket of level&nbsp;1 is written as <code>[=[</code>,
+So, an opening long bracket of level&nbsp;0 is written as <code>[[</code>,
+an opening long bracket of level&nbsp;1 is written as <code>[=[</code>,
and so on.
A <em>closing long bracket</em> is defined similarly;
-for instance, a closing long bracket of level&nbsp;4 is written as <code>]====]</code>.
+for instance,
+a closing long bracket of level&nbsp;4 is written as <code>]====]</code>.
A <em>long literal</em> starts with an opening long bracket of any level and
ends at the first closing long bracket of the same level.
It can contain any text except a closing bracket of the proper level.
@@ -1594,20 +1602,19 @@ is equivalent to the code:
<pre>
do
- local <em>var</em>, <em>limit</em>, <em>step</em> = convert(<em>e1</em>, <em>e2</em>, <em>e3</em>)
+ local <em>var</em>, <em>limit</em>, <em>step</em> = tonumber(<em>e1</em>), tonumber(<em>e2</em>), tonumber(<em>e3</em>)
if not (<em>var</em> and <em>limit</em> and <em>step</em>) then error() end
- while (<em>step</em> &gt; 0 and <em>var</em> &lt;= <em>limit</em>) or (<em>step</em> &lt;= 0 and <em>var</em> &gt;= <em>limit</em>) do
+ <em>var</em> = <em>var</em> - <em>step</em>
+ while true do
+ <em>var</em> = <em>var</em> + <em>step</em>
+ if (<em>step</em> &gt;= 0 and <em>var</em> &gt; <em>limit</em>) or (<em>step</em> &lt; 0 and <em>var</em> &lt; <em>limit</em>) then
+ break
+ end
local v = <em>var</em>
<em>block</em>
- <em>var</em> = <em>var</em> + <em>step</em>
end
end
-</pre><p>
-where <code>convert</code> returns
-its three arguments unaltered
-if they are all integers,
-otherwise it converts them to floats.
-
+</pre>
<p>
Note the following:
@@ -1621,12 +1628,6 @@ They must all result in numbers.
</li>
<li>
-If any of the three control values is not an integer,
-all three values are converted to floats,
-so that the loop is done with floats.
-</li>
-
-<li>
<code><em>var</em></code>, <code><em>limit</em></code>, and <code><em>step</em></code> are invisible variables.
The names shown here are for explanatory purposes only.
</li>
@@ -1641,9 +1642,8 @@ You can use <b>break</b> and <b>goto</b> to exit a <b>for</b> loop.
</li>
<li>
-The loop variable <code>v</code> is local to the loop;
-you cannot use its value after the <b>for</b> ends or is broken.
-If you need its value,
+The loop variable <code>v</code> is local to the loop body.
+If you need its value after the loop,
assign it to another variable before exiting the loop.
</li>
@@ -1840,17 +1840,20 @@ or <b>nil</b> if <code>f</code> does not return any values.)
<h3>3.4.1 &ndash; <a name="3.4.1">Arithmetic Operators</a></h3><p>
Lua supports the following arithmetic operators:
-the binary <code>+</code> (addition),
-<code>-</code> (subtraction), <code>*</code> (multiplication),
-<code>/</code> (division), <code>//</code> (integer division),
-<code>%</code> (modulo), and <code>^</code> (exponentiation);
-and unary <code>-</code> (mathematical negation).
-Modulo is defined as the remainder of a division
-that rounds the quotient towards minus infinite (floor).
+<table border="1">
+<tr><td><code>+</code></td><td>addition</td></tr>
+<tr><td><code>-</code></td><td>subtraction</td></tr>
+<tr><td><code>*</code></td><td>multiplication</td></tr>
+<tr><td><code>/</code></td><td>float division</td></tr>
+<tr><td><code>//</code></td><td>integer division</td></tr>
+<tr><td><code>%</code></td><td>modulo</td></tr>
+<tr><td><code>^</code></td><td>exponentiation</td></tr>
+<tr><td><code>-</code></td><td>unary minus</td></tr>
+</table>
<p>
-With the exception of division and integer division,
+With the exception of divisions and exponentiation,
the arithmetic operators work as follows:
If both operands are integers,
the operation is performed over integers and the result is an integer.
@@ -1865,8 +1868,11 @@ and the result is a float.
<p>
-Division (<code>/</code>) always converts its operands to floats
-and its result is always a float.
+Float division (<code>/</code>) and exponentiation
+always convert their operands to floats
+and the result is always a float.
+Exponentiation uses the ANSI&nbsp;C function <code>pow</code>,
+so that it works for non-integer exponents too.
<p>
@@ -1877,9 +1883,15 @@ The result is always rounded towards minus infinite (floor).
<p>
+Modulo is defined as the remainder of a division
+that rounds the quotient towards minus infinite (floor).
+
+
+<p>
In case of overflows in integer arithmetic,
all operations <em>wrap around</em>,
according to the usual rules of two-complement arithmetic.
+(In other words, they return the correct result modulo <em>2<sup>64</sup></em>.)
@@ -1887,10 +1899,14 @@ according to the usual rules of two-complement arithmetic.
<h3>3.4.2 &ndash; <a name="3.4.2">Bitwise Operators</a></h3><p>
Lua supports the following bitwise operators:
-the binary <code>&amp;</code> (bitwise and),
-<code>|</code> (bitwise or), <code>~</code> (bitwise exclusive or),
-<code>&gt;&gt;</code> (right shift), <code>&lt;&lt;</code> (left shift),
-and unary <code>~</code> (bitwise not).
+<table border="1">
+<tr><td><code>&amp;</code></td><td>bitwise and</td></tr>
+<tr><td><code>|</code></td><td>bitwise or</td></tr>
+<tr><td><code>~</code></td><td>bitwise exclusive or</td></tr>
+<tr><td><code>&gt;&gt;</code></td><td>right shift</td></tr>
+<tr><td><code>&lt;&lt;</code></td><td>left shift</td></tr>
+<tr><td><code>~</code></td><td>unary bitwise not</td></tr>
+</table>
<p>
@@ -1901,7 +1917,7 @@ and result in an integer.
<p>
-Both right and left shifts fill with zeros the vacant bits.
+Both right and left shifts fill the vacant bits with zeros.
Negative displacements shift to the other direction;
displacements with absolute values equal to or higher than
the number of bits in an integer
@@ -1917,7 +1933,7 @@ types and representations at run time.
Most arithmetic operations applied to mixed numbers
(integers and floats) convert the integer operand to a float;
this is called the <em>usual rule</em>.
-Division always convert integer operands to floats;
+Float division always convert integer operands to floats;
integer division and bitwise operators
always convert float operands to integers.
The C API also converts both integers to floats and
@@ -1929,7 +1945,6 @@ besides strings.
<p>
Lua also converts strings to numbers,
whenever a number is expected.
-(This conversion may be deprecated in future versions.)
<p>
@@ -1951,16 +1966,16 @@ Otherwise, the conversion fails.
<p>
-The conversion from strings to floats
-follows the rules of the Lua lexer.
-(The string may have leading and trailing spaces and a sign.)
-There is no direct conversion from strings to integers:
-If a string is provided where an integer is needed,
-Lua converts the string to a float and then the float to an integer.
+The conversion from strings to numbers goes as follows:
+First, the string is converted to an integer or a float,
+following its syntax and the rules of the Lua lexer.
+(The string may have also leading and trailing spaces and a sign.)
+Then, the resulting number is converted to the required type
+(float or integer) according to the previous rules.
<p>
-The conversion from numbers to strings use a human-readable,
+The conversion from numbers to strings uses a human-readable,
non-specified format.
For complete control over how numbers are converted to strings,
use the <code>format</code> function from the string library
@@ -1971,11 +1986,15 @@ use the <code>format</code> function from the string library
<h3>3.4.4 &ndash; <a name="3.4.4">Relational Operators</a></h3><p>
-The relational operators in Lua are
-
-<pre>
- == ~= &lt; &gt; &lt;= &gt;=
-</pre><p>
+Lua supports the following relational operators:
+<table border="1">
+<tr><td><code>==</code></td><td>equality</td></tr>
+<tr><td><code>~=</code></td><td>inequality</td></tr>
+<tr><td><code>&lt;</code></td><td>less than</td></tr>
+<tr><td><code>&gt;</code></td><td>greater than</td></tr>
+<tr><td><code>&lt;=</code></td><td>less or equal</td></tr>
+<tr><td><code>&gt;=</code></td><td>greater or equal</td></tr>
+</table>
These operators always result in <b>false</b> or <b>true</b>.
@@ -1986,8 +2005,8 @@ Otherwise, the values of the operands are compared.
Strings are compared in the obvious way.
Numbers follow the usual rule for binary operations:
if both operands are integers,
-the are compared as integers.
-Otherwise, they are converted to floats
+the are compared as integers;
+otherwise, they are converted to floats
and compared as such.
@@ -2131,10 +2150,14 @@ from lower to higher priority:
or
and
&lt; &gt; &lt;= &gt;= ~= ==
+ |
+ ~
+ &amp;
+ &lt;&lt; &gt;&gt;
..
+ -
* / // %
- not # - (unary)
+ unary operators (not # - ~)
^
</pre><p>
As usual,
@@ -2690,7 +2713,7 @@ The registry table is always located at pseudo-index
<a name="pdf-LUA_REGISTRYINDEX"><code>LUA_REGISTRYINDEX</code></a>,
which is a valid index.
Any C&nbsp;library can store data into this table,
-but it should take care to choose keys
+but it must take care to choose keys
that are different from those used
by other libraries, to avoid collisions.
Typically, you should use as key a string containing your library name,
@@ -2705,7 +2728,7 @@ uppercase letters are reserved for Lua.
The integer keys in the registry are used by the reference mechanism,
implemented by the auxiliary library,
and by some predefined values.
-Therefore, integer keys should not be used for other purposes.
+Therefore, integer keys must not be used for other purposes.
<p>
@@ -2760,18 +2783,18 @@ The panic function runs as if it were a message handler (see <a href="#2.3">&sec
in particular, the error message is at the top of the stack.
However, there is no guarantees about stack space.
To push anything on the stack,
-the panic function should 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>).
<p>
-Most functions in the API can throw an error,
+Most functions in the API can raise an error,
for instance due to a memory allocation error.
The documentation for each function indicates whether
-it can throw errors.
+it can raise errors.
<p>
-Inside a C&nbsp;function you can throw an error by calling <a href="#lua_error"><code>lua_error</code></a>.
+Inside a C&nbsp;function you can raise an error by calling <a href="#lua_error"><code>lua_error</code></a>.
@@ -2781,7 +2804,7 @@ Inside a C&nbsp;function you can throw an error by calling <a href="#lua_error">
<p>
Internally, Lua uses the C <code>longjmp</code> facility to yield a coroutine.
-Therefore, if a function <code>foo</code> calls an API function
+Therefore, if a C function <code>foo</code> calls an API function
and this API function yields
(directly or indirectly by calling another function that yields),
Lua cannot return to <code>foo</code> any more,
@@ -2824,6 +2847,67 @@ of the original function.
<p>
+As an illustration, consider the following function:
+
+<pre>
+ int original_function (lua_State *L) {
+ ... /* code 1 */
+ status = lua_pcall(L, n, m, h); /* calls Lua */
+ ... /* code 2 */
+ }
+</pre><p>
+Now we want to allow
+the Lua code being ran by <a href="#lua_pcall"><code>lua_pcall</code></a> to yield.
+First, we can rewrite our function like here:
+
+<pre>
+ int k (lua_State *L, int status, int ctx) {
+ ... /* code 2 */
+ }
+
+ int original_function (lua_State *L) {
+ ... /* code 1 */
+ return k(L, lua_pcall(L, n, m, h), ctx);
+ }
+</pre><p>
+In the above code,
+the new function <code>k</code> is a
+<em>continuation function</em> (with type <a href="#lua_KFunction"><code>lua_KFunction</code></a>),
+which should do all the work that the original function
+was doing after calling <a href="#lua_pcall"><code>lua_pcall</code></a>.
+Now, we must inform Lua that it must call <code>k</code> if the Lua code
+begin running by <a href="#lua_pcall"><code>lua_pcall</code></a> gets interrupted in some way
+(errors or yielding),
+so we rewrite the code as here,
+replacing <a href="#lua_pcall"><code>lua_pcall</code></a> by <a href="#lua_pcallk"><code>lua_pcallk</code></a>:
+
+<pre>
+ int original_function (lua_State *L) {
+ ... /* code 1 */
+ return k(L, lua_pcallk(L, n, m, h, ctx2, k), ctx1);
+ }
+</pre>
+
+<p>
+Besides the Lua state,
+the continuation function has two other parameters:
+the final status of the call plus the context value (<code>ctx</code>) that
+was passed originally to <a href="#lua_pcallk"><code>lua_pcallk</code></a>.
+(Lua does not use this context value;
+it only passes this value from the original function to the
+continuation function.)
+For <a href="#lua_pcallk"><code>lua_pcallk</code></a>,
+the status is the same value that would be returned by <a href="#lua_pcallk"><code>lua_pcallk</code></a>,
+except that it is <a href="#pdf-LUA_YIELD"><code>LUA_YIELD</code></a> when being executed after an yield
+(instead of <a href="#pdf-LUA_OK"><code>LUA_OK</code></a>).
+For <a href="#lua_yieldk"><code>lua_yieldk</code></a> and <a href="#lua_callk"><code>lua_callk</code></a>,
+the status is always <a href="#pdf-LUA_YIELD"><code>LUA_YIELD</code></a> when Lua calls the continuation.
+(For these two functions,
+Lua will not call the continuation in case of errors,
+because they do not handle errors.)
+
+
+<p>
Lua treats the continuation function as if it were the original function.
The continuation function receives the same Lua stack
from the original function,
@@ -2836,11 +2920,6 @@ Whatever it returns is handled by Lua as if it were the return
of the original function.
-<p>
-The only difference in the Lua state between the original function
-and its continuation is the result of a call to <a href="#lua_getctx"><code>lua_getctx</code></a>.
-
-
@@ -2867,10 +2946,10 @@ we cannot know how many elements the function pops/pushes
by looking only at its arguments
(e.g., they may depend on what is on the stack).
The third field, <code>x</code>,
-tells whether the function may throw errors:
-'<code>-</code>' means the function never throws any error;
-'<code>e</code>' means the function may throw errors;
-'<code>v</code>' means the function may throw an error on purpose.
+tells whether the function may raise errors:
+'<code>-</code>' means the function never raises any error;
+'<code>e</code>' means the function may raise errors;
+'<code>v</code>' means the function may raise an error on purpose.
@@ -2928,13 +3007,13 @@ Lua assumes the following behavior from the allocator function:
<p>
When <code>nsize</code> is zero,
-the allocator should behave like <code>free</code>
+the allocator must behave like <code>free</code>
and return <code>NULL</code>.
<p>
When <code>nsize</code> is not zero,
-the allocator should behave like <code>realloc</code>.
+the allocator must behave like <code>realloc</code>.
The allocator returns <code>NULL</code>
if and only if it cannot fulfill the request.
Lua assumes that the allocator never fails when
@@ -2990,7 +3069,7 @@ The value of <code>op</code> must be one of the following constants:
<li><b><a name="pdf-LUA_OPADD"><code>LUA_OPADD</code></a>: </b> performs addition (<code>+</code>)</li>
<li><b><a name="pdf-LUA_OPSUB"><code>LUA_OPSUB</code></a>: </b> performs subtraction (<code>-</code>)</li>
<li><b><a name="pdf-LUA_OPMUL"><code>LUA_OPMUL</code></a>: </b> performs multiplication (<code>*</code>)</li>
-<li><b><a name="pdf-LUA_OPDIV"><code>LUA_OPDIV</code></a>: </b> performs division (<code>/</code>)</li>
+<li><b><a name="pdf-LUA_OPDIV"><code>LUA_OPDIV</code></a>: </b> performs float division (<code>/</code>)</li>
<li><b><a name="pdf-LUA_OPIDIV"><code>LUA_OPIDIV</code></a>: </b> performs integer division (<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>
@@ -3081,7 +3160,7 @@ This is considered good programming practice.
<hr><h3><a name="lua_callk"><code>lua_callk</code></a></h3><p>
<span class="apii">[-(nargs + 1), +nresults, <em>e</em>]</span>
<pre>void lua_callk (lua_State *L, int nargs, int nresults, int ctx,
- lua_CFunction k);</pre>
+ lua_KFunction k);</pre>
<p>
This function behaves exactly like <a href="#lua_call"><code>lua_call</code></a>,
@@ -3258,7 +3337,10 @@ Otherwise you can use the function <a href="#lua_newtable"><code>lua_newtable</c
<hr><h3><a name="lua_dump"><code>lua_dump</code></a></h3><p>
<span class="apii">[-0, +0, <em>e</em>]</span>
-<pre>int lua_dump (lua_State *L, lua_Writer writer, void *data);</pre>
+<pre>int lua_dump (lua_State *L,
+ lua_Writer writer,
+ void *data,
+ int strip);</pre>
<p>
Dumps a function as a binary chunk.
@@ -3273,6 +3355,12 @@ to write them.
<p>
+If <code>strip</code> is true,
+the binary representation is created without debug information
+about the function.
+
+
+<p>
The value returned is the error code returned by the last
call to the writer;
0&nbsp;means no errors.
@@ -3291,8 +3379,7 @@ This function does not pop the Lua function from the stack.
<p>
Generates a Lua error.
-The error message (which can actually be a Lua value of any type)
-must be on the stack top.
+The error object must be on the stack top.
This function does a long jump,
and therefore never returns
(see <a href="#luaL_error"><code>luaL_error</code></a>).
@@ -3380,45 +3467,9 @@ opaque pointer passed to <a href="#lua_newstate"><code>lua_newstate</code></a>.
-<hr><h3><a name="lua_getctx"><code>lua_getctx</code></a></h3><p>
-<span class="apii">[-0, +0, &ndash;]</span>
-<pre>int lua_getctx (lua_State *L, int *ctx);</pre>
-
-<p>
-This function is called by a continuation function (see <a href="#4.7">&sect;4.7</a>)
-to retrieve the status of the thread and a context information.
-
-
-<p>
-When called in the original function,
-<a href="#lua_getctx"><code>lua_getctx</code></a> always returns <a href="#pdf-LUA_OK"><code>LUA_OK</code></a>
-and does not change the value of its argument <code>ctx</code>.
-When called inside a continuation function,
-<a href="#lua_getctx"><code>lua_getctx</code></a> returns <a href="#pdf-LUA_YIELD"><code>LUA_YIELD</code></a> and sets
-the value of <code>ctx</code> to be the context information
-(the value passed as the <code>ctx</code> argument
-to the callee together with the continuation function).
-
-
-<p>
-When the callee is <a href="#lua_pcallk"><code>lua_pcallk</code></a>,
-Lua may also call its continuation function
-to handle errors during the call.
-That is, upon an error in the function called by <a href="#lua_pcallk"><code>lua_pcallk</code></a>,
-Lua may not return to the original function
-but instead may call the continuation function.
-In that case, a call to <a href="#lua_getctx"><code>lua_getctx</code></a> will return the error code
-(the value that would be returned by <a href="#lua_pcallk"><code>lua_pcallk</code></a>);
-the value of <code>ctx</code> will be set to the context information,
-as in the case of a yield.
-
-
-
-
-
<hr><h3><a name="lua_getfield"><code>lua_getfield</code></a></h3><p>
<span class="apii">[-0, +1, <em>e</em>]</span>
-<pre>void lua_getfield (lua_State *L, int index, const char *k);</pre>
+<pre>int lua_getfield (lua_State *L, int index, const char *k);</pre>
<p>
Pushes onto the stack the value <code>t[k]</code>,
@@ -3427,6 +3478,10 @@ As in Lua, this function may trigger a metamethod
for the "index" event (see <a href="#2.4">&sect;2.4</a>).
+<p>
+Returns the type of the pushed value.
+
+
@@ -3495,13 +3550,17 @@ this result is equal to the number of elements in the stack
<hr><h3><a name="lua_getuservalue"><code>lua_getuservalue</code></a></h3><p>
<span class="apii">[-0, +1, &ndash;]</span>
-<pre>void lua_getuservalue (lua_State *L, int index);</pre>
+<pre>int lua_getuservalue (lua_State *L, int index);</pre>
<p>
Pushes onto the stack the Lua value associated with the userdata
at the given index.
+<p>
+Returns the type of the pushed value.
+
+
@@ -3520,7 +3579,7 @@ because a pseudo-index is not an actual stack position.
<hr><h3><a name="lua_Integer"><code>lua_Integer</code></a></h3>
-<pre>typedef long long int lua_Integer;</pre>
+<pre>typedef ... lua_Integer;</pre>
<p>
The type of integers in Lua.
@@ -3534,6 +3593,12 @@ to <code>long</code> or <code>int</code>
(usually a 32-bit two-complement integer).
+<p>
+Lua also defines the constants
+<a name="pdf-LUA_MININTEGER"><code>LUA_MININTEGER</code></a> and <a name="pdf-LUA_MAXINTEGER"><code>LUA_MAXINTEGER</code></a>,
+with the minimum and the maximum values that fit in this type.
+
+
@@ -3697,6 +3762,28 @@ Returns 1 if the value at the given index is a userdata
+<hr><h3><a name="lua_isyieldable"><code>lua_isyieldable</code></a></h3><p>
+<span class="apii">[-0, +0, &ndash;]</span>
+<pre>int lua_isyieldable (lua_State *L);</pre>
+
+<p>
+Returns 1 if the given coroutine can yield,
+and 0&nbsp;otherwise.
+
+
+
+
+
+<hr><h3><a name="lua_KFunction"><code>lua_KFunction</code></a></h3>
+<pre>typedef int (*lua_KFunction) (lua_State *L, int status, int ctx);</pre>
+
+<p>
+Type for continuation functions (see <a href="#4.7">&sect;4.7</a>).
+
+
+
+
+
<hr><h3><a name="lua_len"><code>lua_len</code></a></h3><p>
<span class="apii">[-0, +1, <em>e</em>]</span>
<pre>void lua_len (lua_State *L, int index);</pre>
@@ -3768,7 +3855,7 @@ a <code>NULL</code> value is equivalent to the string "<code>bt</code>".
<p>
<code>lua_load</code> uses the stack internally,
-so the reader function should always leave the stack
+so the reader function must always leave the stack
unmodified when returning.
@@ -3907,6 +3994,28 @@ but that can be changed in <code>luaconf.h</code> to a single float.
+<hr><h3><a name="lua_numtointeger"><code>lua_numtointeger</code></a></h3>
+<pre>int lua_numtointeger (lua_Number n, lua_Integer *p);</pre>
+
+<p>
+Converts a Lua float to a Lua integer.
+This macro assumes that <code>n</code> has an integral value.
+If that value is within the range of Lua integers,
+it is converted to an integer and assigned to <code>*p</code>.
+The macro results in a boolean indicating whether the
+conversion was successful.
+(Note that this range test can be tricky to do
+correctly without this macro,
+due to roundings.)
+
+
+<p>
+This macro may evaluate its arguments more than once.
+
+
+
+
+
<hr><h3><a name="lua_pcall"><code>lua_pcall</code></a></h3><p>
<span class="apii">[-(nargs + 1), +(nresults|1), &ndash;]</span>
<pre>int lua_pcall (lua_State *L, int nargs, int nresults, int msgh);</pre>
@@ -3950,7 +4059,7 @@ since by then the stack has unwound.
<p>
-The <a href="#lua_pcall"><code>lua_pcall</code></a> function returns one of the following codes
+The <a href="#lua_pcall"><code>lua_pcall</code></a> function returns one of the following constants
(defined in <code>lua.h</code>):
<ul>
@@ -3973,8 +4082,7 @@ error while running the message handler.
<li><b><a name="pdf-LUA_ERRGCMM"><code>LUA_ERRGCMM</code></a>: </b>
error while running a <code>__gc</code> metamethod.
-(This error typically has no relation with the function being called.
-It is generated by the garbage collector.)
+(This error typically has no relation with the function being called.)
</li>
</ul>
@@ -3989,7 +4097,7 @@ It is generated by the garbage collector.)
int nresults,
int errfunc,
int ctx,
- lua_CFunction k);</pre>
+ lua_KFunction k);</pre>
<p>
This function behaves exactly like <a href="#lua_pcall"><code>lua_pcall</code></a>,
@@ -4035,11 +4143,11 @@ it is possible to associate some values with it,
thus creating a C&nbsp;closure (see <a href="#4.4">&sect;4.4</a>);
these values are then accessible to the function whenever it is called.
To associate values with a C&nbsp;function,
-first these values should be pushed onto the stack
+first these values must be pushed onto the stack
(when there are multiple values, the first value is pushed first).
Then <a href="#lua_pushcclosure"><code>lua_pushcclosure</code></a>
is called to create and push the C&nbsp;function onto the stack,
-with the argument <code>n</code> telling how many values should be
+with the argument <code>n</code> telling how many values will be
associated with the function.
<a href="#lua_pushcclosure"><code>lua_pushcclosure</code></a> also pops these values from the stack.
@@ -4052,7 +4160,7 @@ The maximum value for <code>n</code> is 255.
When <code>n</code> is zero,
this function creates a <em>light C function</em>,
which is just a pointer to the C&nbsp;function.
-In that case, it never throws a memory error.
+In that case, it never raises a memory error.
@@ -4540,6 +4648,22 @@ this parameter can be <code>NULL</code>.
+<hr><h3><a name="lua_rotate"><code>lua_rotate</code></a></h3><p>
+<span class="apii">[-0, +0, &ndash;]</span>
+<pre>void lua_rotate (lua_State *L, int idx, int n);</pre>
+
+<p>
+Rotates the stack elements from <code>idx</code> to the top <code>n</code> positions
+in the direction of the top, for a positive <code>n</code>,
+or <code>-n</code> positions in the direction of the bottom,
+for a negative <code>n</code>.
+The absolute value of <code>n</code> must not be greater than the size
+of the slice being rotated.
+
+
+
+
+
<hr><h3><a name="lua_setallocf"><code>lua_setallocf</code></a></h3><p>
<span class="apii">[-0, +0, &ndash;]</span>
<pre>void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);</pre>
@@ -4689,11 +4813,13 @@ You can resume threads with status <a href="#pdf-LUA_OK"><code>LUA_OK</code></a>
<hr><h3><a name="lua_strtonum"><code>lua_strtonum</code></a></h3><p>
<span class="apii">[-0, +1, &ndash;]</span>
-<pre>int lua_strtonum (lua_State *L, const char *s, size_t len);</pre>
+<pre>size_t lua_strtonum (lua_State *L, const char *s);</pre>
<p>
-Converts the string <code>s</code> (with length <code>len</code>) to a number and
-pushes that number into the stack.
+Converts the zero-terminated string <code>s</code> to a number,
+pushes that number into the stack,
+and returns the total size of the string
+(that is, its length plus one).
The conversion can result in an integer or a float,
according to the lexical conventions of Lua (see <a href="#3.1">&sect;3.1</a>).
The string may have leading and trailing spaces and a sign.
@@ -4969,12 +5095,17 @@ which must be one the values returned by <a href="#lua_type"><code>lua_type</cod
<hr><h3><a name="lua_Unsigned"><code>lua_Unsigned</code></a></h3>
-<pre>typedef unsigned long lua_Unsigned;</pre>
+<pre>typedef ... lua_Unsigned;</pre>
<p>
The unsigned version of <a href="#lua_Integer"><code>lua_Integer</code></a>.
+<p>
+Lua also defines the constant <a name="pdf-LUA_MAXUNSIGNED"><code>LUA_MAXUNSIGNED</code></a>,
+with the maximum value that fits in this type.
+
+
@@ -5063,7 +5194,7 @@ the function calling <code>lua_yield</code>.
<hr><h3><a name="lua_yieldk"><code>lua_yieldk</code></a></h3><p>
<span class="apii">[-?, +?, &ndash;]</span>
-<pre>int lua_yieldk (lua_State *L, int nresults, int ctx, lua_CFunction k);</pre>
+<pre>int lua_yieldk (lua_State *L, int nresults, int ctx, lua_KFunction k);</pre>
<p>
Yields a coroutine.
@@ -5074,13 +5205,13 @@ This function should only be called as the
return expression of a C&nbsp;function, as follows:
<pre>
- return lua_yieldk (L, n, i, k);
+ return lua_yieldk (L, n, ctx, k);
</pre><p>
When a C&nbsp;function calls <a href="#lua_yieldk"><code>lua_yieldk</code></a> in that way,
the running coroutine suspends its execution,
and the call to <a href="#lua_resume"><code>lua_resume</code></a> that started this coroutine returns.
The parameter <code>nresults</code> is the number of values from the stack
-that are passed as results to <a href="#lua_resume"><code>lua_resume</code></a>.
+that will be passed as results to <a href="#lua_resume"><code>lua_resume</code></a>.
<p>
@@ -5089,11 +5220,11 @@ Lua calls the given continuation function <code>k</code> to continue
the execution of the C function that yielded (see <a href="#4.7">&sect;4.7</a>).
This continuation function receives the same stack
from the previous function,
-with the results removed and
+with the <code>n</code> results removed and
replaced by the arguments passed to <a href="#lua_resume"><code>lua_resume</code></a>.
Moreover,
-the continuation function may access the value <code>ctx</code>
-by calling <a href="#lua_getctx"><code>lua_getctx</code></a>.
+the continuation function receives the value <code>ctx</code>
+that was passed to <a href="#lua_yieldk"><code>lua_yieldk</code></a>.
@@ -5326,6 +5457,11 @@ numbers of the lines that are valid on the function.
(A <em>valid line</em> is a line with some associated code,
that is, a line where you can put a break point.
Non-valid lines include empty lines and comments.)
+
+
+<p>
+If this option is given together with option '<code>f</code>',
+its table is pushed after the function.
</li>
</ul>
@@ -5363,7 +5499,7 @@ and returns its name.
<p>
-In the second case, <code>ar</code> should be <code>NULL</code> and the function
+In the second case, <code>ar</code> must be <code>NULL</code> and the function
to be inspected must be at the top of the stack.
In this case, only parameters of Lua functions are visible
(as there is no information about what variables are active)
@@ -5656,7 +5792,7 @@ you should not use these functions for other stack values.
<p>
Functions called <code>luaL_check*</code>
-always throw an error if the check is not satisfied.
+always raise an error if the check is not satisfied.
@@ -6398,7 +6534,7 @@ returns 0.
Otherwise,
creates a new table to be used as a metatable for userdata,
adds to this new table the pair <code>__name = tname</code>,
-adds to the registry the pair <code></code>[tname] = new table,
+adds to the registry the pair <code>[tname] = new table</code>,
and returns 1.
@@ -6762,7 +6898,7 @@ the field value is changed to <b>nil</b> to signal that the handle is closed.
<p>
This function works like <a href="#luaL_checkudata"><code>luaL_checkudata</code></a>,
except that, when the test fails,
-it returns <code>NULL</code> instead of throwing an error.
+it returns <code>NULL</code> instead of raising an error.
@@ -6862,6 +6998,8 @@ This function is used to build a prefix for error messages.
+
+
<h1>6 &ndash; <a name="6">Standard Libraries</a></h1>
<p>
@@ -6939,11 +7077,15 @@ implementations for some of its facilities.
<p>
<hr><h3><a name="pdf-assert"><code>assert (v [, message])</code></a></h3>
-Issues an error when
+
+
+<p>
+Calls <a href="#pdf-error"><code>error</code></a> if
the value of its argument <code>v</code> is false (i.e., <b>nil</b> or <b>false</b>);
otherwise, returns all its arguments.
-<code>message</code> is an error message;
-when absent, it defaults to "assertion failed!"
+In case of error,
+<code>message</code> is the error object;
+when absent, it defaults to "<code>assertion failed!</code>"
@@ -7009,16 +7151,6 @@ returns a boolean that tells whether the collector is running
(i.e., not stopped).
</li>
-<li><b>"<code>generational</code>": </b>
-changes the collector to generational mode.
-This is an experimental feature (see <a href="#2.5">&sect;2.5</a>).
-</li>
-
-<li><b>"<code>incremental</code>": </b>
-changes the collector to incremental mode.
-This is the default mode.
-</li>
-
</ul>
@@ -7038,7 +7170,7 @@ to its caller (that is, <code>dofile</code> does not run in protected mode).
<p>
<hr><h3><a name="pdf-error"><code>error (message [, level])</code></a></h3>
Terminates the last protected function called
-and returns <code>message</code> as the error message.
+and returns <code>message</code> as the error object.
Function <code>error</code> never returns.
@@ -7375,7 +7507,7 @@ according to the lexical conventions of Lua (see <a href="#3.1">&sect;3.1</a>).
<p>
When called with <code>base</code>,
-then <code>e</code> should be a string to be interpreted as
+then <code>e</code> must be a string to be interpreted as
an integer numeral in that base.
The base may be any integer between 2 and 36, inclusive.
In bases above&nbsp;10, the letter '<code>A</code>' (in either upper or lower case)
@@ -7467,6 +7599,21 @@ an object with type <code>"thread"</code>.
<p>
+<hr><h3><a name="pdf-coroutine.isyieldable"><code>coroutine.isyieldable ()</code></a></h3>
+
+
+<p>
+Returns true when the running coroutine can yield.
+
+
+<p>
+A running coroutine is yieldable if it is not the main thread and
+it is not inside a non-yieldable C function.
+
+
+
+
+<p>
<hr><h3><a name="pdf-coroutine.resume"><code>coroutine.resume (co [, val1, &middot;&middot;&middot;])</code></a></h3>
@@ -7485,8 +7632,8 @@ as the results from the yield.
<p>
If the coroutine runs without any errors,
<code>resume</code> returns <b>true</b> plus any values passed to <code>yield</code>
-(if the coroutine yields) or any values returned by the body function
-(if the coroutine terminates).
+(when the coroutine yields) or any values returned by the body function
+(when the coroutine terminates).
If there is any error,
<code>resume</code> returns <b>false</b> plus the error message.
@@ -7588,7 +7735,7 @@ for <a href="#pdf-package.searchers"><code>package.searchers</code></a>.
<p>
First <code>require</code> queries <code>package.preload[modname]</code>.
If it has a value,
-this value (which should be a function) is the loader.
+this value (which must be a function) is the loader.
Otherwise <code>require</code> searches for a Lua loader using the
path stored in <a href="#pdf-package.path"><code>package.path</code></a>.
If that also fails, it searches for a C&nbsp;loader using the
@@ -7663,7 +7810,7 @@ The path used by <a href="#pdf-require"><code>require</code></a> to search for a
<p>
Lua initializes the C&nbsp;path <a href="#pdf-package.cpath"><code>package.cpath</code></a> in the same way
it initializes the Lua path <a href="#pdf-package.path"><code>package.path</code></a>,
-using the environment variable <a name="pdf-LUA_CPATH_5_2"><code>LUA_CPATH_5_2</code></a>
+using the environment variable <a name="pdf-LUA_CPATH_5_3"><code>LUA_CPATH_5_3</code></a>
or the environment variable <a name="pdf-LUA_CPATH"><code>LUA_CPATH</code></a>
or a default path defined in <code>luaconf.h</code>.
@@ -7741,7 +7888,7 @@ The path used by <a href="#pdf-require"><code>require</code></a> to search for a
<p>
At start-up, Lua initializes this variable with
-the value of the environment variable <a name="pdf-LUA_PATH_5_2"><code>LUA_PATH_5_2</code></a> or
+the value of the environment variable <a name="pdf-LUA_PATH_5_3"><code>LUA_PATH_5_3</code></a> or
the environment variable <a name="pdf-LUA_PATH"><code>LUA_PATH</code></a> or
with a default path defined in <code>luaconf.h</code>,
if those environment variables are not defined.
@@ -7974,6 +8121,45 @@ about the function
<p>
+<hr><h3><a name="pdf-string.dumpfloat"><code>string.dumpfloat (n [, size [, endianness]])</code></a></h3>
+Returns a string with the machine representation of float <code>n</code>,
+with given size and endianness.
+The <code>size</code> is the string "<code>f</code>" (single precision),
+"<code>d</code>" (double precision), or "<code>n</code>",
+which means the size of a <a href="#lua_Number"><code>lua_Number</code></a>;
+its default is "<code>n</code>".
+The endianness is the string "<code>l</code>" (little endian), "<code>b</code>" (big endian),
+or "<code>n</code>" (native);
+the default is the native endianness.
+
+
+<p>
+This function may not work correctly in architectures
+with mixed endian.
+
+
+<p>
+<hr><h3><a name="pdf-string.dumpint"><code>string.dumpint (n [, size [, endianness]])</code></a></h3>
+Returns a string with the two-complement representation of integer <code>n</code>,
+with <code>size</code> bytes and given endianness.
+The <code>size</code> can be any value from 1 to 12,
+or 0, which means the size of a <a href="#lua_Integer"><code>lua_Integer</code></a>
+(8 bytes in standard Lua);
+its default is zero.
+The endianness is the string "<code>l</code>" (little endian), "<code>b</code>" (big endian),
+or "<code>n</code>" (native);
+the default is the native endianness.
+
+
+<p>
+This function may not work correctly in architectures
+with mixed endian or
+that do not use a two-complement representation for integers.
+
+
+
+
+<p>
<hr><h3><a name="pdf-string.find"><code>string.find (s, pattern [, init [, plain]])</code></a></h3>
@@ -8196,45 +8382,6 @@ its default value is&nbsp;1 and can be negative.
<p>
-<hr><h3><a name="pdf-string.packfloat"><code>string.packfloat (n [, size [, endianess]])</code></a></h3>
-Returns a string with the machine representation of float <code>n</code>,
-with given size and endianess.
-The <code>size</code> is the string "<code>f</code>" (single precision),
-"<code>d</code>" (double precision), or "<code>n</code>",
-which means the size of a <a href="#lua_Number"><code>lua_Number</code></a>;
-its default is St{n}.
-The endianess is the string "<code>l</code>" (little endian), "<code>b</code>" (big endian),
-or "<code>n</code>" (native);
-the default is the native endianess.
-
-
-<p>
-(This function may not work correctly for non-native endianess
-in mixed-endian architectures.)
-
-
-
-
-<p>
-<hr><h3><a name="pdf-string.packint"><code>string.packint (n [, size [, endianess]])</code></a></h3>
-Returns a string with the machine representation of integer <code>n</code>,
-with <code>size</code> bytes and given endianess.
-The <code>size</code> can be any value from 1 to 8 or 0,
-which means the size of a <a href="#lua_Integer"><code>lua_Integer</code></a>;
-its default is zero.
-The endianess is the string "<code>l</code>" (little endian), "<code>b</code>" (big endian),
-or "<code>n</code>" (native);
-the default is the native endianess.
-
-
-<p>
-(This function may not work correctly for native endianess
-in mixed-endian architectures.)
-
-
-
-
-<p>
<hr><h3><a name="pdf-string.rep"><code>string.rep (s, n [, sep])</code></a></h3>
Returns a string that is the concatenation of <code>n</code> copies of
the string <code>s</code> separated by the string <code>sep</code>.
@@ -8279,19 +8426,19 @@ the function returns the empty string.
<p>
-<hr><h3><a name="pdf-string.unpackfloat"><code>string.unpackfloat (s [, pos [, size [, endianess]]])</code></a></h3>
+<hr><h3><a name="pdf-string.undumpfloat"><code>string.undumpfloat (s [, pos [, size [, endianness]]])</code></a></h3>
Reads the machine representation of a float starting at position
<code>pos</code> in string <code>s</code> and returns that number.
-See <a href="#pdf-string.packfloat"><code>string.packfloat</code></a> for details about <code>size</code> and <code>endianess</code>.
+See <a href="#pdf-string.dumpfloat"><code>string.dumpfloat</code></a> for details about <code>size</code> and <code>endianness</code>.
<p>
-<hr><h3><a name="pdf-string.unpackint"><code>string.unpackint (s [, pos [, size [, endianess]]])</code></a></h3>
+<hr><h3><a name="pdf-string.undumpint"><code>string.undumpint (s [, pos [, size [, endianness]]])</code></a></h3>
Reads the machine representation of an integer starting at position
<code>pos</code> in string <code>s</code> and returns that integer.
-See <a href="#pdf-string.packint"><code>string.packint</code></a> for details about <code>size</code> and <code>endianess</code>.
+See <a href="#pdf-string.dumpint"><code>string.dumpint</code></a> for details about <code>size</code> and <code>endianness</code>.
<p>
@@ -8517,7 +8664,7 @@ such as character classification, is outside its scope.
<p>
Unless stated otherwise,
-all functions that expect a byte index as a parameter
+all functions that expect a byte position as a parameter
assume that the given position is either the start of a byte sequence
or one plus the length of the subject string.
As in the string library,
@@ -8572,24 +8719,29 @@ It raises an error if it meets any invalid byte sequence.
<p>
-<hr><h3><a name="pdf-utf8.len"><code>utf8.len (s [, i])</code></a></h3>
-Returns the number of UTF-8 characters in string <code>s</code>,
-starting from position <code>i</code>.
-The default for <code>i</code> is 1.
-Returns <b>nil</b> if the sufix of <code>s</code> starting at <code>i</code>
-contains any invalid byte sequence.
+<hr><h3><a name="pdf-utf8.len"><code>utf8.len (s [, i [, j]])</code></a></h3>
+Returns the number of UTF-8 characters in string <code>s</code>
+that start between positions <code>i</code> and @{j} (both inclusive).
+The default for <code>i</code> is 1 and for <code>j</code> is -1.
+If it finds any invalid byte sequence,
+returns <b>nil</b> plus the position of the first invalid byte.
<p>
<hr><h3><a name="pdf-utf8.offset"><code>utf8.offset (s, n [, i])</code></a></h3>
-Returns the byte index where the encoding of the
-<code>n</code>-th character of <code>s</code> starts,
-counting from position <code>i</code>.
+Returns the position (in bytes) where the encoding of the
+<code>n</code>-th character of <code>s</code>
+(counting from position <code>i</code>) starts.
A negative <code>n</code> gets characters before position <code>i</code>.
-The default for <code>i</code> is 1.
-Returns <b>nil</b> if the subject does not have such character.
+The default for <code>i</code> is 1 when <code>n</code> is non-negative
+and <code>#s + 1</code> otherwise,
+so that <code>utf8.offset(s, -n)</code> gets the offset of the
+<code>n</code>-th character from the end of the string.
+If the specified character is not in the subject
+or right after its end,
+the function returns <b>nil</b>.
<p>
@@ -8616,7 +8768,7 @@ It provides all its functions inside the table <a name="pdf-table"><code>table</
<p>
Remember that, whenever an operation needs the length of a table,
-the table should be a proper sequence
+the table must be a proper sequence
or have a <code>__len</code> metamethod (see <a href="#3.4.7">&sect;3.4.7</a>).
All functions ignore non-numeric keys
in tables given as arguments.
@@ -8739,10 +8891,15 @@ By default, <code>i</code> is&nbsp;1 and <code>j</code> is <code>#list</code>.
<h2>6.7 &ndash; <a name="6.7">Mathematical Functions</a></h2>
<p>
-This library is an interface to the standard C&nbsp;math library.
-It provides all its functions inside the table <a name="pdf-math"><code>math</code></a>.
-Unless stated otherwise,
-all functions in this library operate with and return floats.
+This library provides basic mathematical functions.
+It provides all its functions and constants inside the table <a name="pdf-math"><code>math</code></a>.
+Functions with the annotation "<code>integer/float</code>" give
+integer results for integer arguments
+and float results for float (or mixed) arguments.
+Rounding functions
+(<a href="#pdf-math.ceil"><code>math.ceil</code></a>, <a href="#pdf-math.floor"><code>math.floor</code></a>, and <a href="#pdf-math.modf"><code>math.modf</code></a>)
+return an integer when the result fits in the range of an integer,
+otherwise they return a float.
<p>
@@ -8750,7 +8907,7 @@ all functions in this library operate with and return floats.
<p>
-Returns the absolute value of <code>x</code>.
+Returns the absolute value of <code>x</code>. (integer/float)
@@ -8776,54 +8933,41 @@ Returns the arc sine of <code>x</code> (in radians).
<p>
-<hr><h3><a name="pdf-math.atan"><code>math.atan (x)</code></a></h3>
+<hr><h3><a name="pdf-math.atan"><code>math.atan (y [, x])</code></a></h3>
<p>
-Returns the arc tangent of <code>x</code> (in radians).
-
-
-
-<p>
-<hr><h3><a name="pdf-math.atan2"><code>math.atan2 (y, x)</code></a></h3>
-
-
-<p>
Returns the arc tangent of <code>y/x</code> (in radians),
but uses the signs of both parameters to find the
quadrant of the result.
(It also handles correctly the case of <code>x</code> being zero.)
-
-
-<p>
-<hr><h3><a name="pdf-math.ceil"><code>math.ceil (x)</code></a></h3>
-
-
<p>
-Returns the smallest integer larger than or equal to <code>x</code>.
+The default value for <code>x</code> is 1,
+so that the call <code>math.atan(y)</code>
+returns the arc tangent of <code>y</code>.
<p>
-<hr><h3><a name="pdf-math.cos"><code>math.cos (x)</code></a></h3>
+<hr><h3><a name="pdf-math.ceil"><code>math.ceil (x)</code></a></h3>
<p>
-Returns the cosine of <code>x</code> (assumed to be in radians).
+Returns the smaller integral value larger than or equal to <code>x</code>.
<p>
-<hr><h3><a name="pdf-math.cosh"><code>math.cosh (x)</code></a></h3>
+<hr><h3><a name="pdf-math.cos"><code>math.cos (x)</code></a></h3>
<p>
-Returns the hyperbolic cosine of <code>x</code>.
+Returns the cosine of <code>x</code> (assumed to be in radians).
@@ -8833,17 +8977,7 @@ Returns the hyperbolic cosine of <code>x</code>.
<p>
-Returns the angle <code>x</code> (given in radians) in degrees.
-
-
-
-
-<p>
-<hr><h3><a name="pdf-math.exp"><code>math.exp (x)</code></a></h3>
-
-
-<p>
-Returns the value <em>e<sup>x</sup></em>.
+Converts the angle <code>x</code> from radians to degrees.
@@ -8853,8 +8987,7 @@ Returns the value <em>e<sup>x</sup></em>.
<p>
-Returns a float with the largest
-integral value smaller than or equal to <code>x</code>.
+Returns the largest integral value smaller than or equal to <code>x</code>.
@@ -8865,20 +8998,7 @@ integral value smaller than or equal to <code>x</code>.
<p>
Returns the remainder of the division of <code>x</code> by <code>y</code>
-that rounds the quotient towards zero.
-
-
-
-
-<p>
-<hr><h3><a name="pdf-math.frexp"><code>math.frexp (x)</code></a></h3>
-
-
-<p>
-Returns <code>m</code> and <code>e</code> such that <em>x = m2<sup>e</sup></em>,
-<code>e</code> is an integer and the absolute value of <code>m</code> is
-in the range <em>[0.5, 1)</em>
-(or zero when <code>x</code> is zero).
+that rounds the quotient towards zero. (integer/float)
@@ -8888,8 +9008,8 @@ in the range <em>[0.5, 1)</em>
<p>
-The value <code>HUGE_VAL</code>,
-a value larger than or equal to any other numerical value.
+The float value <code>HUGE_VAL</code>,
+a value larger than any other numerical value.
@@ -8907,16 +9027,6 @@ returns <b>nil</b>.
<p>
-<hr><h3><a name="pdf-math.ldexp"><code>math.ldexp (m, e)</code></a></h3>
-
-
-<p>
-Returns <em>m2<sup>e</sup></em> (<code>e</code> should be an integer).
-
-
-
-
-<p>
<hr><h3><a name="pdf-math.log"><code>math.log (x [, base])</code></a></h3>
@@ -8933,49 +9043,54 @@ The default for <code>base</code> is <em>e</em>
<p>
-Returns the maximum value among its arguments.
+Returns the argument with the maximum value,
+according to the Lua operator <code>&lt;</code>. (integer/float)
<p>
-<hr><h3><a name="pdf-math.min"><code>math.min (x, &middot;&middot;&middot;)</code></a></h3>
+<hr><h3><a name="pdf-math.maxinteger"><code>math.maxinteger</code></a></h3>
+An integer with the maximum value for an integer.
-<p>
-Returns the minimum value among its arguments.
+<p>
+<hr><h3><a name="pdf-math.min"><code>math.min (x, &middot;&middot;&middot;)</code></a></h3>
<p>
-<hr><h3><a name="pdf-math.modf"><code>math.modf (x)</code></a></h3>
+Returns the argument with the minimum value,
+according to the Lua operator <code>&lt;</code>. (integer/float)
+
+
<p>
-Returns two numbers,
-the integral part of <code>x</code> and the fractional part of <code>x</code>.
+<hr><h3><a name="pdf-math.mininteger"><code>math.mininteger</code></a></h3>
+An integer with the minimum value for an integer.
<p>
-<hr><h3><a name="pdf-math.pi"><code>math.pi</code></a></h3>
+<hr><h3><a name="pdf-math.modf"><code>math.modf (x)</code></a></h3>
<p>
-The value of <em>&pi;</em>.
+Returns the integral part of <code>x</code> and the fractional part of <code>x</code>.
+Its second result is always a float.
<p>
-<hr><h3><a name="pdf-math.pow"><code>math.pow (x, y)</code></a></h3>
+<hr><h3><a name="pdf-math.pi"><code>math.pi</code></a></h3>
<p>
-Returns <em>x<sup>y</sup></em>.
-(You can also use the expression <code>x^y</code> to compute this value.)
+The value of <em>&pi;</em>.
@@ -8985,7 +9100,7 @@ Returns <em>x<sup>y</sup></em>.
<p>
-Returns the angle <code>x</code> (given in degrees) in radians.
+Converts the angle <code>x</code> from degrees to radians.
@@ -8995,21 +9110,22 @@ Returns the angle <code>x</code> (given in degrees) in radians.
<p>
-This function is an interface to the simple
-pseudo-random generator function <code>rand</code> provided by Standard&nbsp;C.
-(No guarantees can be given for its statistical properties.)
-
-
-<p>
When called without arguments,
-returns a uniform pseudo-random float
-in the range <em>[0,1)</em>.
+returns a pseudo-random float with uniform distribution
+in the range <em>[0,1)</em>.
When called with two integers <code>m</code> and <code>n</code>,
-<code>math.random</code> returns a uniform pseudo-random
-integer in the range <em>[m, n]</em>.
+<code>math.random</code> returns a pseudo-random integer
+with uniform distribution in the range <em>[m, n]</em>.
+(The interval size must fit in a Lua integer.)
The call <code>math.random(n)</code> is equivalent to <code>math.random(1,n)</code>.
+<p>
+This function is an interface to the underling
+pseudo-random generator function provided by C.
+No guarantees can be given for its statistical properties.
+
+
<p>
@@ -9035,16 +9151,6 @@ Returns the sine of <code>x</code> (assumed to be in radians).
<p>
-<hr><h3><a name="pdf-math.sinh"><code>math.sinh (x)</code></a></h3>
-
-
-<p>
-Returns the hyperbolic sine of <code>x</code>.
-
-
-
-
-<p>
<hr><h3><a name="pdf-math.sqrt"><code>math.sqrt (x)</code></a></h3>
@@ -9066,16 +9172,6 @@ Returns the tangent of <code>x</code> (assumed to be in radians).
<p>
-<hr><h3><a name="pdf-math.tanh"><code>math.tanh (x)</code></a></h3>
-
-
-<p>
-Returns the hyperbolic tangent of <code>x</code>.
-
-
-
-
-<p>
<hr><h3><a name="pdf-math.type"><code>math.type (x)</code></a></h3>
@@ -9337,7 +9433,7 @@ Returns an iterator function that,
each time it is called,
reads the file according to the given formats.
When no format is given,
-uses "*l" as a default.
+uses "<code>l</code>" as a default.
As an example, the construction
<pre>
@@ -9376,30 +9472,33 @@ The available formats are
<ul>
-<li><b>"<code>*n</code>": </b>
-reads a number and returns it as a float.
-If the input has only a prefix of a valid number
-(e.g., "<code>0x</code>" or "<code>3.4e-</code>"),
-this format can read the entire prefix
-even when returning <b>nil</b>.
+<li><b>"<code>n</code>": </b>
+reads a numeral and returns it as a float or an integer,
+following the lexical conventions of Lua.
+(The numeral may have leading spaces and a sign.)
+This format always reads the longest input sequence that
+is a valid prefix for a number;
+if that prefix does not form a valid number
+(e.g., an empty string, "<code>0x</code>", or "<code>3.4e-</code>"),
+it is discarded and the function returns <b>nil</b>.
</li>
-<li><b>"<code>*i</code>": </b>
+<li><b>"<code>i</code>": </b>
reads an integral number and returns it as an integer.
</li>
-<li><b>"<code>*a</code>": </b>
+<li><b>"<code>a</code>": </b>
reads the whole file, starting at the current position.
On end of file, it returns the empty string.
</li>
-<li><b>"<code>*l</code>": </b>
+<li><b>"<code>l</code>": </b>
reads the next line skipping the end of line,
returning <b>nil</b> on end of file.
This is the default format.
</li>
-<li><b>"<code>*L</code>": </b>
+<li><b>"<code>L</code>": </b>
reads the next line keeping the end-of-line character (if present),
returning <b>nil</b> on end of file.
</li>
@@ -9413,7 +9512,7 @@ or <b>nil</b> on end of file.
</li>
</ul><p>
-The formats "<code>*l</code>" and "<code>*L</code>" should be used only for text files.
+The formats "<code>l</code>" and "<code>L</code>" should be used only for text files.
@@ -9622,7 +9721,7 @@ When called without a <code>command</code>,
<p>
-<hr><h3><a name="pdf-os.exit"><code>os.exit ([code [, close])</code></a></h3>
+<hr><h3><a name="pdf-os.exit"><code>os.exit ([code [, close]])</code></a></h3>
<p>
@@ -9800,6 +9899,32 @@ The default is always the current thread.
<p>
+<hr><h3><a name="pdf-debug.Csize"><code>debug.Csize (t)</code></a></h3>
+
+
+<p>
+Returns the size of the underlying representation of a given C type,
+according to the following table:
+<table border="1">
+<tr><td>'<code>I</code>'</td><td><code>lua_Integer</code></td></tr>
+<tr><td>'<code>F</code>'</td><td><code>lua_Number</code></td></tr>
+<tr><td>'<code>b</code>'</td><td><code>byte</code></td></tr>
+<tr><td>'<code>d</code>'</td><td><code>double</code></td></tr>
+<tr><td>'<code>f</code>'</td><td><code>float</code></td></tr>
+<tr><td>'<code>h</code>'</td><td><code>short int</code></td></tr>
+<tr><td>'<code>i</code>'</td><td><code>int</code></td></tr>
+<tr><td>'<code>l</code>'</td><td><code>long int</code></td></tr>
+<tr><td>'<code>z</code>'</td><td><code>size_t</code></td></tr>
+</table>
+For all options except '<code>b</code>',
+the size is given in number of bytes;
+for option '<code>b</code>',
+the size is its number of bits.
+
+
+
+
+<p>
<hr><h3><a name="pdf-debug.debug"><code>debug.debug ()</code></a></h3>
@@ -9898,7 +10023,7 @@ and raises an error when called with a level out of range.
<p>
-Variable names starting with '<code>(</code>' (open parenthesis)
+Variable names starting with '<code>(</code>' (open parenthesis)
represent variables with no known names
(internal variables like loop control variables,
and variables from chunks saved without debug information).
@@ -9943,7 +10068,7 @@ The function returns <b>nil</b> if there is no upvalue with the given index.
<p>
-Variable names starting with '<code>(</code>' (open parenthesis)
+Variable names starting with '<code>(</code>' (open parenthesis)
represent variables with no known names
(variables from chunks saved without debug information).
@@ -9963,18 +10088,6 @@ returns <b>nil</b>.
<p>
-<hr><h3><a name="pdf-debug.numbits"><code>debug.numbits (t)</code></a></h3>
-
-
-<p>
-Returns the number of bits in the underlying representation
-of an integer (if <code>t</code> is "<code>i</code>")
-or a float (if <code>t</code> is "<code>f</code>").
-
-
-
-
-<p>
<hr><h3><a name="pdf-debug.sethook"><code>debug.sethook ([thread,] hook, mask [, count])</code></a></h3>
@@ -10169,7 +10282,7 @@ and as <code>lua -</code> otherwise.
<p>
When called without option <code>-E</code>,
-the interpreter checks for an environment variable <a name="pdf-LUA_INIT_5_2"><code>LUA_INIT_5_2</code></a>
+the interpreter checks for an environment variable <a name="pdf-LUA_INIT_5_3"><code>LUA_INIT_5_3</code></a>
(or <a name="pdf-LUA_INIT"><code>LUA_INIT</code></a> if it is not defined)
before running any argument.
If the variable content has the format <code>@<em>filename</em></code>,
@@ -10200,37 +10313,46 @@ and finally run the file <code>script.lua</code> with no arguments.
<p>
-Before starting to run the script,
-<code>lua</code> collects all arguments in the command line
+Before running any code,
+<code>lua</code> collects all command-line arguments
in a global table called <code>arg</code>.
-The script name is stored at index 0,
+The script name goes to index 0,
the first argument after the script name goes to index 1,
and so on.
Any arguments before the script name
-(that is, the interpreter name plus the options)
+(that is, the interpreter name plus its options)
go to negative indices.
For instance, in the call
<pre>
$ lua -la b.lua t1 t2
</pre><p>
-the interpreter first runs the file <code>a.lua</code>,
-then creates a table
+the table is like this:
<pre>
arg = { [-2] = "lua", [-1] = "-la",
[0] = "b.lua",
[1] = "t1", [2] = "t2" }
</pre><p>
-and finally runs the file <code>b.lua</code>.
-The script is called with <code>arg[1]</code>, <code>arg[2]</code>, ...
-as arguments;
-it can also access these arguments with the vararg expression '<code>...</code>'.
+If there is no script in the call,
+the interpreter name goes to index 0,
+followed by the other arguments.
+For instance, the call
+
+<pre>
+ $ lua -e "print(arg[1])"
+</pre><p>
+will print "<code>-e</code>".
<p>
In interactive mode,
-if you write an incomplete statement,
+Lua repeatedly prompts and waits for a line.
+After reading a line,
+Lua first try to interpret the line as an expression.
+If it succeeds, it prints its value.
+Otherwise, it interprets the line as a statement.
+If you write an incomplete statement,
the interpreter waits for its completion
by issuing a different prompt.
@@ -10302,6 +10424,12 @@ using a new version.
<p>
+Similarly, Lua versions can always change the internal representation
+of precompiled chunks;
+precompiled chunks are never compatible between different Lua versions.
+
+
+<p>
The standard paths in the official distribution may
change between versions.
@@ -10325,8 +10453,8 @@ You can fix these differences by forcing a number to be a float
in particular writing constants with an ending <code>.0</code>
or using <code>x = x + 0.0</code> to convert a variable.
(This recommendation is only for a quick fix
-for an occasional incompatibility,
-not as a general guideline for good programming.
+for an occasional incompatibility;
+it is not a general guideline for good programming.
For good programming,
use floats where you need floats
and integers where you need integers.)
@@ -10335,7 +10463,22 @@ and integers where you need integers.)
<p>
Although not formally an incompatibility,
the proper differentiation between floats and integers
-can sometimes have a big impact on performance.
+have an impact on performance.
+</li>
+
+<li>
+The conversion of a float to a string now adds a <code>.0</code> suffix
+to the result if it looks like an integer.
+(For instance, the float 2.0 will be printed as <code>2.0</code>,
+not as <code>2</code>.)
+You should always use an explicit format
+when you need a specific format for numbers.
+
+
+<p>
+(Formally this is not an incompatibility,
+because Lua does not specify how numbers are formatted as strings,
+but some programs assumed a specific format.)
</li>
<li>
@@ -10352,23 +10495,30 @@ The generational mode for the garbage collector was removed.
<ul>
<li>
-The conversion of a float to a string through <a href="#pdf-tostring"><code>tostring</code></a>
-(which is used by <a href="#pdf-print"><code>print</code></a>) now adds a <code>.0</code> suffix if the
-number has an integral value.
-(For instance, the float 2.0 will be printed as <code>2.0</code>,
-not as <code>2</code>.)
-You should always use an explicit format
-when you need a specific format for numbers.
-</li>
-
-<li>
The <code>bit32</code> library has been deprecated.
It is easy to require a compatible external library or,
better yet, to replace its functions with appropriate bitwise operations.
-(Just keep in mind that <code>bit32</code> operates on 32-bit integers,
+(Keep in mind that <code>bit32</code> operates on 32-bit integers,
while the bitwise operators in Standard Lua operate on 64-bit integers.)
</li>
+<li>
+Option names in <a href="#pdf-io.read"><code>io.read</code></a> do not have a starting '<code>*</code>' anymore.
+For compatibility, Lua will continue to ignore this character.
+</li>
+
+<li>
+The following functions were deprecated in the mathematical library:
+<code>atan2</code>, <code>cosh</code>, <code>sinh</code>, <code>tanh</code>, <code>pow</code>,
+<code>frexp</code>, and <code>ldexp</code>.
+You can replace <code>math.pow(x,y)</code> with <code>x^y</code>;
+you can replace <code>math.atan2</code> with <code>math.atan</code>,
+which now accepts two parameters;
+you can replace <code>math.ldexp(x,exp)</code> with <code>x * 2.0^exp</code>.
+For the other operations,
+the best choice is to use an external library.
+</li>
+
</ul>
@@ -10380,7 +10530,15 @@ while the bitwise operators in Standard Lua operate on 64-bit integers.)
<ul>
<li>
-No changes (yet).
+Continuation functions now receive as parameters what they needed
+to get through <code>lua_getctx</code>,
+so <code>lua_getctx</code> has been removed.
+Adapt your code accordingly.
+</li>
+
+<li>
+Function <a href="#lua_dump"><code>lua_dump</code></a> has an extra parameter, <code>strip</code>.
+Use 0 as the value of this parameter to get the old behavior.
</li>
</ul>
@@ -10456,11 +10614,12 @@ Here is the complete syntax of Lua in extended BNF.
fieldsep ::= &lsquo;<b>,</b>&rsquo; | &lsquo;<b>;</b>&rsquo;
- binop ::= &lsquo;<b>+</b>&rsquo; | &lsquo;<b>-</b>&rsquo; | &lsquo;<b>*</b>&rsquo; | &lsquo;<b>/</b>&rsquo; | &lsquo;<b>^</b>&rsquo; | &lsquo;<b>%</b>&rsquo; | &lsquo;<b>..</b>&rsquo; |
+ binop ::= &lsquo;<b>+</b>&rsquo; | &lsquo;<b>-</b>&rsquo; | &lsquo;<b>*</b>&rsquo; | &lsquo;<b>/</b>&rsquo; | &lsquo;<b>//</b>&rsquo; | &lsquo;<b>^</b>&rsquo; | &lsquo;<b>%</b>&rsquo; |
+ &lsquo;<b>&amp;</b>&rsquo; | &lsquo;<b>~</b>&rsquo; | &lsquo;<b>|</b>&rsquo; | &lsquo;<b>&gt;&gt;</b>&rsquo; | &lsquo;<b>&lt;&lt;</b>&rsquo; | &lsquo;<b>..</b>&rsquo; |
&lsquo;<b>&lt;</b>&rsquo; | &lsquo;<b>&lt;=</b>&rsquo; | &lsquo;<b>&gt;</b>&rsquo; | &lsquo;<b>&gt;=</b>&rsquo; | &lsquo;<b>==</b>&rsquo; | &lsquo;<b>~=</b>&rsquo; |
<b>and</b> | <b>or</b>
- unop ::= &lsquo;<b>-</b>&rsquo; | <b>not</b> | &lsquo;<b>#</b>&rsquo;
+ unop ::= &lsquo;<b>-</b>&rsquo; | <b>not</b> | &lsquo;<b>#</b>&rsquo; | &lsquo;<b>~</b>&rsquo;
</pre>
@@ -10468,17 +10627,18 @@ Here is the complete syntax of Lua in extended BNF.
-}
+
+
<HR>
<SMALL CLASS="footer">
Last update:
-Fri Mar 21 17:33:56 BRT 2014
+Thu Jun 19 17:13:19 BRT 2014
</SMALL>
<!--
-Last change: updated for Lua 5.3.0 (work2)
+Last change: updated for Lua 5.3.0 (work3)
-->
</body></html>
diff --git a/doc/readme.html b/doc/readme.html
index edb319d3..6c9ec1e1 100644
--- a/doc/readme.html
+++ b/doc/readme.html
@@ -31,7 +31,7 @@ tt, kbd, code {
<HR>
<H1>
<A HREF="http://www.lua.org/"><IMG SRC="logo.gif" ALT="Lua" BORDER=0></A>
-Welcome to Lua 5.3 (work2)
+Welcome to Lua 5.3 (work3)
</H1>
<P>
@@ -102,8 +102,8 @@ If you don't have the time or the inclination to compile Lua yourself,
get a binary from
<A HREF="http://lua-users.org/wiki/LuaBinaries">LuaBinaries</A>.
Try also
-<A HREF="http://luaforwindows.luaforge.net/">Lua for Windows</A>,
-an easy-to-use distribution of Lua that includes many useful libraries.
+<A HREF="http://luadist.org/">LuaDist</A>,
+a multi-platform distribution of Lua that includes batteries.
<H3>Building Lua</H3>
@@ -114,8 +114,8 @@ Here are the details.
<OL>
<LI>
Open a terminal window and move to
-the top-level directory, which is named <TT>lua-5.3.0</TT>.
-The Makefile there controls both the build process and the installation process.
+the top-level directory, which is named <TT>lua-5.3.0-work3</TT>.
+The <TT>Makefile</TT> there controls both the build process and the installation process.
<P>
<LI>
Do "<KBD>make</KBD>" and see if your platform is listed.
@@ -140,7 +140,7 @@ and liblua.a (the library).
<P>
<LI>
To check that Lua has been built correctly, do "<KBD>make test</KBD>"
- after building Lua. This will run the interpreter and print its version string.
+ after building Lua. This will run the interpreter and print its version.
</OL>
<P>
If you're running Linux and get compilation errors,
@@ -152,7 +152,7 @@ then try "<KBD>make linux MYLIBS=-ltermcap</KBD>".
<P>
Once you have built Lua, you may want to install it in an official
place in your system. In this case, do "<KBD>make install</KBD>". The official
- place and the way to install files are defined in the Makefile. You'll
+ place and the way to install files are defined in the <TT>Makefile</TT>. You'll
probably need the right permissions to install files.
<P>
@@ -162,11 +162,13 @@ then try "<KBD>make linux MYLIBS=-ltermcap</KBD>".
<P>
To install Lua locally, do "<KBD>make local</KBD>".
This will create a directory <TT>install</TT> with subdirectories
- <TT>bin</TT>, <TT>include</TT>, <TT>lib</TT>, <TT>man</TT>,
+ <TT>bin</TT>, <TT>include</TT>, <TT>lib</TT>, <TT>man</TT>, <TT>share</TT>,
and install Lua as listed below.
To install Lua locally, but in some other directory, do
"<KBD>make install INSTALL_TOP=xxx</KBD>", where xxx is your chosen directory.
+ The installation starts in the <TT>src</TT> and <TT>doc</TT> directories,
+ so take care if <TT>INSTALL_TOP</TT> is not an absolute path.
<DL CLASS="display">
<DT>
@@ -176,7 +178,7 @@ then try "<KBD>make linux MYLIBS=-ltermcap</KBD>".
<DT>
include:
<DD>
- lua.h luaconf.h lualib.h lauxlib.h lua.hpp
+ lauxlib.h lua.h lua.hpp luaconf.h lualib.h
<DT>
lib:
<DD>
@@ -190,8 +192,8 @@ then try "<KBD>make linux MYLIBS=-ltermcap</KBD>".
<P>
These are the only directories you need for development.
If you only want to run Lua programs,
- you only need the files in bin and man.
- The files in include and lib are needed for
+ you only need the files in <TT>bin</TT> and <TT>man</TT>.
+ The files in <TT>include</TT> and <TT>lib</TT> are needed for
embedding Lua in C or C++ programs.
<H3><A NAME="customization">Customization</A></H3>
@@ -207,7 +209,7 @@ then try "<KBD>make linux MYLIBS=-ltermcap</KBD>".
You don't actually need to edit the Makefiles because you may set the
relevant variables in the command line when invoking make.
Nevertheless, it's probably best to edit and save the Makefiles to
- record the changes you need.
+ record the changes you've made.
<P>
On the other hand, if you need to customize some Lua features, you'll need
@@ -216,11 +218,6 @@ then try "<KBD>make linux MYLIBS=-ltermcap</KBD>".
it will be used by any Lua clients that you build, to ensure consistency.
Further customization is available to experts by editing the Lua sources.
-<P>
- We strongly recommend that you enable dynamic loading in <TT>src/luaconf.h</TT>.
- This is done automatically for all platforms listed above that have
- this feature and also for Windows.
-
<H3><A NAME="other">Building Lua on other systems</A></H3>
<P>
@@ -357,10 +354,10 @@ THE SOFTWARE.
<HR>
<SMALL CLASS="footer">
Last update:
-Fri Mar 21 17:33:08 BRT 2014
+Wed Jun 11 22:54:18 BRT 2014
</SMALL>
<!--
-Last change: updated for Lua 5.3.0 (work2)
+Last change: updated for Lua 5.3.0 (work3)
-->
</BODY>
diff --git a/src/.fix b/src/.fix
deleted file mode 100644
index 16915891..00000000
--- a/src/.fix
+++ /dev/null
@@ -1,2 +0,0 @@
-#define nvalue(x) ((lua_Number)0)
-#define ttypenv(x) ttnov(x)
diff --git a/src/Makefile b/src/Makefile
index 45e1ac9e..4b357ce1 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -109,7 +109,7 @@ macosx:
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_MACOSX" SYSLIBS="-lreadline" CC=cc
mingw:
- $(MAKE) "LUA_A=lua52.dll" "LUA_T=lua.exe" \
+ $(MAKE) "LUA_A=lua53.dll" "LUA_T=lua.exe" \
"AR=$(CC) -shared -o" "RANLIB=strip --strip-unneeded" \
"SYSCFLAGS=-DLUA_BUILD_AS_DLL" "SYSLIBS=" "SYSLDFLAGS=-s" lua.exe
$(MAKE) "LUAC_T=luac.exe" luac.exe
@@ -118,7 +118,7 @@ posix:
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX"
solaris:
- $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-ldl"
+ $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN -D_REENTRANT" SYSLIBS="-ldl"
# list targets that do not create files (but not all makes understand .PHONY)
.PHONY: all $(PLATS) default o a clean depend echo none
diff --git a/src/lapi.c b/src/lapi.c
index 923297dc..b726e3c5 100644
--- a/src/lapi.c
+++ b/src/lapi.c
@@ -1,5 +1,5 @@
/*
-** $Id: lapi.c,v 2.201 2014/03/12 20:57:40 roberto Exp $
+** $Id: lapi.c,v 2.219 2014/06/19 18:27:20 roberto Exp $
** Lua API
** See Copyright Notice in lua.h
*/
@@ -94,6 +94,7 @@ LUA_API int lua_checkstack (lua_State *L, int size) {
int res;
CallInfo *ci = L->ci;
lua_lock(L);
+ api_check(L, size >= 0, "negative 'size'");
if (L->stack_last - L->top > size) /* stack large enough? */
res = 1; /* yes; check is OK */
else { /* no; need to grow stack */
@@ -180,26 +181,35 @@ LUA_API void lua_settop (lua_State *L, int idx) {
}
-LUA_API void lua_remove (lua_State *L, int idx) {
- StkId p;
- lua_lock(L);
- p = index2addr(L, idx);
- api_checkstackindex(L, idx, p);
- while (++p < L->top) setobjs2s(L, p-1, p);
- L->top--;
- lua_unlock(L);
+/*
+** Reverse the stack segment from 'from' to 'to'
+** (auxiliar to 'lua_rotate')
+*/
+static void reverse (lua_State *L, StkId from, StkId to) {
+ for (; from < to; from++, to--) {
+ TValue temp;
+ setobj(L, &temp, from);
+ setobjs2s(L, from, to);
+ setobj2s(L, to, &temp);
+ }
}
-LUA_API void lua_insert (lua_State *L, int idx) {
- StkId p;
- StkId q;
+/*
+** Let x = AB, where A is a prefix of length 'n'. Then,
+** rotate x n == BA. But BA == (A^r . B^r)^r.
+*/
+LUA_API void lua_rotate (lua_State *L, int idx, int n) {
+ StkId p, t, m;
lua_lock(L);
- p = index2addr(L, idx);
+ t = L->top - 1; /* end of stack segment being rotated */
+ p = index2addr(L, idx); /* start of segment */
api_checkstackindex(L, idx, p);
- for (q = L->top; q > p; q--) /* use L->top as a temporary */
- setobjs2s(L, q, q - 1);
- setobjs2s(L, p, L->top);
+ api_check(L, (n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'");
+ m = (n >= 0 ? t - n : p - n - 1); /* end of prefix */
+ reverse(L, p, m); /* reverse the prefix with length 'n' */
+ reverse(L, m + 1, t); /* reverse the suffix */
+ reverse(L, p, t); /* reverse the entire segment */
lua_unlock(L);
}
@@ -332,18 +342,11 @@ LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) {
}
-LUA_API int lua_strtonum (lua_State *L, const char *s, size_t len) {
- lua_Integer i; lua_Number n;
- if (luaO_str2int(s, len, &i)) { /* try as an integer */
- setivalue(L->top, i);
- }
- else if (luaO_str2d(s, len, &n)) { /* else try as a float */
- setnvalue(L->top, n);
- }
- else
- return 0; /* conversion failed */
- api_incr_top(L);
- return 1;
+LUA_API size_t lua_strtonum (lua_State *L, const char *s) {
+ size_t sz = luaO_str2num(s, L->top);
+ if (sz != 0)
+ api_incr_top(L);
+ return sz;
}
@@ -375,12 +378,12 @@ LUA_API lua_Unsigned lua_tounsignedx (lua_State *L, int idx, int *pisnum) {
int isnum = 0;
switch (ttype(o)) {
case LUA_TNUMINT: {
- res = cast_unsigned(ivalue(o));
+ res = l_castS2U(ivalue(o));
isnum = 1;
break;
}
case LUA_TNUMFLT: { /* compute floor(n) % 2^(numbits in an integer) */
- const lua_Number twop = cast_num(MAX_UINTEGER) + cast_num(1); /* 2^n */
+ const lua_Number two2n = cast_num(LUA_MAXUNSIGNED) + cast_num(1);
lua_Number n = fltvalue(o); /* get value */
int neg = 0;
n = l_floor(n); /* get its floor */
@@ -388,10 +391,10 @@ LUA_API lua_Unsigned lua_tounsignedx (lua_State *L, int idx, int *pisnum) {
neg = 1;
n = -n; /* make 'n' positive, so that 'fmod' is the same as '%' */
}
- n = l_mathop(fmod)(n, twop); /* n = n % 2^(numbits in an integer) */
+ n = l_mathop(fmod)(n, two2n); /* n = n % 2^(numbits in an integer) */
if (luai_numisnan(n)) /* not a number? */
break; /* not an integer, too */
- res = cast_unsigned(n); /* 'n' now must fit in an unsigned */
+ res = cast(lua_Unsigned, n); /* 'n' now must fit in an unsigned */
if (neg) res = 0u - res; /* back to negative, if needed */
isnum = 1;
break;
@@ -495,9 +498,7 @@ LUA_API void lua_pushnil (lua_State *L) {
LUA_API void lua_pushnumber (lua_State *L, lua_Number n) {
lua_lock(L);
- setnvalue(L->top, n);
- luai_checknum(L, L->top,
- luaG_runerror(L, "C API - attempt to push a signaling NaN"));
+ setfltvalue(L->top, n);
api_incr_top(L);
lua_unlock(L);
}
@@ -513,7 +514,7 @@ LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) {
LUA_API void lua_pushunsigned (lua_State *L, lua_Unsigned u) {
lua_lock(L);
- setivalue(L->top, cast_integer(u));
+ setivalue(L->top, l_castU2S(u));
api_incr_top(L);
lua_unlock(L);
}
@@ -579,15 +580,15 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
setfvalue(L->top, fn);
}
else {
- Closure *cl;
+ CClosure *cl;
api_checknelems(L, n);
api_check(L, n <= MAXUPVAL, "upvalue index too large");
luaC_checkGC(L);
cl = luaF_newCclosure(L, n);
- cl->c.f = fn;
+ cl->f = fn;
L->top -= n;
while (n--) {
- setobj2n(L, &cl->c.upvalue[n], L->top + n);
+ setobj2n(L, &cl->upvalue[n], L->top + n);
/* does not need barrier because closure is white */
}
setclCvalue(L, L->top, cl);
@@ -741,7 +742,7 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) {
}
-LUA_API void lua_getuservalue (lua_State *L, int idx) {
+LUA_API int lua_getuservalue (lua_State *L, int idx) {
StkId o;
lua_lock(L);
o = index2addr(L, idx);
@@ -749,6 +750,7 @@ LUA_API void lua_getuservalue (lua_State *L, int idx) {
getuservalue(L, rawuvalue(o), L->top);
api_incr_top(L);
lua_unlock(L);
+ return ttnov(L->top - 1);
}
@@ -898,17 +900,8 @@ LUA_API void lua_setuservalue (lua_State *L, int idx) {
"results from function overflow current stack size")
-LUA_API int lua_getctx (lua_State *L, int *ctx) {
- if (L->ci->callstatus & CIST_YIELDED) {
- if (ctx) *ctx = L->ci->u.c.ctx;
- return L->ci->u.c.status;
- }
- else return LUA_OK;
-}
-
-
LUA_API void lua_callk (lua_State *L, int nargs, int nresults, int ctx,
- lua_CFunction k) {
+ lua_KFunction k) {
StkId func;
lua_lock(L);
api_check(L, k == NULL || !isLua(L->ci),
@@ -947,7 +940,7 @@ static void f_call (lua_State *L, void *ud) {
LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc,
- int ctx, lua_CFunction k) {
+ int ctx, lua_KFunction k) {
struct CallS c;
int status;
ptrdiff_t func;
@@ -975,11 +968,10 @@ LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc,
ci->u.c.ctx = ctx; /* save context */
/* save information for error recovery */
ci->extra = savestack(L, c.func);
- ci->u.c.old_allowhook = L->allowhook;
ci->u.c.old_errfunc = L->errfunc;
L->errfunc = func;
- /* mark that function may do error recovery */
- ci->callstatus |= CIST_YPCALL;
+ setoah(ci->callstatus, L->allowhook); /* save value of 'allowhook' */
+ ci->callstatus |= CIST_YPCALL; /* function can do error recovery */
luaD_call(L, c.func, nresults, 1); /* do the call */
ci->callstatus &= ~CIST_YPCALL;
L->errfunc = ci->u.c.old_errfunc;
diff --git a/src/lauxlib.c b/src/lauxlib.c
index 8007c1fb..df0e5156 100644
--- a/src/lauxlib.c
+++ b/src/lauxlib.c
@@ -1,5 +1,5 @@
/*
-** $Id: lauxlib.c,v 1.260 2014/03/12 20:57:40 roberto Exp $
+** $Id: lauxlib.c,v 1.263 2014/05/12 21:44:17 roberto Exp $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/
@@ -397,7 +397,7 @@ LUALIB_API lua_Number luaL_optnumber (lua_State *L, int arg, lua_Number def) {
static void interror (lua_State *L, int arg) {
if (lua_type(L, arg) == LUA_TNUMBER)
- luaL_argerror(L, arg, "float value out of range");
+ luaL_argerror(L, arg, "float value out of integer range");
else
tag_error(L, arg, LUA_TNUMBER);
}
@@ -757,13 +757,8 @@ LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) {
case LUA_TNUMBER: {
if (lua_isinteger(L, idx))
lua_pushfstring(L, "%I", lua_tointeger(L, idx));
- else {
- const char *s = lua_pushfstring(L, "%f", lua_tonumber(L, idx));
- if (s[strspn(s, "-0123456789")] == '\0') { /* looks like an int? */
- lua_pushliteral(L, ".0"); /* add a '.0' to result */
- lua_concat(L, 2);
- }
- }
+ else
+ lua_pushfstring(L, "%f", lua_tonumber(L, idx));
break;
}
case LUA_TSTRING:
@@ -966,12 +961,12 @@ LUALIB_API lua_State *luaL_newstate (void) {
}
-LUALIB_API void luaL_checkversion_ (lua_State *L, int ver, size_t sz) {
+LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver, size_t sz) {
const lua_Number *v = lua_version(L);
if (v != lua_version(NULL))
luaL_error(L, "multiple Lua VMs detected");
else if (*v != ver)
- luaL_error(L, "version mismatch: app. needs %d, Lua core provides %f",
+ luaL_error(L, "version mismatch: app. needs %f, Lua core provides %f",
ver, *v);
/* check numeric types */
if (sz != LUAL_NUMSIZES)
diff --git a/src/lauxlib.h b/src/lauxlib.h
index 55871c5a..3ffe3561 100644
--- a/src/lauxlib.h
+++ b/src/lauxlib.h
@@ -1,5 +1,5 @@
/*
-** $Id: lauxlib.h,v 1.123 2014/01/05 14:04:46 roberto Exp $
+** $Id: lauxlib.h,v 1.124 2014/04/15 18:25:49 roberto Exp $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/
@@ -28,7 +28,7 @@ typedef struct luaL_Reg {
#define LUAL_NUMSIZES (sizeof(lua_Integer)*16 + sizeof(lua_Number))
-LUALIB_API void (luaL_checkversion_) (lua_State *L, int ver, size_t sz);
+LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver, size_t sz);
#define luaL_checkversion(L) \
luaL_checkversion_(L, LUA_VERSION_NUM, LUAL_NUMSIZES)
diff --git a/src/lbaselib.c b/src/lbaselib.c
index 4f43824c..deefe6c6 100644
--- a/src/lbaselib.c
+++ b/src/lbaselib.c
@@ -1,5 +1,5 @@
/*
-** $Id: lbaselib.c,v 1.285 2014/03/12 20:57:40 roberto Exp $
+** $Id: lbaselib.c,v 1.289 2014/06/10 17:41:38 roberto Exp $
** Basic library
** See Copyright Notice in lua.h
*/
@@ -45,31 +45,31 @@ static int luaB_print (lua_State *L) {
#define SPACECHARS " \f\n\r\t\v"
-static int b_str2int (const char *s, const char *e, int base, lua_Integer *pn) {
+static const char *b_str2int (const char *s, int base, lua_Integer *pn) {
lua_Unsigned n = 0;
int neg = 0;
s += strspn(s, SPACECHARS); /* skip initial spaces */
if (*s == '-') { s++; neg = 1; } /* handle signal */
else if (*s == '+') s++;
if (!isalnum((unsigned char)*s)) /* no digit? */
- return 0;
+ return NULL;
do {
int digit = (isdigit((unsigned char)*s)) ? *s - '0'
: toupper((unsigned char)*s) - 'A' + 10;
- if (digit >= base) return 0; /* invalid numeral */
+ if (digit >= base) return NULL; /* invalid numeral */
n = n * base + digit;
s++;
} while (isalnum((unsigned char)*s));
s += strspn(s, SPACECHARS); /* skip trailing spaces */
- if (s != e) /* invalid trailing characters? */
- return 0;
+ if (*s != '\0') /* invalid trailing characters? */
+ return NULL;
*pn = (lua_Integer)((neg) ? (0u - n) : n);
- return 1;
+ return s;
}
static int luaB_tonumber (lua_State *L) {
- if (lua_isnoneornil(L, 2)) { /* standard conversion */
+ if (lua_isnoneornil(L, 2)) { /* standard conversion? */
luaL_checkany(L, 1);
if (lua_type(L, 1) == LUA_TNUMBER) { /* already a number? */
lua_settop(L, 1); /* yes; return it */
@@ -78,20 +78,20 @@ static int luaB_tonumber (lua_State *L) {
else {
size_t l;
const char *s = lua_tolstring(L, 1, &l);
- if (s != NULL && lua_strtonum(L, s, l)) /* can convert to a number? */
- return 1;
+ if (s != NULL && lua_strtonum(L, s) == l + 1)
+ return 1; /* successful conversion to number */
/* else not a number */
}
}
else {
size_t l;
const char *s;
- lua_Integer n;
+ lua_Integer n = 0; /* to avoid warnings */
int base = luaL_checkint(L, 2);
luaL_checktype(L, 1, LUA_TSTRING); /* before 'luaL_checklstring'! */
s = luaL_checklstring(L, 1, &l);
luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
- if (b_str2int(s, s + l, base, &n)) {
+ if (b_str2int(s, base, &n) == s + l) {
lua_pushinteger(L, n);
return 1;
} /* else not a number */
@@ -341,7 +341,8 @@ static int luaB_load (lua_State *L) {
/* }====================================================== */
-static int dofilecont (lua_State *L) {
+static int dofilecont (lua_State *L, int d1, int d2) {
+ (void)d1; (void)d2; /* only to match 'lua_Kfunction' prototype */
return lua_gettop(L) - 1;
}
@@ -352,14 +353,19 @@ static int luaB_dofile (lua_State *L) {
if (luaL_loadfile(L, fname) != LUA_OK)
return lua_error(L);
lua_callk(L, 0, LUA_MULTRET, 0, dofilecont);
- return dofilecont(L);
+ return dofilecont(L, 0, 0);
}
static int luaB_assert (lua_State *L) {
- if (!lua_toboolean(L, 1))
- return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!"));
- return lua_gettop(L);
+ if (lua_toboolean(L, 1)) /* condition is true? */
+ return lua_gettop(L); /* return all arguments */
+ else { /* error */
+ if (lua_isnone(L, 2)) /* no error message? */
+ lua_pushliteral(L, "assertion failed!"); /* use standard message */
+ lua_remove(L, 1); /* remove the condition (if there is one...) */
+ return luaB_error(L); /* call 'error' */
+ }
}
@@ -379,44 +385,48 @@ static int luaB_select (lua_State *L) {
}
-static int finishpcall (lua_State *L, int status) {
- if (!lua_checkstack(L, 1)) { /* no space for extra boolean? */
- lua_settop(L, 0); /* create space for return values */
- lua_pushboolean(L, 0);
- lua_pushstring(L, "stack overflow");
+/*
+** Continuation function for 'pcall' and 'xpcall'. Both functions
+** already pushed a 'true' before doing the call, so in case of sucess
+** 'finishpcall' only has to return everything in the stack minus
+** 'extra' values (where 'extra' is exactly the number of items to be
+** ignored).
+*/
+static int finishpcall (lua_State *L, int status, int extra) {
+ if (status != LUA_OK && status != LUA_YIELD) { /* error? */
+ lua_pushboolean(L, 0); /* first result (false) */
+ lua_pushvalue(L, -2); /* error message */
return 2; /* return false, msg */
}
- lua_pushboolean(L, status); /* first result (status) */
- lua_replace(L, 1); /* put first result in first slot */
- return lua_gettop(L);
-}
-
-
-static int pcallcont (lua_State *L) {
- int status = lua_getctx(L, NULL);
- return finishpcall(L, (status == LUA_YIELD));
+ else
+ return lua_gettop(L) - extra; /* return all results */
}
static int luaB_pcall (lua_State *L) {
int status;
luaL_checkany(L, 1);
- lua_pushnil(L);
- lua_insert(L, 1); /* create space for status result */
- status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, pcallcont);
- return finishpcall(L, (status == LUA_OK));
+ lua_pushboolean(L, 1); /* first result if no errors */
+ lua_insert(L, 1); /* put it in place */
+ status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, finishpcall);
+ return finishpcall(L, status, 0);
}
+/*
+** Do a protected call with error handling. After 'lua_rotate', the
+** stack will have <f, err, true, f, [args...]>; so, the function passes
+** 2 to 'finishpcall' to skip the 2 first values when returning results.
+*/
static int luaB_xpcall (lua_State *L) {
int status;
int n = lua_gettop(L);
- luaL_argcheck(L, n >= 2, 2, "value expected");
- lua_pushvalue(L, 1); /* exchange function... */
- lua_copy(L, 2, 1); /* ...and error handler */
- lua_replace(L, 2);
- status = lua_pcallk(L, n - 2, LUA_MULTRET, 1, 0, pcallcont);
- return finishpcall(L, (status == LUA_OK));
+ luaL_checktype(L, 2, LUA_TFUNCTION); /* check error function */
+ lua_pushboolean(L, 1); /* first result */
+ lua_pushvalue(L, 1); /* function */
+ lua_rotate(L, 3, 2); /* move them below function's arguments */
+ status = lua_pcallk(L, n - 2, LUA_MULTRET, 2, 2, finishpcall);
+ return finishpcall(L, status, 2);
}
diff --git a/src/lbitlib.c b/src/lbitlib.c
index ce5f0b0f..dfec1d31 100644
--- a/src/lbitlib.c
+++ b/src/lbitlib.c
@@ -1,5 +1,5 @@
/*
-** $Id: lbitlib.c,v 1.25 2014/03/20 19:22:16 roberto Exp $
+** $Id: lbitlib.c,v 1.26 2014/05/15 19:28:34 roberto Exp $
** Standard library for bitwise operations
** See Copyright Notice in lua.h
*/
@@ -221,8 +221,7 @@ LUAMOD_API int luaopen_bit32 (lua_State *L) {
LUAMOD_API int luaopen_bit32 (lua_State *L) {
- lua_pushnil(L);
- return 1;
+ return luaL_error(L, "library 'bit32' has been deprecated");
}
#endif /* } */
diff --git a/src/lcode.c b/src/lcode.c
index 2e8b3fb4..72afce96 100644
--- a/src/lcode.c
+++ b/src/lcode.c
@@ -1,5 +1,5 @@
/*
-** $Id: lcode.c,v 2.85 2014/03/21 13:52:33 roberto Exp $
+** $Id: lcode.c,v 2.90 2014/05/08 18:58:46 roberto Exp $
** Code generator for Lua
** See Copyright Notice in lua.h
*/
@@ -46,7 +46,7 @@ static int tonumeral(expdesc *e, TValue *v) {
if (v) setivalue(v, e->u.ival);
return 1;
case VKFLT:
- if (v) setnvalue(v, e->u.nval);
+ if (v) setfltvalue(v, e->u.nval);
return 1;
default: return 0;
}
@@ -195,7 +195,7 @@ void luaK_patchlist (FuncState *fs, int list, int target) {
}
-LUAI_FUNC void luaK_patchclose (FuncState *fs, int list, int level) {
+void luaK_patchclose (FuncState *fs, int list, int level) {
level++; /* argument is +1 to reserve 0 as non-op */
while (list != NO_JUMP) {
int next = getjump(fs, list);
@@ -317,7 +317,7 @@ static int addk (FuncState *fs, TValue *key, TValue *v) {
TValue *idx = luaH_set(L, fs->ls->h, key); /* index scanner table */
int k, oldsize;
if (ttisinteger(idx)) { /* is there an index there? */
- k = ivalue(idx);
+ k = cast_int(ivalue(idx));
/* correct value? (warning: must distinguish floats from integers!) */
if (k < fs->nk && ttype(&f->k[k]) == ttype(v) &&
luaV_rawequalobj(&f->k[k], v))
@@ -346,8 +346,9 @@ int luaK_stringK (FuncState *fs, TString *s) {
/*
-** use userdata as key to avoid collision with float with same value;
-** conversion to 'void*' used only for hash, no "precision" problems
+** Integers use userdata as keys to avoid collision with floats with same
+** value; conversion to 'void*' used only for hashing, no "precision"
+** problems
*/
int luaK_intK (FuncState *fs, lua_Integer n) {
TValue k, o;
@@ -359,13 +360,13 @@ int luaK_intK (FuncState *fs, lua_Integer n) {
/*
** Both NaN and -0.0 should not go to the constant table, as they have
-** problems with the hashing. (NaN is not ** a valid key,
-** -0.0 collides with +0.0.)
+** problems with the hashing. (NaN is not a valid key, -0.0 collides
+** with +0.0.)
*/
static int luaK_numberK (FuncState *fs, lua_Number r) {
TValue o;
lua_assert(!luai_numisnan(r) && !isminuszero(r));
- setnvalue(&o, r);
+ setfltvalue(&o, r);
return addk(fs, &o, &o);
}
@@ -768,8 +769,6 @@ static int validop (int op, TValue *v1, TValue *v2) {
return (tointeger(v1, &i) && tointeger(v2, &i));
case LUA_OPMOD: /* integer module by 0 */
return !(ttisinteger(v1) && ttisinteger(v2) && ivalue(v2) == 0);
- case LUA_OPPOW: /* negative integer exponentiation */
- return !(ttisinteger(v1) && ttisinteger(v2) && ivalue(v2) < 0);
default: return 1; /* everything else is valid */
}
}
diff --git a/src/lcorolib.c b/src/lcorolib.c
index 1326c814..fae85b95 100644
--- a/src/lcorolib.c
+++ b/src/lcorolib.c
@@ -1,5 +1,5 @@
/*
-** $Id: lcorolib.c,v 1.5 2013/02/21 13:44:53 roberto Exp $
+** $Id: lcorolib.c,v 1.6 2014/05/08 13:52:20 roberto Exp $
** Coroutine Library
** See Copyright Notice in lua.h
*/
@@ -17,6 +17,13 @@
#include "lualib.h"
+static lua_State *getco (lua_State *L) {
+ lua_State *co = lua_tothread(L, 1);
+ luaL_argcheck(L, co, 1, "coroutine expected");
+ return co;
+}
+
+
static int auxresume (lua_State *L, lua_State *co, int narg) {
int status;
if (!lua_checkstack(co, narg)) {
@@ -47,9 +54,8 @@ static int auxresume (lua_State *L, lua_State *co, int narg) {
static int luaB_coresume (lua_State *L) {
- lua_State *co = lua_tothread(L, 1);
+ lua_State *co = getco(L);
int r;
- luaL_argcheck(L, co, 1, "coroutine expected");
r = auxresume(L, co, lua_gettop(L) - 1);
if (r < 0) {
lua_pushboolean(L, 0);
@@ -102,8 +108,7 @@ static int luaB_yield (lua_State *L) {
static int luaB_costatus (lua_State *L) {
- lua_State *co = lua_tothread(L, 1);
- luaL_argcheck(L, co, 1, "coroutine expected");
+ lua_State *co = getco(L);
if (L == co) lua_pushliteral(L, "running");
else {
switch (lua_status(co)) {
@@ -129,6 +134,12 @@ static int luaB_costatus (lua_State *L) {
}
+static int luaB_yieldable (lua_State *L) {
+ lua_pushboolean(L, lua_isyieldable(L));
+ return 1;
+}
+
+
static int luaB_corunning (lua_State *L) {
int ismain = lua_pushthread(L);
lua_pushboolean(L, ismain);
@@ -143,6 +154,7 @@ static const luaL_Reg co_funcs[] = {
{"status", luaB_costatus},
{"wrap", luaB_cowrap},
{"yield", luaB_yield},
+ {"isyieldable", luaB_yieldable},
{NULL, NULL}
};
diff --git a/src/ldblib.c b/src/ldblib.c
index 8a724a1e..db79de38 100644
--- a/src/ldblib.c
+++ b/src/ldblib.c
@@ -1,5 +1,5 @@
/*
-** $Id: ldblib.c,v 1.137 2014/03/12 20:57:40 roberto Exp $
+** $Id: ldblib.c,v 1.139 2014/05/15 19:27:33 roberto Exp $
** Interface from Lua to its debug API
** See Copyright Notice in lua.h
*/
@@ -21,16 +21,30 @@
#define HOOKKEY "_HKEY"
-
-static int db_numbits (lua_State *L) {
+static int db_Csize (lua_State *L) {
+ static struct {
+ char c;
+ unsigned char sz;
+ } sizes[] = {
+ {'I', sizeof(lua_Integer)},
+ {'F', sizeof(lua_Number)},
+ {'b', CHAR_BIT}, /* here is number of bits (not bytes) */
+ {'h', sizeof(short)},
+ {'i', sizeof(int)},
+ {'l', sizeof(long)},
+ {'z', sizeof(size_t)},
+ {'f', sizeof(float)},
+ {'d', sizeof(double)}
+ };
const char *s = luaL_checkstring(L, 1);
- if (*s == 'i')
- lua_pushinteger(L, sizeof(lua_Integer) * CHAR_BIT);
- else if (*s == 'f')
- lua_pushinteger(L, sizeof(lua_Number) * CHAR_BIT);
- else
- luaL_argerror(L, 1, lua_pushfstring(L, "invalid option '%s'", s));
- return 1;
+ int i;
+ for (i = 0; i < (int)(sizeof(sizes)/sizeof(sizes[0])); i++) {
+ if (*s == sizes[i].c) {
+ lua_pushinteger(L, sizes[i].sz);
+ return 1;
+ }
+ }
+ return luaL_argerror(L, 1, lua_pushfstring(L, "invalid option '%c'", *s));
}
@@ -77,24 +91,12 @@ static int db_setuservalue (lua_State *L) {
}
-static void settabss (lua_State *L, const char *i, const char *v) {
- lua_pushstring(L, v);
- lua_setfield(L, -2, i);
-}
-
-
-static void settabsi (lua_State *L, const char *i, int v) {
- lua_pushinteger(L, v);
- lua_setfield(L, -2, i);
-}
-
-
-static void settabsb (lua_State *L, const char *i, int v) {
- lua_pushboolean(L, v);
- lua_setfield(L, -2, i);
-}
-
-
+/*
+** Auxiliary function used by several library functions: check for
+** an optional thread as function's first argument and set 'arg' with
+** 1 if this argument is present (so that functions can skip it to
+** access their other arguments)
+*/
static lua_State *getthread (lua_State *L, int *arg) {
if (lua_isthread(L, 1)) {
*arg = 1;
@@ -102,44 +104,70 @@ static lua_State *getthread (lua_State *L, int *arg) {
}
else {
*arg = 0;
- return L;
+ return L; /* function will operate over current thread */
}
}
+/*
+** Variations of 'lua_settable', used by 'db_getinfo' to put results
+** from 'lua_getinfo' into result table. Key is always a string;
+** value can be a string, an int, or a boolean.
+*/
+static void settabss (lua_State *L, const char *k, const char *v) {
+ lua_pushstring(L, v);
+ lua_setfield(L, -2, k);
+}
+
+static void settabsi (lua_State *L, const char *k, int v) {
+ lua_pushinteger(L, v);
+ lua_setfield(L, -2, k);
+}
+
+static void settabsb (lua_State *L, const char *k, int v) {
+ lua_pushboolean(L, v);
+ lua_setfield(L, -2, k);
+}
+
+
+/*
+** In function 'db_getinfo', the call to 'lua_getinfo' may push
+** results on the stack; later it creates the result table to put
+** these objects. Function 'treatstackoption' puts the result from
+** 'lua_getinfo' on top of the result table so that it can call
+** 'lua_setfield'.
+*/
static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) {
- if (L == L1) {
- lua_pushvalue(L, -2);
- lua_remove(L, -3);
- }
+ if (L == L1)
+ lua_rotate(L, -2, 1); /* exchange object and table */
else
- lua_xmove(L1, L, 1);
- lua_setfield(L, -2, fname);
+ lua_xmove(L1, L, 1); /* move object to the "main" stack */
+ lua_setfield(L, -2, fname); /* put object into table */
}
+/*
+** Calls 'lua_getinfo' and collects all results in a new table.
+*/
static int db_getinfo (lua_State *L) {
lua_Debug ar;
int arg;
lua_State *L1 = getthread(L, &arg);
const char *options = luaL_optstring(L, arg+2, "flnStu");
- if (lua_isnumber(L, arg+1)) {
- if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) {
+ if (lua_isfunction(L, arg + 1)) { /* info about a function? */
+ options = lua_pushfstring(L, ">%s", options); /* add '>' to 'options' */
+ lua_pushvalue(L, arg + 1); /* move function to 'L1' stack */
+ lua_xmove(L, L1, 1);
+ }
+ else { /* stack level */
+ if (!lua_getstack(L1, luaL_checkint(L, arg + 1), &ar)) {
lua_pushnil(L); /* level out of range */
return 1;
}
}
- else if (lua_isfunction(L, arg+1)) {
- lua_pushfstring(L, ">%s", options);
- options = lua_tostring(L, -1);
- lua_pushvalue(L, arg+1);
- lua_xmove(L, L1, 1);
- }
- else
- return luaL_argerror(L, arg+1, "function or level expected");
if (!lua_getinfo(L1, options, &ar))
return luaL_argerror(L, arg+2, "invalid option");
- lua_createtable(L, 0, 2);
+ lua_newtable(L); /* table to collect results */
if (strchr(options, 'S')) {
settabss(L, "source", ar.source);
settabss(L, "short_src", ar.short_src);
@@ -177,16 +205,16 @@ static int db_getlocal (lua_State *L) {
if (lua_isfunction(L, arg + 1)) { /* function argument? */
lua_pushvalue(L, arg + 1); /* push function */
lua_pushstring(L, lua_getlocal(L, NULL, nvar)); /* push local name */
- return 1;
+ return 1; /* return only name (there is no value) */
}
else { /* stack-level argument */
if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */
return luaL_argerror(L, arg+1, "level out of range");
name = lua_getlocal(L1, &ar, nvar);
if (name) {
- lua_xmove(L1, L, 1); /* push local value */
+ lua_xmove(L1, L, 1); /* move local value */
lua_pushstring(L, name); /* push name */
- lua_pushvalue(L, -2); /* re-order */
+ lua_rotate(L, -2, 1); /* re-order */
return 2;
}
else {
@@ -211,14 +239,17 @@ static int db_setlocal (lua_State *L) {
}
+/*
+** get (if 'get' is true) or set an upvalue from a closure
+*/
static int auxupvalue (lua_State *L, int get) {
const char *name;
- int n = luaL_checkint(L, 2);
- luaL_checktype(L, 1, LUA_TFUNCTION);
+ int n = luaL_checkint(L, 2); /* upvalue index */
+ luaL_checktype(L, 1, LUA_TFUNCTION); /* closure */
name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n);
if (name == NULL) return 0;
lua_pushstring(L, name);
- lua_insert(L, -(get+1));
+ lua_insert(L, -(get+1)); /* no-op if get is false */
return get + 1;
}
@@ -234,13 +265,15 @@ static int db_setupvalue (lua_State *L) {
}
+/*
+** Check whether a given upvalue from a given closure exists and
+** returns its index
+*/
static int checkupval (lua_State *L, int argf, int argnup) {
- lua_Debug ar;
- int nup = luaL_checkint(L, argnup);
- luaL_checktype(L, argf, LUA_TFUNCTION);
- lua_pushvalue(L, argf);
- lua_getinfo(L, ">u", &ar);
- luaL_argcheck(L, 1 <= nup && nup <= ar.nups, argnup, "invalid upvalue index");
+ int nup = luaL_checkint(L, argnup); /* upvalue index */
+ luaL_checktype(L, argf, LUA_TFUNCTION); /* closure */
+ luaL_argcheck(L, (lua_getupvalue(L, argf, nup) != NULL), argnup,
+ "invalid upvalue index");
return nup;
}
@@ -262,25 +295,36 @@ static int db_upvaluejoin (lua_State *L) {
}
+/*
+** The hook table (at registry[HOOKKEY]) maps threads to their current
+** hook function
+*/
#define gethooktable(L) luaL_getsubtable(L, LUA_REGISTRYINDEX, HOOKKEY)
+/*
+** Call hook function registered at hook table for the current
+** thread (if there is one)
+*/
static void hookf (lua_State *L, lua_Debug *ar) {
static const char *const hooknames[] =
{"call", "return", "line", "count", "tail call"};
gethooktable(L);
lua_pushthread(L);
- if (lua_rawget(L, -2) == LUA_TFUNCTION) {
- lua_pushstring(L, hooknames[(int)ar->event]);
+ if (lua_rawget(L, -2) == LUA_TFUNCTION) { /* is there a hook function? */
+ lua_pushstring(L, hooknames[(int)ar->event]); /* push event name */
if (ar->currentline >= 0)
- lua_pushinteger(L, ar->currentline);
+ lua_pushinteger(L, ar->currentline); /* push current line */
else lua_pushnil(L);
lua_assert(lua_getinfo(L, "lS", ar));
- lua_call(L, 2, 0);
+ lua_call(L, 2, 0); /* call hook function */
}
}
+/*
+** Convert a string mask (for 'sethook') into a bit mask
+*/
static int makemask (const char *smask, int count) {
int mask = 0;
if (strchr(smask, 'c')) mask |= LUA_MASKCALL;
@@ -291,6 +335,9 @@ static int makemask (const char *smask, int count) {
}
+/*
+** Convert a bit mask (for 'gethook') into a string mask
+*/
static char *unmakemask (int mask, char *smask) {
int i = 0;
if (mask & LUA_MASKCALL) smask[i++] = 'c';
@@ -305,7 +352,7 @@ static int db_sethook (lua_State *L) {
int arg, mask, count;
lua_Hook func;
lua_State *L1 = getthread(L, &arg);
- if (lua_isnoneornil(L, arg+1)) {
+ if (lua_isnoneornil(L, arg+1)) { /* no hook? */
lua_settop(L, arg+1);
func = NULL; mask = 0; count = 0; /* turn off hooks */
}
@@ -321,9 +368,9 @@ static int db_sethook (lua_State *L) {
lua_pushvalue(L, -1);
lua_setmetatable(L, -2); /* setmetatable(hooktable) = hooktable */
}
- lua_pushthread(L1); lua_xmove(L1, L, 1);
- lua_pushvalue(L, arg+1);
- lua_rawset(L, -3); /* set new hook */
+ lua_pushthread(L1); lua_xmove(L1, L, 1); /* key */
+ lua_pushvalue(L, arg+1); /* value */
+ lua_rawset(L, -3); /* hooktable[L1] = new Lua hook */
lua_sethook(L1, func, mask, count); /* set hooks */
return 0;
}
@@ -340,11 +387,11 @@ static int db_gethook (lua_State *L) {
else {
gethooktable(L);
lua_pushthread(L1); lua_xmove(L1, L, 1);
- lua_rawget(L, -2); /* get hook */
+ lua_rawget(L, -2); /* 1st result = hooktable[L1] */
lua_remove(L, -2); /* remove hook table */
}
- lua_pushstring(L, unmakemask(mask, buff));
- lua_pushinteger(L, lua_gethookcount(L1));
+ lua_pushstring(L, unmakemask(mask, buff)); /* 2nd result = mask */
+ lua_pushinteger(L, lua_gethookcount(L1)); /* 3rd result = count */
return 3;
}
@@ -379,6 +426,7 @@ static int db_traceback (lua_State *L) {
static const luaL_Reg dblib[] = {
+ {"Csize", db_Csize},
{"debug", db_debug},
{"getuservalue", db_getuservalue},
{"gethook", db_gethook},
@@ -387,7 +435,6 @@ static const luaL_Reg dblib[] = {
{"getregistry", db_getregistry},
{"getmetatable", db_getmetatable},
{"getupvalue", db_getupvalue},
- {"numbits", db_numbits},
{"upvaluejoin", db_upvaluejoin},
{"upvalueid", db_upvalueid},
{"setuservalue", db_setuservalue},
diff --git a/src/ldo.c b/src/ldo.c
index 5075ce39..a4ba3bd0 100644
--- a/src/ldo.c
+++ b/src/ldo.c
@@ -1,5 +1,5 @@
/*
-** $Id: ldo.c,v 2.115 2014/03/21 13:52:33 roberto Exp $
+** $Id: ldo.c,v 2.123 2014/06/19 18:27:20 roberto Exp $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
@@ -33,6 +33,8 @@
+#define errorstatus(s) ((s) > LUA_YIELD)
+
/*
** {======================================================
@@ -412,24 +414,27 @@ void luaD_call (lua_State *L, StkId func, int nResults, int allowyield) {
}
-static void finishCcall (lua_State *L) {
+/*
+** Completes the execution of an interrupted C function, calling its
+** continuation function.
+*/
+static void finishCcall (lua_State *L, int status) {
CallInfo *ci = L->ci;
int n;
- lua_assert(ci->u.c.k != NULL); /* must have a continuation */
- lua_assert(L->nny == 0);
+ /* must have a continuation and must be able to call it */
+ lua_assert(ci->u.c.k != NULL && L->nny == 0);
+ /* error status can only happen in a protected call */
+ lua_assert((ci->callstatus & CIST_YPCALL) || status == LUA_YIELD);
if (ci->callstatus & CIST_YPCALL) { /* was inside a pcall? */
ci->callstatus &= ~CIST_YPCALL; /* finish 'lua_pcall' */
L->errfunc = ci->u.c.old_errfunc;
}
- /* finish 'lua_callk'/'lua_pcall' */
+ /* finish 'lua_callk'/'lua_pcall'; CIST_YPCALL and 'errfunc' already
+ handled */
adjustresults(L, ci->nresults);
/* call continuation function */
- if (!(ci->callstatus & CIST_STAT)) /* no call status? */
- ci->u.c.status = LUA_YIELD; /* 'default' status */
- lua_assert(ci->u.c.status != LUA_OK);
- ci->callstatus = (ci->callstatus & ~(CIST_YPCALL | CIST_STAT)) | CIST_YIELDED;
lua_unlock(L);
- n = (*ci->u.c.k)(L);
+ n = (*ci->u.c.k)(L, status, ci->u.c.ctx);
lua_lock(L);
api_checknelems(L, n);
/* finish 'luaD_precall' */
@@ -437,13 +442,20 @@ static void finishCcall (lua_State *L) {
}
+/*
+** Executes "full continuation" (everything in the stack) of a
+** previously interrupted coroutine until the stack is empty (or another
+** interruption long-jumps out of the loop). If the coroutine is
+** recovering from an error, 'ud' points to the error status, which must
+** be passed to the first continuation function (otherwise the default
+** status is LUA_YIELD).
+*/
static void unroll (lua_State *L, void *ud) {
- UNUSED(ud);
- for (;;) {
- if (L->ci == &L->base_ci) /* stack is empty? */
- return; /* coroutine finished normally */
+ if (ud != NULL) /* error status? */
+ finishCcall(L, *(int *)ud); /* finish 'lua_pcallk' callee */
+ while (L->ci != &L->base_ci) { /* something in the stack */
if (!isLua(L->ci)) /* C function? */
- finishCcall(L);
+ finishCcall(L, LUA_YIELD); /* complete its execution */
else { /* Lua function */
luaV_finishOp(L); /* finish interrupted instruction */
luaV_execute(L); /* execute down to higher C 'boundary' */
@@ -453,7 +465,8 @@ static void unroll (lua_State *L, void *ud) {
/*
-** check whether thread has a suspended protected call
+** Try to find a suspended protected call (a "recover point") for the
+** given thread.
*/
static CallInfo *findpcall (lua_State *L) {
CallInfo *ci;
@@ -465,6 +478,11 @@ static CallInfo *findpcall (lua_State *L) {
}
+/*
+** Recovers from an error in a coroutine. Finds a recover point (if
+** there is one) and completes the execution of the interrupted
+** 'luaD_pcall'. If there is no recover point, returns zero.
+*/
static int recover (lua_State *L, int status) {
StkId oldtop;
CallInfo *ci = findpcall(L);
@@ -474,12 +492,10 @@ static int recover (lua_State *L, int status) {
luaF_close(L, oldtop);
seterrorobj(L, status, oldtop);
L->ci = ci;
- L->allowhook = ci->u.c.old_allowhook;
+ L->allowhook = getoah(ci->callstatus); /* restore original 'allowhook' */
L->nny = 0; /* should be zero to be yieldable */
luaD_shrinkstack(L);
L->errfunc = ci->u.c.old_errfunc;
- ci->callstatus |= CIST_STAT; /* call has error status */
- ci->u.c.status = status; /* (here it is) */
return 1; /* continue running the coroutine */
}
@@ -498,7 +514,11 @@ static l_noret resume_error (lua_State *L, const char *msg, StkId firstArg) {
/*
-** do the work for 'lua_resume' in protected mode
+** Do the work for 'lua_resume' in protected mode. Most of the work
+** depends on the status of the coroutine: initial state, suspended
+** inside a hook, or regulary suspended (optionally with a continuation
+** function), plus erroneous cases: non-suspended coroutine or dead
+** coroutine.
*/
static void resume (lua_State *L, void *ud) {
int nCcalls = L->nCcalls;
@@ -516,24 +536,22 @@ static void resume (lua_State *L, void *ud) {
else if (L->status != LUA_YIELD)
resume_error(L, "cannot resume dead coroutine", firstArg);
else { /* resuming from previous yield */
- L->status = LUA_OK;
+ L->status = LUA_OK; /* mark that it is running (again) */
ci->func = restorestack(L, ci->extra);
if (isLua(ci)) /* yielded inside a hook? */
luaV_execute(L); /* just continue running Lua code */
else { /* 'common' yield */
- if (ci->u.c.k != NULL) { /* does it have a continuation? */
+ if (ci->u.c.k != NULL) { /* does it have a continuation function? */
int n;
- ci->u.c.status = LUA_YIELD; /* 'default' status */
- ci->callstatus |= CIST_YIELDED;
lua_unlock(L);
- n = (*ci->u.c.k)(L); /* call continuation */
+ n = (*ci->u.c.k)(L, LUA_YIELD, ci->u.c.ctx); /* call continuation */
lua_lock(L);
api_checknelems(L, n);
firstArg = L->top - n; /* yield results come from continuation */
}
luaD_poscall(L, firstArg); /* finish 'luaD_precall' */
}
- unroll(L, NULL);
+ unroll(L, NULL); /* run continuation */
}
lua_assert(nCcalls == L->nCcalls);
}
@@ -541,7 +559,7 @@ static void resume (lua_State *L, void *ud) {
LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) {
int status;
- int oldnny = L->nny; /* save 'nny' */
+ int oldnny = L->nny; /* save "number of non-yieldable" calls */
lua_lock(L);
luai_userstateresume(L, nargs);
L->nCcalls = (from) ? from->nCcalls + 1 : 1;
@@ -550,18 +568,17 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) {
status = luaD_rawrunprotected(L, resume, L->top - nargs);
if (status == -1) /* error calling 'lua_resume'? */
status = LUA_ERRRUN;
- else { /* yield or regular error */
- while (status != LUA_OK && status != LUA_YIELD) { /* error? */
- if (recover(L, status)) /* recover point? */
- status = luaD_rawrunprotected(L, unroll, NULL); /* run continuation */
- else { /* unrecoverable error */
- L->status = cast_byte(status); /* mark thread as `dead' */
- seterrorobj(L, status, L->top);
- L->ci->top = L->top;
- break;
- }
+ else { /* continue running after recoverable errors */
+ while (errorstatus(status) && recover(L, status)) {
+ /* unroll continuation */
+ status = luaD_rawrunprotected(L, unroll, &status);
+ }
+ if (errorstatus(status)) { /* unrecoverable error? */
+ L->status = cast_byte(status); /* mark thread as `dead' */
+ seterrorobj(L, status, L->top); /* push error message */
+ L->ci->top = L->top;
}
- lua_assert(status == L->status);
+ else lua_assert(status == L->status); /* normal end or yield */
}
L->nny = oldnny; /* restore 'nny' */
L->nCcalls--;
@@ -571,7 +588,12 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) {
}
-LUA_API int lua_yieldk (lua_State *L, int nresults, int ctx, lua_CFunction k) {
+LUA_API int lua_isyieldable (lua_State *L) {
+ return (L->nny == 0);
+}
+
+
+LUA_API int lua_yieldk (lua_State *L, int nresults, int ctx, lua_KFunction k) {
CallInfo *ci = L->ci;
luai_userstateyield(L, nresults);
lua_lock(L);
@@ -645,7 +667,7 @@ static void checkmode (lua_State *L, const char *mode, const char *x) {
static void f_parser (lua_State *L, void *ud) {
- Closure *cl;
+ LClosure *cl;
struct SParser *p = cast(struct SParser *, ud);
int c = zgetc(p->z); /* read first character */
if (c == LUA_SIGNATURE[0]) {
@@ -656,8 +678,8 @@ static void f_parser (lua_State *L, void *ud) {
checkmode(L, p->mode, "text");
cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c);
}
- lua_assert(cl->l.nupvalues == cl->l.p->sizeupvalues);
- luaF_initupvals(L, &cl->l);
+ lua_assert(cl->nupvalues == cl->p->sizeupvalues);
+ luaF_initupvals(L, cl);
}
diff --git a/src/ldump.c b/src/ldump.c
index a4c96416..0be56c65 100644
--- a/src/ldump.c
+++ b/src/ldump.c
@@ -1,5 +1,5 @@
/*
-** $Id: ldump.c,v 2.27 2014/03/11 18:56:27 roberto Exp $
+** $Id: ldump.c,v 2.32 2014/06/18 18:35:43 roberto Exp $
** save precompiled Lua chunks
** See Copyright Notice in lua.h
*/
@@ -27,7 +27,7 @@ typedef struct {
/*
** All high-level dumps go through DumpVector; you can change it to
-** change the endianess of the result
+** change the endianness of the result
*/
#define DumpVector(v,n,D) DumpBlock(v,(n)*sizeof((v)[0]),D)
@@ -73,7 +73,7 @@ static void DumpString (const TString *s, DumpState *D) {
else {
size_t size = s->tsv.len + 1; /* include trailing '\0' */
if (size < 0xFF)
- DumpByte(size, D);
+ DumpByte(cast_int(size), D);
else {
DumpByte(0xFF, D);
DumpVar(size, D);
@@ -89,7 +89,7 @@ static void DumpCode (const Proto *f, DumpState *D) {
}
-static void DumpFunction(const Proto *f, DumpState *D);
+static void DumpFunction(const Proto *f, TString *psource, DumpState *D);
static void DumpConstants (const Proto *f, DumpState *D) {
int i;
@@ -118,10 +118,15 @@ static void DumpConstants (const Proto *f, DumpState *D) {
lua_assert(0);
}
}
- n = f->sizep;
+}
+
+
+static void DumpProtos (const Proto *f, DumpState *D) {
+ int i;
+ int n = f->sizep;
DumpInt(n, D);
for (i = 0; i < n; i++)
- DumpFunction(f->p[i], D);
+ DumpFunction(f->p[i], f->source, D);
}
@@ -137,7 +142,6 @@ static void DumpUpvalues (const Proto *f, DumpState *D) {
static void DumpDebug (const Proto *f, DumpState *D) {
int i, n;
- DumpString((D->strip) ? NULL : f->source, D);
n = (D->strip) ? 0 : f->sizelineinfo;
DumpInt(n, D);
DumpVector(f->lineinfo, n, D);
@@ -155,7 +159,11 @@ static void DumpDebug (const Proto *f, DumpState *D) {
}
-static void DumpFunction (const Proto *f, DumpState *D) {
+static void DumpFunction (const Proto *f, TString *psource, DumpState *D) {
+ if (D->strip || f->source == psource)
+ DumpString(NULL, D); /* no debug info or same source as its parent */
+ else
+ DumpString(f->source, D);
DumpInt(f->linedefined, D);
DumpInt(f->lastlinedefined, D);
DumpByte(f->numparams, D);
@@ -164,6 +172,7 @@ static void DumpFunction (const Proto *f, DumpState *D) {
DumpCode(f, D);
DumpConstants(f, D);
DumpUpvalues(f, D);
+ DumpProtos(f, D);
DumpDebug(f, D);
}
@@ -196,7 +205,7 @@ int luaU_dump(lua_State *L, const Proto *f, lua_Writer w, void *data,
D.status = 0;
DumpHeader(&D);
DumpByte(f->sizeupvalues, &D);
- DumpFunction(f, &D);
+ DumpFunction(f, NULL, &D);
return D.status;
}
diff --git a/src/lfunc.c b/src/lfunc.c
index c78daf1e..8a78fb6e 100644
--- a/src/lfunc.c
+++ b/src/lfunc.c
@@ -1,5 +1,5 @@
/*
-** $Id: lfunc.c,v 2.41 2014/02/18 13:39:37 roberto Exp $
+** $Id: lfunc.c,v 2.43 2014/06/19 18:27:20 roberto Exp $
** Auxiliary functions to manipulate prototypes and closures
** See Copyright Notice in lua.h
*/
@@ -20,18 +20,20 @@
-Closure *luaF_newCclosure (lua_State *L, int n) {
- Closure *c = &luaC_newobj(L, LUA_TCCL, sizeCclosure(n))->cl;
- c->c.nupvalues = cast_byte(n);
+CClosure *luaF_newCclosure (lua_State *L, int n) {
+ GCObject *o = luaC_newobj(L, LUA_TCCL, sizeCclosure(n));
+ CClosure *c = gco2ccl(o);
+ c->nupvalues = cast_byte(n);
return c;
}
-Closure *luaF_newLclosure (lua_State *L, int n) {
- Closure *c = &luaC_newobj(L, LUA_TLCL, sizeLclosure(n))->cl;
- c->l.p = NULL;
- c->l.nupvalues = cast_byte(n);
- while (n--) c->l.upvals[n] = NULL;
+LClosure *luaF_newLclosure (lua_State *L, int n) {
+ GCObject *o = luaC_newobj(L, LUA_TLCL, sizeLclosure(n));
+ LClosure *c = gco2lcl(o);
+ c->p = NULL;
+ c->nupvalues = cast_byte(n);
+ while (n--) c->upvals[n] = NULL;
return c;
}
@@ -93,7 +95,8 @@ void luaF_close (lua_State *L, StkId level) {
Proto *luaF_newproto (lua_State *L) {
- Proto *f = &luaC_newobj(L, LUA_TPROTO, sizeof(Proto))->p;
+ GCObject *o = luaC_newobj(L, LUA_TPROTO, sizeof(Proto));
+ Proto *f = gco2p(o);
f->k = NULL;
f->sizek = 0;
f->p = NULL;
diff --git a/src/lfunc.h b/src/lfunc.h
index dce699bc..256d3cf9 100644
--- a/src/lfunc.h
+++ b/src/lfunc.h
@@ -1,5 +1,5 @@
/*
-** $Id: lfunc.h,v 2.13 2014/02/18 13:39:37 roberto Exp $
+** $Id: lfunc.h,v 2.14 2014/06/19 18:27:20 roberto Exp $
** Auxiliary functions to manipulate prototypes and closures
** See Copyright Notice in lua.h
*/
@@ -41,8 +41,8 @@ struct UpVal {
LUAI_FUNC Proto *luaF_newproto (lua_State *L);
-LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems);
-LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems);
+LUAI_FUNC CClosure *luaF_newCclosure (lua_State *L, int nelems);
+LUAI_FUNC LClosure *luaF_newLclosure (lua_State *L, int nelems);
LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl);
LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level);
LUAI_FUNC void luaF_close (lua_State *L, StkId level);
diff --git a/src/lgc.c b/src/lgc.c
index 9ecfd3b9..74cacdae 100644
--- a/src/lgc.c
+++ b/src/lgc.c
@@ -1,5 +1,5 @@
/*
-** $Id: lgc.c,v 2.179 2014/03/21 13:52:33 roberto Exp $
+** $Id: lgc.c,v 2.183 2014/05/25 19:08:32 roberto Exp $
** Garbage Collector
** See Copyright Notice in lua.h
*/
@@ -172,7 +172,7 @@ void luaC_barrierback_ (lua_State *L, GCObject *o) {
** closures pointing to it. So, we assume that the object being assigned
** must be marked.
*/
-LUAI_FUNC void luaC_upvalbarrier_ (lua_State *L, UpVal *uv) {
+void luaC_upvalbarrier_ (lua_State *L, UpVal *uv) {
global_State *g = G(L);
GCObject *o = gcvalue(uv->v);
lua_assert(!upisopen(uv)); /* ensured by macro luaC_upvalbarrier */
@@ -495,8 +495,7 @@ static lu_mem traverseLclosure (global_State *g, LClosure *cl) {
}
-static lu_mem traversestack (global_State *g, lua_State *th) {
- int n = 0;
+static lu_mem traversethread (global_State *g, lua_State *th) {
StkId o = th->stack;
if (o == NULL)
return 1; /* stack not completely built yet */
@@ -514,16 +513,9 @@ static lu_mem traversestack (global_State *g, lua_State *th) {
g->twups = th;
}
}
- else {
- CallInfo *ci;
- for (ci = &th->base_ci; ci != th->ci; ci = ci->next)
- n++; /* count call infos to compute size */
- /* should not change the stack during an emergency gc cycle */
- if (g->gckind != KGC_EMERGENCY)
- luaD_shrinkstack(th);
- }
- return sizeof(lua_State) + sizeof(TValue) * th->stacksize +
- sizeof(CallInfo) * n;
+ else if (g->gckind != KGC_EMERGENCY)
+ luaD_shrinkstack(th); /* do not change stack in emergency cycle */
+ return (sizeof(lua_State) + sizeof(TValue) * th->stacksize);
}
@@ -561,7 +553,7 @@ static void propagatemark (global_State *g) {
th->gclist = g->grayagain;
g->grayagain = o; /* insert into 'grayagain' list */
black2gray(o);
- size = traversestack(g, th);
+ size = traversethread(g, th);
break;
}
case LUA_TPROTO: {
@@ -777,9 +769,11 @@ static GCObject **sweeptolive (lua_State *L, GCObject **p, int *n) {
*/
static void checkSizes (lua_State *L, global_State *g) {
if (g->gckind != KGC_EMERGENCY) {
+ l_mem olddebt = g->GCdebt;
luaZ_freebuffer(L, &g->buff); /* free concatenation buffer */
if (g->strt.nuse < g->strt.size / 4) /* string table too big? */
luaS_resize(L, g->strt.size / 2); /* shrink it a little */
+ g->GCestimate += g->GCdebt - olddebt; /* update estimate */
}
}
@@ -836,6 +830,21 @@ static void GCTM (lua_State *L, int propagateerrors) {
/*
+** call a few (up to 'g->gcfinnum') finalizers
+*/
+static int runafewfinalizers (lua_State *L) {
+ global_State *g = G(L);
+ unsigned int i;
+ lua_assert(!g->tobefnz || g->gcfinnum > 0);
+ for (i = 0; g->tobefnz && i < g->gcfinnum; i++)
+ GCTM(L, 1); /* call one finalizer */
+ g->gcfinnum = (!g->tobefnz) ? 0 /* nothing more to finalize? */
+ : g->gcfinnum * 2; /* else call a few more next time */
+ return i;
+}
+
+
+/*
** call all pending finalizers
*/
static void callallpendingfinalizers (lua_State *L, int propagateerrors) {
@@ -888,18 +897,17 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
return; /* nothing to be done */
else { /* move 'o' to 'finobj' list */
GCObject **p;
- if (g->sweepgc == &o->gch.next) { /* avoid removing current sweep object */
- lua_assert(issweepphase(g));
- g->sweepgc = sweeptolive(L, g->sweepgc, NULL);
+ if (issweepphase(g)) {
+ makewhite(g, o); /* "sweep" object 'o' */
+ if (g->sweepgc == &o->gch.next) /* shoud not remove 'sweepgc' object */
+ g->sweepgc = sweeptolive(L, g->sweepgc, NULL); /* change 'sweepgc' */
}
/* search for pointer pointing to 'o' */
for (p = &g->allgc; *p != o; p = &gch(*p)->next) { /* empty */ }
- *p = o->gch.next; /* remove 'o' from its list */
+ *p = o->gch.next; /* remove 'o' from 'allgc' list */
o->gch.next = g->finobj; /* link it in "fin" list */
g->finobj = o;
l_setbit(o->gch.marked, FINALIZEDBIT); /* mark it as such */
- if (issweepphase(g))
- makewhite(g, o); /* "sweep" object */
}
}
@@ -918,9 +926,9 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
** set a reasonable "time" to wait before starting a new GC cycle;
** cycle will start when memory use hits threshold
*/
-static void setpause (global_State *g, l_mem estimate) {
+static void setpause (global_State *g) {
l_mem threshold, debt;
- estimate = estimate / PAUSEADJ; /* adjust 'estimate' */
+ l_mem estimate = g->GCestimate / PAUSEADJ; /* adjust 'estimate' */
threshold = (g->gcpause < MAX_LMEM / estimate) /* overflow? */
? estimate * g->gcpause /* no overflow */
: MAX_LMEM; /* overflow; truncate to maximum */
@@ -964,8 +972,9 @@ void luaC_freeallobjects (lua_State *L) {
static l_mem atomic (lua_State *L) {
global_State *g = G(L);
- l_mem work = -cast(l_mem, g->GCmemtrav); /* start counting work */
+ l_mem work;
GCObject *origweak, *origall;
+ g->GCmemtrav = 0; /* start counting work */
lua_assert(!iswhite(obj2gco(g->mainthread)));
g->gcstate = GCSinsideatomic;
markobject(g, L); /* mark running thread */
@@ -975,10 +984,10 @@ static l_mem atomic (lua_State *L) {
/* remark occasional upvalues of (maybe) dead threads */
remarkupvals(g);
propagateall(g); /* propagate changes */
- work += g->GCmemtrav; /* stop counting (do not (re)count grays) */
+ work = g->GCmemtrav; /* stop counting (do not (re)count grays) */
/* traverse objects caught by write barrier and by 'remarkupvals' */
retraversegrays(g);
- work -= g->GCmemtrav; /* restart counting */
+ g->GCmemtrav = 0; /* restart counting */
convergeephemerons(g);
/* at this point, all strongly accessible objects are marked. */
/* Clear values from weak tables, before checking finalizers */
@@ -990,7 +999,7 @@ static l_mem atomic (lua_State *L) {
g->gcfinnum = 1; /* there may be objects to be finalized */
markbeingfnz(g); /* mark objects that will be finalized */
propagateall(g); /* remark, to propagate 'resurrection' */
- work -= g->GCmemtrav; /* restart counting */
+ g->GCmemtrav = 0; /* restart counting */
convergeephemerons(g);
/* at this point, all resurrected objects are marked. */
/* remove dead objects from weak tables */
@@ -1008,7 +1017,9 @@ static l_mem atomic (lua_State *L) {
static lu_mem sweepstep (lua_State *L, global_State *g,
int nextstate, GCObject **nextlist) {
if (g->sweepgc) {
+ l_mem olddebt = g->GCdebt;
g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX);
+ g->GCestimate += g->GCdebt - olddebt; /* update estimate */
if (g->sweepgc) /* is there still something to sweep? */
return (GCSWEEPMAX * GCSWEEPCOST);
}
@@ -1023,28 +1034,26 @@ static lu_mem singlestep (lua_State *L) {
global_State *g = G(L);
switch (g->gcstate) {
case GCSpause: {
- /* start to count memory traversed */
g->GCmemtrav = g->strt.size * sizeof(GCObject*);
restartcollection(g);
g->gcstate = GCSpropagate;
return g->GCmemtrav;
}
case GCSpropagate: {
- lu_mem oldtrav = g->GCmemtrav;
+ g->GCmemtrav = 0;
lua_assert(g->gray);
propagatemark(g);
if (g->gray == NULL) /* no more `gray' objects? */
g->gcstate = GCSatomic; /* finish propagate phase */
- return g->GCmemtrav - oldtrav; /* memory traversed in this step */
+ return g->GCmemtrav; /* memory traversed in this step */
}
case GCSatomic: {
lu_mem work;
int sw;
propagateall(g); /* make sure gray list is empty */
- g->GCestimate = g->GCmemtrav; /* save what was counted */;
work = atomic(L); /* work is what was traversed by 'atomic' */
- g->GCestimate += work; /* estimate of total memory traversed */
sw = entersweep(L);
+ g->GCestimate = gettotalbytes(g); /* first estimate */;
return work + sw * GCSWEEPCOST;
}
case GCSswpallgc: { /* sweep "regular" objects */
@@ -1062,10 +1071,15 @@ static lu_mem singlestep (lua_State *L) {
g->gcstate = GCScallfin;
return 0;
}
- case GCScallfin: { /* state to finish calling finalizers */
- /* do nothing here; should be handled by 'luaC_forcestep' */
- g->gcstate = GCSpause; /* finish collection */
- return 0;
+ case GCScallfin: { /* call remaining finalizers */
+ if (g->tobefnz && g->gckind != KGC_EMERGENCY) {
+ int n = runafewfinalizers(L);
+ return (n * GCFINALIZECOST);
+ }
+ else { /* emergency mode or no more finalizers */
+ g->gcstate = GCSpause; /* finish collection */
+ return 0;
+ }
}
default: lua_assert(0); return 0;
}
@@ -1084,21 +1098,6 @@ void luaC_runtilstate (lua_State *L, int statesmask) {
/*
-** run a few (up to 'g->gcfinnum') finalizers
-*/
-static int runafewfinalizers (lua_State *L) {
- global_State *g = G(L);
- unsigned int i;
- lua_assert(!g->tobefnz || g->gcfinnum > 0);
- for (i = 0; g->tobefnz && i < g->gcfinnum; i++)
- GCTM(L, 1); /* call one finalizer */
- g->gcfinnum = (!g->tobefnz) ? 0 /* nothing more to finalize? */
- : g->gcfinnum * 2; /* else call a few more next time */
- return i;
-}
-
-
-/*
** get GC debt and convert it from Kb to 'work units' (avoid zero debt
** and overflows)
*/
@@ -1115,23 +1114,17 @@ static l_mem getdebt (global_State *g) {
*/
void luaC_step (lua_State *L) {
global_State *g = G(L);
- l_mem debt = getdebt(g);
+ l_mem debt = getdebt(g); /* GC deficit (be paid now) */
if (!g->gcrunning) { /* not running? */
luaE_setdebt(g, -GCSTEPSIZE * 10); /* avoid being called too often */
return;
}
- do {
- if (g->gcstate == GCScallfin && g->tobefnz) {
- unsigned int n = runafewfinalizers(L);
- debt -= (n * GCFINALIZECOST);
- }
- else { /* perform one single step */
- lu_mem work = singlestep(L);
- debt -= work;
- }
+ do { /* repeat until pause or enough "credit" (negative debt) */
+ lu_mem work = singlestep(L); /* perform one single step */
+ debt -= work;
} while (debt > -GCSTEPSIZE && g->gcstate != GCSpause);
if (g->gcstate == GCSpause)
- setpause(g, g->GCestimate); /* pause until next cycle */
+ setpause(g); /* pause until next cycle */
else {
debt = (debt / g->gcstepmul) * STEPMULADJ; /* convert 'work units' to Kb */
luaE_setdebt(g, debt);
@@ -1141,29 +1134,30 @@ void luaC_step (lua_State *L) {
/*
-** performs a full GC cycle; if "isemergency", does not call
-** finalizers (which could change stack positions)
+** Performs a full GC cycle; if "isemergency", set a flag to avoid
+** some operations which could change the interpreter state in some
+** unexpected ways (running finalizers and shrinking some structures).
+** Before running the collection, check 'keepinvariant'; if it is true,
+** there may be some objects marked as black, so the collector has
+** to sweep all objects to turn them back to white (as white has not
+** changed, nothing will be collected).
*/
void luaC_fullgc (lua_State *L, int isemergency) {
global_State *g = G(L);
lua_assert(g->gckind == KGC_NORMAL);
- if (isemergency) /* do not run finalizers during emergency GC */
- g->gckind = KGC_EMERGENCY;
- else
- callallpendingfinalizers(L, 1);
- if (keepinvariant(g)) { /* may there be some black objects? */
- /* must sweep all objects to turn them back to white
- (as white has not changed, nothing will be collected) */
- entersweep(L);
+ if (isemergency) g->gckind = KGC_EMERGENCY; /* set flag */
+ if (keepinvariant(g)) { /* black objects? */
+ entersweep(L); /* sweep everything to turn them back to white */
}
/* finish any pending sweep phase to start a new cycle */
luaC_runtilstate(L, bitmask(GCSpause));
luaC_runtilstate(L, ~bitmask(GCSpause)); /* start new collection */
- luaC_runtilstate(L, bitmask(GCSpause)); /* run entire collection */
+ luaC_runtilstate(L, bitmask(GCScallfin)); /* run up to finalizers */
+ /* estimate must be correct after a full GC cycle */
+ lua_assert(g->GCestimate == gettotalbytes(g));
+ luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */
g->gckind = KGC_NORMAL;
- setpause(g, gettotalbytes(g));
- if (!isemergency) /* do not run finalizers during emergency GC */
- callallpendingfinalizers(L, 1);
+ setpause(g);
}
/* }====================================================== */
diff --git a/src/linit.c b/src/linit.c
index 2b48be8b..904aca9a 100644
--- a/src/linit.c
+++ b/src/linit.c
@@ -1,5 +1,5 @@
/*
-** $Id: linit.c,v 1.33 2014/02/06 17:32:33 roberto Exp $
+** $Id: linit.c,v 1.34 2014/05/15 19:28:34 roberto Exp $
** Initialization of libraries for lua.c and other clients
** See Copyright Notice in lua.h
*/
@@ -34,10 +34,12 @@ static const luaL_Reg loadedlibs[] = {
{LUA_IOLIBNAME, luaopen_io},
{LUA_OSLIBNAME, luaopen_os},
{LUA_STRLIBNAME, luaopen_string},
- {LUA_UTF8LIBNAME, luaopen_utf8},
- {LUA_BITLIBNAME, luaopen_bit32},
{LUA_MATHLIBNAME, luaopen_math},
{LUA_DBLIBNAME, luaopen_debug},
+ {LUA_UTF8LIBNAME, luaopen_utf8},
+#if defined(LUA_COMPAT_BITLIB)
+ {LUA_BITLIBNAME, luaopen_bit32},
+#endif
{NULL, NULL}
};
diff --git a/src/liolib.c b/src/liolib.c
index d1605024..5613aa1a 100644
--- a/src/liolib.c
+++ b/src/liolib.c
@@ -1,5 +1,5 @@
/*
-** $Id: liolib.c,v 2.120 2014/03/19 18:57:42 roberto Exp $
+** $Id: liolib.c,v 2.126 2014/06/02 03:00:51 roberto Exp $
** Standard I/O (and system) library
** See Copyright Notice in lua.h
*/
@@ -15,7 +15,9 @@
#endif
+#include <ctype.h>
#include <errno.h>
+#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -104,6 +106,8 @@
#if defined(LUA_USE_POSIX) /* { */
+#include <sys/types.h>
+
#define l_fseek(f,o,w) fseeko(f,o,w)
#define l_ftell(f) ftello(f)
#define l_seeknum off_t
@@ -317,14 +321,10 @@ static int io_readline (lua_State *L);
static void aux_lines (lua_State *L, int toclose) {
- int i;
int n = lua_gettop(L) - 1; /* number of arguments to read */
- /* ensure that arguments will fit here and into 'io_readline' stack */
- luaL_argcheck(L, n <= LUA_MINSTACK - 3, LUA_MINSTACK - 3, "too many options");
- lua_pushvalue(L, 1); /* file handle */
lua_pushinteger(L, n); /* number of arguments to read */
lua_pushboolean(L, toclose); /* close/not close file when finished */
- for (i = 1; i <= n; i++) lua_pushvalue(L, i + 1); /* copy arguments */
+ lua_rotate(L, 2, 2); /* move 'n' and 'toclose' to their positions */
lua_pushcclosure(L, io_readline, 3 + n);
}
@@ -363,26 +363,93 @@ static int io_lines (lua_State *L) {
*/
-static int read_integer (lua_State *L, FILE *f) {
- lua_Integer d;
- if (fscanf(f, LUA_INTEGER_SCAN, &d) == 1) {
- lua_pushinteger(L, d);
- return 1;
+/* maximum length of a numeral */
+#define MAXRN 200
+
+/* auxiliary structure used by 'read_number' */
+typedef struct {
+ FILE *f; /* file being read */
+ int c; /* current character (look ahead) */
+ int n; /* number of elements in buffer 'buff' */
+ char buff[MAXRN + 1]; /* +1 for ending '\0' */
+} RN;
+
+
+/*
+** Add current char to buffer (if not out of space) and read next one
+*/
+static int nextc (RN *rn) {
+ if (rn->n >= MAXRN) { /* buffer overflow? */
+ rn->buff[0] = '\0'; /* invalidate result */
+ return 0; /* fail */
}
else {
- lua_pushnil(L); /* "result" to be removed */
- return 0; /* read fails */
+ rn->buff[rn->n++] = rn->c; /* save current char */
+ rn->c = l_getc(rn->f); /* read next one */
+ return 1;
}
}
+/*
+** Accept current char if it is in 'set' (of size 1 or 2)
+*/
+static int test2 (RN *rn, const char *set) {
+ if (rn->c == set[0] || (rn->c == set[1] && rn->c != '\0'))
+ return nextc(rn);
+ else return 0;
+}
+
+
+/*
+** Read a sequence of (hexa)digits
+*/
+static int readdigits (RN *rn, int hexa) {
+ int count = 0;
+ while ((hexa ? isxdigit(rn->c) : isdigit(rn->c)) && nextc(rn))
+ count++;
+ return count;
+}
+
+
+/* access to locale "radix character" (decimal point) */
+#if !defined(getlocaledecpoint)
+#define getlocaledecpoint() (localeconv()->decimal_point[0])
+#endif
+
+
+/*
+** Read a number: first reads a valid prefix of a numeral into a buffer.
+** Then it calls 'lua_strtonum' to check whether the format is correct
+** and to convert it to a Lua number
+*/
static int read_number (lua_State *L, FILE *f) {
- lua_Number d;
- if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) {
- lua_pushnumber(L, d);
- return 1;
+ RN rn;
+ int count = 0;
+ int hexa = 0;
+ char decp[2] = ".";
+ rn.f = f; rn.n = 0;
+ decp[0] = getlocaledecpoint(); /* get decimal point from locale */
+ l_lockfile(rn.f);
+ do { rn.c = l_getc(rn.f); } while (isspace(rn.c)); /* skip spaces */
+ test2(&rn, "-+"); /* optional signal */
+ if (test2(&rn, "0")) {
+ if (test2(&rn, "xX")) hexa = 1; /* numeral is hexadecimal */
+ else count = 1; /* count initial '0' as a valid digit */
}
- else {
+ count += readdigits(&rn, hexa); /* integral part */
+ if (test2(&rn, decp)) /* decimal point? */
+ count += readdigits(&rn, hexa); /* fractionary part */
+ if (count > 0 && test2(&rn, (hexa ? "pP" : "eE"))) { /* exponent mark? */
+ test2(&rn, "-+"); /* exponent signal */
+ readdigits(&rn, 0); /* exponent digits */
+ }
+ ungetc(rn.c, rn.f); /* unread look-ahead char */
+ l_unlockfile(rn.f);
+ rn.buff[rn.n] = '\0'; /* finish string */
+ if (lua_strtonum(L, rn.buff)) /* is this a valid number? */
+ return 1; /* ok */
+ else { /* invalid format */
lua_pushnil(L); /* "result" to be removed */
return 0; /* read fails */
}
@@ -455,12 +522,9 @@ static int g_read (lua_State *L, FILE *f, int first) {
success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);
}
else {
- const char *p = lua_tostring(L, n);
- luaL_argcheck(L, p && p[0] == '*', n, "invalid option");
- switch (p[1]) {
- case 'i': /* integer */
- success = read_integer(L, f);
- break;
+ const char *p = luaL_checkstring(L, n);
+ if (*p == '*') p++; /* skip optional '*' (for compatibility) */
+ switch (*p) {
case 'n': /* number */
success = read_number(L, f);
break;
@@ -507,6 +571,7 @@ static int io_readline (lua_State *L) {
if (isclosed(p)) /* file is already closed? */
return luaL_error(L, "file is already closed");
lua_settop(L , 1);
+ luaL_checkstack(L, n, "too many arguments");
for (i = 1; i <= n; i++) /* push arguments to 'g_read' */
lua_pushvalue(L, lua_upvalueindex(3 + i));
n = g_read(L, p->f, 2); /* 'n' is number of results */
diff --git a/src/llex.c b/src/llex.c
index 6ca0f42b..e358f20f 100644
--- a/src/llex.c
+++ b/src/llex.c
@@ -1,5 +1,5 @@
/*
-** $Id: llex.c,v 2.74 2014/02/14 15:23:51 roberto Exp $
+** $Id: llex.c,v 2.78 2014/05/21 15:22:02 roberto Exp $
** Lexical Analyzer
** See Copyright Notice in lua.h
*/
@@ -183,12 +183,26 @@ void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source,
*/
+static int check_next1 (LexState *ls, int c) {
+ if (ls->current == c) {
+ next(ls);
+ return 1;
+ }
+ else return 0;
+}
-static int check_next (LexState *ls, const char *set) {
- if (ls->current == '\0' || !strchr(set, ls->current))
- return 0;
- save_and_next(ls);
- return 1;
+
+/*
+** Check whether current char is in set 'set' (with two chars) and
+** saves it
+*/
+static int check_next2 (LexState *ls, const char *set) {
+ lua_assert(set[2] == '\0');
+ if (ls->current == set[0] || ls->current == set[1]) {
+ save_and_next(ls);
+ return 1;
+ }
+ else return 0;
}
@@ -196,10 +210,12 @@ static int check_next (LexState *ls, const char *set) {
** change all characters 'from' in buffer to 'to'
*/
static void buffreplace (LexState *ls, char from, char to) {
- size_t n = luaZ_bufflen(ls->buff);
- char *p = luaZ_buffer(ls->buff);
- while (n--)
- if (p[n] == from) p[n] = 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;
+ }
}
@@ -208,17 +224,17 @@ static void buffreplace (LexState *ls, char from, char to) {
#endif
-#define buff2d(b,e) luaO_str2d(luaZ_buffer(b), luaZ_bufflen(b) - 1, e)
+#define buff2num(b,o) (luaO_str2num(luaZ_buffer(b), o) != 0)
/*
** 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, SemInfo *seminfo) {
+static void trydecpoint (LexState *ls, TValue *o) {
char old = ls->decpoint;
ls->decpoint = getlocaledecpoint();
buffreplace(ls, old, ls->decpoint); /* try new decimal separator */
- if (!buff2d(ls->buff, &seminfo->r)) {
+ if (!buff2num(ls->buff, o)) {
/* format error with correct decimal point: no more options */
buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */
lexerror(ls, "malformed number", TK_FLT);
@@ -228,41 +244,37 @@ static void trydecpoint (LexState *ls, SemInfo *seminfo) {
/* LUA_NUMBER */
/*
-** this function is quite liberal in what it accepts, as 'luaO_str2d'
-** will reject ill-formed numerals. 'isf' means the numeral is not
-** an integer (it has a dot or an exponent).
+** this function is quite liberal in what it accepts, as 'luaO_str2num'
+** will reject ill-formed numerals.
*/
-static int read_numeral (LexState *ls, SemInfo *seminfo, int isf) {
+static int read_numeral (LexState *ls, SemInfo *seminfo) {
+ TValue obj;
const char *expo = "Ee";
int first = ls->current;
lua_assert(lisdigit(ls->current));
save_and_next(ls);
- if (first == '0' && check_next(ls, "Xx")) /* hexadecimal? */
+ if (first == '0' && check_next2(ls, "xX")) /* hexadecimal? */
expo = "Pp";
for (;;) {
- if (check_next(ls, expo)) { /* exponent part? */
- check_next(ls, "+-"); /* optional exponent sign */
- isf = 1;
- }
+ if (check_next2(ls, expo)) /* exponent part? */
+ check_next2(ls, "-+"); /* optional exponent sign */
if (lisxdigit(ls->current))
save_and_next(ls);
- else if (ls->current == '.') {
+ else if (ls->current == '.')
save_and_next(ls);
- isf = 1;
- }
else break;
}
save(ls, '\0');
- if (!isf) {
- if (!luaO_str2int(luaZ_buffer(ls->buff), luaZ_bufflen(ls->buff) - 1,
- &seminfo->i))
- lexerror(ls, "malformed number", TK_INT);
+ buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */
+ if (!buff2num(ls->buff, &obj)) /* format error? */
+ trydecpoint(ls, &obj); /* try to update decimal point separator */
+ if (ttisinteger(&obj)) {
+ seminfo->i = ivalue(&obj);
return TK_INT;
}
else {
- buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */
- if (!buff2d(ls->buff, &seminfo->r)) /* format error? */
- trydecpoint(ls, seminfo); /* try to update decimal point separator */
+ lua_assert(ttisfloat(&obj));
+ seminfo->r = fltvalue(&obj);
return TK_FLT;
}
}
@@ -286,15 +298,19 @@ static int skip_sep (LexState *ls) {
static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) {
+ int line = ls->linenumber; /* initial line (for error message) */
save_and_next(ls); /* skip 2nd `[' */
if (currIsNewline(ls)) /* string starts with a newline? */
inclinenumber(ls); /* skip it */
for (;;) {
switch (ls->current) {
- case EOZ:
- lexerror(ls, (seminfo) ? "unfinished long string" :
- "unfinished long comment", TK_EOS);
+ case EOZ: { /* error */
+ const char *what = (seminfo ? "string" : "comment");
+ const char *msg = luaO_pushfstring(ls->L,
+ "unfinished long %s (starting at line %d)", what, line);
+ lexerror(ls, msg, TK_EOS);
break; /* to avoid warnings */
+ }
case ']': {
if (skip_sep(ls) == sep) {
save_and_next(ls); /* skip 2nd `]' */
@@ -488,35 +504,35 @@ static int llex (LexState *ls, SemInfo *seminfo) {
}
case '=': {
next(ls);
- if (ls->current != '=') return '=';
- else { next(ls); return TK_EQ; }
+ if (check_next1(ls, '=')) return TK_EQ;
+ else return '=';
}
case '<': {
next(ls);
- if (ls->current == '=') { next(ls); return TK_LE; }
- if (ls->current == '<') { next(ls); return TK_SHL; }
- return '<';
+ if (check_next1(ls, '=')) return TK_LE;
+ else if (check_next1(ls, '<')) return TK_SHL;
+ else return '<';
}
case '>': {
next(ls);
- if (ls->current == '=') { next(ls); return TK_GE; }
- if (ls->current == '>') { next(ls); return TK_SHR; }
- return '>';
+ if (check_next1(ls, '=')) return TK_GE;
+ else if (check_next1(ls, '>')) return TK_SHR;
+ else return '>';
}
case '/': {
next(ls);
- if (ls->current != '/') return '/';
- else { next(ls); return TK_IDIV; }
+ if (check_next1(ls, '/')) return TK_IDIV;
+ else return '/';
}
case '~': {
next(ls);
- if (ls->current != '=') return '~';
- else { next(ls); return TK_NE; }
+ if (check_next1(ls, '=')) return TK_NE;
+ else return '~';
}
case ':': {
next(ls);
- if (ls->current != ':') return ':';
- else { next(ls); return TK_DBCOLON; }
+ if (check_next1(ls, ':')) return TK_DBCOLON;
+ else return ':';
}
case '"': case '\'': { /* short literal strings */
read_string(ls, ls->current, seminfo);
@@ -524,17 +540,17 @@ static int llex (LexState *ls, SemInfo *seminfo) {
}
case '.': { /* '.', '..', '...', or number */
save_and_next(ls);
- if (check_next(ls, ".")) {
- if (check_next(ls, "."))
+ if (check_next1(ls, '.')) {
+ if (check_next1(ls, '.'))
return TK_DOTS; /* '...' */
else return TK_CONCAT; /* '..' */
}
else if (!lisdigit(ls->current)) return '.';
- else return read_numeral(ls, seminfo, 1);
+ else return read_numeral(ls, seminfo);
}
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': {
- return read_numeral(ls, seminfo, 0);
+ return read_numeral(ls, seminfo);
}
case EOZ: {
return TK_EOS;
diff --git a/src/llimits.h b/src/llimits.h
index 80a5d2a0..b3f7774d 100644
--- a/src/llimits.h
+++ b/src/llimits.h
@@ -1,5 +1,5 @@
/*
-** $Id: llimits.h,v 1.111 2014/03/07 16:19:00 roberto Exp $
+** $Id: llimits.h,v 1.116 2014/04/15 16:32:49 roberto Exp $
** Limits, basic types, and some other `installation-dependent' definitions
** See Copyright Notice in lua.h
*/
@@ -31,8 +31,8 @@ typedef unsigned char lu_byte;
#define MAX_SIZET ((size_t)(~(size_t)0)-2)
/* maximum size visible for Lua (must be representable in a lua_Integer */
-#define MAX_SIZE (sizeof(size_t) <= sizeof(lua_Integer) ? MAX_SIZET \
- : (size_t)(~(lua_Unsigned)0)-2)
+#define MAX_SIZE (sizeof(size_t) < sizeof(lua_Integer) ? MAX_SIZET \
+ : (size_t)(LUA_MAXINTEGER)-2)
#define MAX_LUMEM ((lu_mem)(~(lu_mem)0)-2)
@@ -43,13 +43,6 @@ typedef unsigned char lu_byte;
#define MAX_INT (INT_MAX-2) /* maximum value of an int (-2 for safety) */
-/* maximum value for a lua_Unsigned */
-#define MAX_UINTEGER (~(lua_Unsigned)0)
-
-/* minimum and maximum values for lua_Integer */
-#define MAX_INTEGER ((lua_Integer)(MAX_UINTEGER >> 1))
-#define MIN_INTEGER (~MAX_INTEGER)
-
/*
** conversion of pointer to integer
** this is for hashing only; there is no problem if the integer
@@ -67,8 +60,9 @@ typedef unsigned char lu_byte;
typedef LUAI_USER_ALIGNMENT_T L_Umaxalign;
-/* result of a `usual argument conversion' over lua_Number */
+/* types of 'usual argument conversions' for lua_Number and lua_Integer */
typedef LUAI_UACNUMBER l_uacNumber;
+typedef LUAI_UACINT l_uacInt;
/* internal assertions for in-house debugging */
@@ -111,8 +105,21 @@ typedef LUAI_UACNUMBER l_uacNumber;
#define cast_num(i) cast(lua_Number, (i))
#define cast_int(i) cast(int, (i))
#define cast_uchar(i) cast(unsigned char, (i))
-#define cast_integer(i) cast(lua_Integer, (i))
-#define cast_unsigned(i) cast(lua_Unsigned, (i))
+
+
+/* cast a signed lua_Integer to lua_Unsigned */
+#if !defined(l_castS2U)
+#define l_castS2U(i) ((lua_Unsigned)(i))
+#endif
+
+/*
+** cast a lua_Unsigned to a signed lua_Integer; this cast is
+** not strict ANSI C, but two-complement architectures should
+** work fine.
+*/
+#if !defined(l_castU2S)
+#define l_castU2S(i) ((lua_Integer)(i))
+#endif
/*
diff --git a/src/lmathlib.c b/src/lmathlib.c
index a40a6fb6..145b35ab 100644
--- a/src/lmathlib.c
+++ b/src/lmathlib.c
@@ -1,5 +1,5 @@
/*
-** $Id: lmathlib.c,v 1.92 2013/07/22 16:05:53 roberto Exp $
+** $Id: lmathlib.c,v 1.103 2014/06/18 12:35:53 roberto Exp $
** Standard mathematical library
** See Copyright Notice in lua.h
*/
@@ -18,12 +18,28 @@
#undef PI
-#define PI ((lua_Number)(3.1415926535897932384626433832795))
-#define RADIANS_PER_DEGREE ((lua_Number)(PI/180.0))
+#define PI (l_mathop(3.141592653589793238462643383279502884))
+
+
+#if !defined(l_rand) /* { */
+#if defined(LUA_USE_POSIX)
+#define l_rand() random()
+#define l_srand(x) srandom(x)
+#else
+#define l_rand() rand()
+#define l_srand(x) srand(x)
+#endif
+#endif /* } */
static int math_abs (lua_State *L) {
- lua_pushnumber(L, l_mathop(fabs)(luaL_checknumber(L, 1)));
+ if (lua_isinteger(L, 1)) {
+ lua_Integer n = lua_tointeger(L, 1);
+ if (n < 0) n = (lua_Integer)(0u - n);
+ lua_pushinteger(L, n);
+ }
+ else
+ lua_pushnumber(L, l_mathop(fabs)(luaL_checknumber(L, 1)));
return 1;
}
@@ -32,31 +48,16 @@ static int math_sin (lua_State *L) {
return 1;
}
-static int math_sinh (lua_State *L) {
- lua_pushnumber(L, l_mathop(sinh)(luaL_checknumber(L, 1)));
- return 1;
-}
-
static int math_cos (lua_State *L) {
lua_pushnumber(L, l_mathop(cos)(luaL_checknumber(L, 1)));
return 1;
}
-static int math_cosh (lua_State *L) {
- lua_pushnumber(L, l_mathop(cosh)(luaL_checknumber(L, 1)));
- return 1;
-}
-
static int math_tan (lua_State *L) {
lua_pushnumber(L, l_mathop(tan)(luaL_checknumber(L, 1)));
return 1;
}
-static int math_tanh (lua_State *L) {
- lua_pushnumber(L, l_mathop(tanh)(luaL_checknumber(L, 1)));
- return 1;
-}
-
static int math_asin (lua_State *L) {
lua_pushnumber(L, l_mathop(asin)(luaL_checknumber(L, 1)));
return 1;
@@ -68,56 +69,92 @@ static int math_acos (lua_State *L) {
}
static int math_atan (lua_State *L) {
- lua_pushnumber(L, l_mathop(atan)(luaL_checknumber(L, 1)));
+ lua_Number y = luaL_checknumber(L, 1);
+ lua_Number x = luaL_optnumber(L, 2, 1);
+ lua_pushnumber(L, l_mathop(atan2)(y, x));
return 1;
}
-static int math_atan2 (lua_State *L) {
- lua_pushnumber(L, l_mathop(atan2)(luaL_checknumber(L, 1),
- luaL_checknumber(L, 2)));
- return 1;
-}
-static int math_ceil (lua_State *L) {
- lua_pushnumber(L, l_mathop(ceil)(luaL_checknumber(L, 1)));
+static int math_ifloor (lua_State *L) {
+ int valid;
+ lua_Integer n = lua_tointegerx(L, 1, &valid);
+ if (valid)
+ lua_pushinteger(L, n); /* floor computed by Lua */
+ else {
+ luaL_checktype(L, 1, LUA_TNUMBER); /* argument must be a number */
+ lua_pushnil(L); /* number is not convertible to integer */
+ }
return 1;
}
-static int math_floor (lua_State *L) {
- lua_pushnumber(L, l_mathop(floor)(luaL_checknumber(L, 1)));
- return 1;
-}
-static int math_ifloor (lua_State *L) {
+static int math_floor (lua_State *L) {
int valid;
lua_Integer n = lua_tointegerx(L, 1, &valid);
if (valid)
- lua_pushinteger(L, n);
+ lua_pushinteger(L, n); /* floor computed by Lua */
+ else
+ lua_pushnumber(L, l_mathop(floor)(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+
+static void pushnumint (lua_State *L, lua_Number d) {
+ lua_Integer n;
+ if (lua_numtointeger(d, &n)) /* fits in an integer? */
+ lua_pushinteger(L, n); /* result is integer */
+ else
+ lua_pushnumber(L, d); /* result is float */
+}
+
+
+static int math_ceil (lua_State *L) {
+ if (lua_isinteger(L, 1))
+ lua_settop(L, 1); /* integer is its own ceil */
else {
- luaL_checktype(L, 1, LUA_TNUMBER); /* error if not a number */
- lua_pushnil(L); /* number with invalid integer value */
+ lua_Number d = l_mathop(ceil)(luaL_checknumber(L, 1));
+ pushnumint(L, d);
}
return 1;
}
+
static int math_fmod (lua_State *L) {
- lua_pushnumber(L, l_mathop(fmod)(luaL_checknumber(L, 1),
- luaL_checknumber(L, 2)));
+ if (lua_isinteger(L, 1) && lua_isinteger(L, 2)) {
+ lua_Integer d = lua_tointeger(L, 2);
+ if ((lua_Unsigned)d + 1u <= 1u) { /* special cases: -1 or 0 */
+ luaL_argcheck(L, d != 0, 2, "zero");
+ lua_pushinteger(L, 0); /* avoid overflow with 0x80000... / -1 */
+ }
+ else
+ lua_pushinteger(L, lua_tointeger(L, 1) % d);
+ }
+ else
+ lua_pushnumber(L, l_mathop(fmod)(luaL_checknumber(L, 1),
+ luaL_checknumber(L, 2)));
return 1;
}
+
/*
** next function does not use 'modf', avoiding problems with 'double*'
** (which is not compatible with 'float*') when lua_Number is not
** 'double'.
*/
static int math_modf (lua_State *L) {
- lua_Number n = luaL_checknumber(L, 1);
- /* integer part (rounds toward zero) */
- lua_Number ip = (n < 0) ? -l_mathop(floor)(-n) : l_mathop(floor)(n);
- lua_pushnumber(L, ip);
- /* fractionary part (test handles inf/-inf) */
- lua_pushnumber(L, (n == ip) ? 0.0 : (n - ip));
+ if (lua_isinteger(L ,1)) {
+ lua_settop(L, 1); /* number is its own integer part */
+ lua_pushnumber(L, 0); /* no fractionary part */
+ }
+ else {
+ lua_Number n = luaL_checknumber(L, 1);
+ /* integer part (rounds toward zero) */
+ lua_Number ip = (n < 0) ? l_mathop(ceil)(n) : l_mathop(floor)(n);
+ pushnumint(L, ip);
+ /* fractionary part (test needed for inf/-inf) */
+ lua_pushnumber(L, (n == ip) ? 0.0 : (n - ip));
+ }
return 2;
}
@@ -127,13 +164,6 @@ static int math_sqrt (lua_State *L) {
return 1;
}
-static int math_pow (lua_State *L) {
- lua_Number x = luaL_checknumber(L, 1);
- lua_Number y = luaL_checknumber(L, 2);
- lua_pushnumber(L, l_mathop(pow)(x, y));
- return 1;
-}
-
static int math_log (lua_State *L) {
lua_Number x = luaL_checknumber(L, 1);
lua_Number res;
@@ -141,84 +171,64 @@ static int math_log (lua_State *L) {
res = l_mathop(log)(x);
else {
lua_Number base = luaL_checknumber(L, 2);
- if (base == (lua_Number)10.0) res = l_mathop(log10)(x);
+ if (base == 10.0) res = l_mathop(log10)(x);
else res = l_mathop(log)(x)/l_mathop(log)(base);
}
lua_pushnumber(L, res);
return 1;
}
-#if defined(LUA_COMPAT_LOG10)
-static int math_log10 (lua_State *L) {
- lua_pushnumber(L, l_mathop(log10)(luaL_checknumber(L, 1)));
- return 1;
-}
-#endif
-
static int math_exp (lua_State *L) {
lua_pushnumber(L, l_mathop(exp)(luaL_checknumber(L, 1)));
return 1;
}
static int math_deg (lua_State *L) {
- lua_pushnumber(L, luaL_checknumber(L, 1)/RADIANS_PER_DEGREE);
+ lua_pushnumber(L, luaL_checknumber(L, 1) * (180.0 / PI));
return 1;
}
static int math_rad (lua_State *L) {
- lua_pushnumber(L, luaL_checknumber(L, 1)*RADIANS_PER_DEGREE);
+ lua_pushnumber(L, luaL_checknumber(L, 1) * (PI / 180.0));
return 1;
}
-static int math_frexp (lua_State *L) {
- int e;
- lua_pushnumber(L, l_mathop(frexp)(luaL_checknumber(L, 1), &e));
- lua_pushinteger(L, e);
- return 2;
-}
-
-static int math_ldexp (lua_State *L) {
- lua_Number x = luaL_checknumber(L, 1);
- int ep = luaL_checkint(L, 2);
- lua_pushnumber(L, l_mathop(ldexp)(x, ep));
- return 1;
-}
-
-
static int math_min (lua_State *L) {
int n = lua_gettop(L); /* number of arguments */
- lua_Number dmin = luaL_checknumber(L, 1);
+ int imin = 1; /* index of current minimum value */
int i;
- for (i=2; i<=n; i++) {
- lua_Number d = luaL_checknumber(L, i);
- if (d < dmin)
- dmin = d;
+ luaL_argcheck(L, n >= 1, 1, "value expected");
+ for (i = 2; i <= n; i++) {
+ if (lua_compare(L, i, imin, LUA_OPLT))
+ imin = i;
}
- lua_pushnumber(L, dmin);
+ lua_pushvalue(L, imin);
return 1;
}
static int math_max (lua_State *L) {
int n = lua_gettop(L); /* number of arguments */
- lua_Number dmax = luaL_checknumber(L, 1);
+ int imax = 1; /* index of current maximum value */
int i;
- for (i=2; i<=n; i++) {
- lua_Number d = luaL_checknumber(L, i);
- if (d > dmax)
- dmax = d;
+ luaL_argcheck(L, n >= 1, 1, "value expected");
+ for (i = 2; i <= n; i++) {
+ if (lua_compare(L, imax, i, LUA_OPLT))
+ imax = i;
}
- lua_pushnumber(L, dmax);
+ lua_pushvalue(L, imax);
return 1;
}
-
+/*
+** This function uses 'double' (instead of 'lua_Number') to ensure that
+** all bits from 'l_rand' can be represented, and that 'RAND_MAX + 1.0'
+** will keep full precision (ensuring that 'r' is always less than 1.0.)
+*/
static int math_random (lua_State *L) {
- /* the `%' avoids the (rare) case of r==1, and is needed also because on
- some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */
- lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX;
lua_Integer low, up;
+ double r = (double)l_rand() * (1.0 / ((double)RAND_MAX + 1.0));
switch (lua_gettop(L)) { /* check number of arguments */
case 0: { /* no arguments */
lua_pushnumber(L, r); /* Number between 0 and 1 */
@@ -237,15 +247,17 @@ static int math_random (lua_State *L) {
default: return luaL_error(L, "wrong number of arguments");
}
/* random integer in the interval [low, up] */
- up++; /* change interval to [low, up) */
- luaL_argcheck(L, up - low > 0, 1, "interval is empty");
- lua_pushinteger(L, (lua_Integer)(r * (lua_Number)(up - low)) + low);
+ luaL_argcheck(L, low <= up, 1, "interval is empty");
+ luaL_argcheck(L, (lua_Unsigned)up - low <= (lua_Unsigned)LUA_MAXINTEGER,
+ 1, "interval too large");
+ r *= (double)(up - low) + 1.0;
+ lua_pushinteger(L, (lua_Integer)r + low);
return 1;
}
static int math_randomseed (lua_State *L) {
- srand(luaL_checkunsigned(L, 1));
+ l_srand((unsigned int)luaL_checkunsigned(L, 1));
(void)rand(); /* discard first value to avoid undesirable correlations */
return 0;
}
@@ -265,39 +277,92 @@ static int math_type (lua_State *L) {
}
+/*
+** {==================================================================
+** Deprecated functions (for compatibility only)
+** ===================================================================
+*/
+#if defined(LUA_COMPAT_MATHLIB)
+
+static int math_cosh (lua_State *L) {
+ lua_pushnumber(L, l_mathop(cosh)(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_sinh (lua_State *L) {
+ lua_pushnumber(L, l_mathop(sinh)(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_tanh (lua_State *L) {
+ lua_pushnumber(L, l_mathop(tanh)(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_pow (lua_State *L) {
+ lua_Number x = luaL_checknumber(L, 1);
+ lua_Number y = luaL_checknumber(L, 2);
+ lua_pushnumber(L, l_mathop(pow)(x, y));
+ return 1;
+}
+
+static int math_frexp (lua_State *L) {
+ int e;
+ lua_pushnumber(L, l_mathop(frexp)(luaL_checknumber(L, 1), &e));
+ lua_pushinteger(L, e);
+ return 2;
+}
+
+static int math_ldexp (lua_State *L) {
+ lua_Number x = luaL_checknumber(L, 1);
+ int ep = luaL_checkint(L, 2);
+ lua_pushnumber(L, l_mathop(ldexp)(x, ep));
+ return 1;
+}
+
+static int math_log10 (lua_State *L) {
+ lua_pushnumber(L, l_mathop(log10)(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+#endif
+/* }================================================================== */
+
+
+
static const luaL_Reg mathlib[] = {
{"abs", math_abs},
{"acos", math_acos},
{"asin", math_asin},
- {"atan2", math_atan2},
{"atan", math_atan},
{"ceil", math_ceil},
- {"cosh", math_cosh},
{"cos", math_cos},
{"deg", math_deg},
{"exp", math_exp},
- {"floor", math_floor},
{"ifloor", math_ifloor},
+ {"floor", math_floor},
{"fmod", math_fmod},
- {"frexp", math_frexp},
- {"ldexp", math_ldexp},
-#if defined(LUA_COMPAT_LOG10)
- {"log10", math_log10},
-#endif
{"log", math_log},
{"max", math_max},
{"min", math_min},
{"modf", math_modf},
- {"pow", math_pow},
{"rad", math_rad},
{"random", math_random},
{"randomseed", math_randomseed},
- {"sinh", math_sinh},
{"sin", math_sin},
{"sqrt", math_sqrt},
- {"tanh", math_tanh},
{"tan", math_tan},
{"type", math_type},
+#if defined(LUA_COMPAT_MATHLIB)
+ {"atan2", math_atan},
+ {"cosh", math_cosh},
+ {"sinh", math_sinh},
+ {"tanh", math_tanh},
+ {"pow", math_pow},
+ {"frexp", math_frexp},
+ {"ldexp", math_ldexp},
+ {"log10", math_log10},
+#endif
{NULL, NULL}
};
@@ -311,6 +376,10 @@ LUAMOD_API int luaopen_math (lua_State *L) {
lua_setfield(L, -2, "pi");
lua_pushnumber(L, HUGE_VAL);
lua_setfield(L, -2, "huge");
+ lua_pushinteger(L, LUA_MAXINTEGER);
+ lua_setfield(L, -2, "maxinteger");
+ lua_pushinteger(L, LUA_MININTEGER);
+ lua_setfield(L, -2, "mininteger");
return 1;
}
diff --git a/src/lobject.c b/src/lobject.c
index 41bde947..0130c1c0 100644
--- a/src/lobject.c
+++ b/src/lobject.c
@@ -1,5 +1,5 @@
/*
-** $Id: lobject.c,v 2.76 2014/03/21 13:52:33 roberto Exp $
+** $Id: lobject.c,v 2.86 2014/05/12 21:44:17 roberto Exp $
** Some generic functions over Lua objects
** See Copyright Notice in lua.h
*/
@@ -77,7 +77,6 @@ static lua_Integer intarith (lua_State *L, int op, lua_Integer v1,
case LUA_OPSUB:return intop(-, v1, v2);
case LUA_OPMUL:return intop(*, v1, v2);
case LUA_OPMOD: return luaV_mod(L, v1, v2);
- case LUA_OPPOW: return luaV_pow(L, v1, v2);
case LUA_OPIDIV: return luaV_div(L, v1, v2);
case LUA_OPBAND: return intop(&, v1, v2);
case LUA_OPBOR: return intop(|, v1, v2);
@@ -85,7 +84,7 @@ static lua_Integer intarith (lua_State *L, int op, lua_Integer v1,
case LUA_OPSHL: return luaV_shiftl(v1, v2);
case LUA_OPSHR: return luaV_shiftl(v1, -v2);
case LUA_OPUNM: return intop(-, 0, v1);
- case LUA_OPBNOT: return intop(^, cast_integer(-1), v1);
+ case LUA_OPBNOT: return intop(^, ~l_castS2U(0), v1);
default: lua_assert(0); return 0;
}
}
@@ -98,9 +97,13 @@ static lua_Number numarith (lua_State *L, int op, lua_Number v1,
case LUA_OPSUB: return luai_numsub(L, v1, v2);
case LUA_OPMUL: return luai_nummul(L, v1, v2);
case LUA_OPDIV: return luai_numdiv(L, v1, v2);
- case LUA_OPMOD: return luai_nummod(L, v1, v2);
case LUA_OPPOW: return luai_numpow(L, v1, v2);
case LUA_OPUNM: return luai_numunm(L, v1);
+ case LUA_OPMOD: {
+ lua_Number m;
+ luai_nummod(L, v1, v2, m);
+ return m;
+ }
default: lua_assert(0); return 0;
}
}
@@ -119,10 +122,10 @@ void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2,
}
else break; /* go to the end */
}
- case LUA_OPDIV: { /* operates only on floats */
+ case LUA_OPDIV: case LUA_OPPOW: { /* operate only on floats */
lua_Number n1; lua_Number n2;
if (tonumber(p1, &n1) && tonumber(p2, &n2)) {
- setnvalue(res, numarith(L, op, n1, n2));
+ setfltvalue(res, numarith(L, op, n1, n2));
return;
}
else break; /* go to the end */
@@ -134,7 +137,7 @@ void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2,
return;
}
else if (tonumber(p1, &n1) && tonumber(p2, &n2)) {
- setnvalue(res, numarith(L, op, n1, n2));
+ setfltvalue(res, numarith(L, op, n1, n2));
return;
}
else break; /* go to the end */
@@ -249,22 +252,21 @@ static lua_Number lua_strx2number (const char *s, char **endptr) {
/* }====================================================== */
-int luaO_str2d (const char *s, size_t len, lua_Number *result) {
+static const char *l_str2d (const char *s, lua_Number *result) {
char *endptr;
if (strpbrk(s, "nN")) /* reject 'inf' and 'nan' */
- return 0;
+ return NULL;
else if (strpbrk(s, "xX")) /* hexa? */
*result = lua_strx2number(s, &endptr);
else
*result = lua_str2number(s, &endptr);
if (endptr == s) return 0; /* nothing recognized */
while (lisspace(cast_uchar(*endptr))) endptr++;
- return (endptr == s + len); /* OK if no trailing characters */
+ return (*endptr == '\0' ? endptr : NULL); /* OK if no trailing characters */
}
-int luaO_str2int (const char *s, size_t len, lua_Integer *result) {
- const char *ends = s + len;
+static const char *l_str2int (const char *s, lua_Integer *result) {
lua_Unsigned a = 0;
int empty = 1;
int neg;
@@ -285,14 +287,29 @@ int luaO_str2int (const char *s, size_t len, lua_Integer *result) {
}
}
while (lisspace(cast_uchar(*s))) s++; /* skip trailing spaces */
- if (empty || s != ends) return 0; /* something wrong in the numeral */
+ if (empty || *s != '\0') return NULL; /* something wrong in the numeral */
else {
- *result = cast_integer((neg) ? 0u - a : a);
- return 1;
+ *result = l_castU2S((neg) ? 0u - a : a);
+ return s;
}
}
+size_t luaO_str2num (const char *s, TValue *o) {
+ lua_Integer i; lua_Number n;
+ const char *e;
+ if ((e = l_str2int(s, &i)) != NULL) { /* try as an integer */
+ setivalue(o, i);
+ }
+ else if ((e = l_str2d(s, &n)) != NULL) { /* else try as a float */
+ setfltvalue(o, n);
+ }
+ else
+ return 0; /* conversion failed */
+ return (e - s + 1); /* success; return string size */
+}
+
+
int luaO_utf8esc (char *buff, unsigned int x) {
int n = 1; /* number of bytes put in buffer (backwards) */
if (x < 0x80) /* ascii? */
@@ -339,14 +356,17 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
}
case 'd': {
setivalue(L->top++, cast_int(va_arg(argp, int)));
+ luaV_tostring(L, L->top - 1);
break;
}
case 'I': {
- setivalue(L->top++, cast_integer(va_arg(argp, lua_Integer)));
+ setivalue(L->top++, cast(lua_Integer, va_arg(argp, l_uacInt)));
+ luaV_tostring(L, L->top - 1);
break;
}
case 'f': {
- setnvalue(L->top++, cast_num(va_arg(argp, l_uacNumber)));
+ setfltvalue(L->top++, cast_num(va_arg(argp, l_uacNumber)));
+ luaV_tostring(L, L->top - 1);
break;
}
case 'p': {
diff --git a/src/lobject.h b/src/lobject.h
index b8b621f9..7c512422 100644
--- a/src/lobject.h
+++ b/src/lobject.h
@@ -1,5 +1,5 @@
/*
-** $Id: lobject.h,v 2.86 2014/02/19 13:52:42 roberto Exp $
+** $Id: lobject.h,v 2.94 2014/06/19 18:39:36 roberto Exp $
** Type definitions for Lua objects
** See Copyright Notice in lua.h
*/
@@ -156,17 +156,17 @@ typedef struct lua_TValue TValue;
#define fltvalue(o) check_exp(ttisfloat(o), val_(o).n)
#define gcvalue(o) check_exp(iscollectable(o), val_(o).gc)
#define pvalue(o) check_exp(ttislightuserdata(o), val_(o).p)
-#define rawtsvalue(o) check_exp(ttisstring(o), &val_(o).gc->ts)
+#define rawtsvalue(o) check_exp(ttisstring(o), rawgco2ts(val_(o).gc))
#define tsvalue(o) (&rawtsvalue(o)->tsv)
-#define rawuvalue(o) check_exp(ttisfulluserdata(o), &val_(o).gc->u)
+#define rawuvalue(o) check_exp(ttisfulluserdata(o), rawgco2u(val_(o).gc))
#define uvalue(o) (&rawuvalue(o)->uv)
-#define clvalue(o) check_exp(ttisclosure(o), &val_(o).gc->cl)
-#define clLvalue(o) check_exp(ttisLclosure(o), &val_(o).gc->cl.l)
-#define clCvalue(o) check_exp(ttisCclosure(o), &val_(o).gc->cl.c)
+#define clvalue(o) check_exp(ttisclosure(o), gco2cl(val_(o).gc))
+#define clLvalue(o) check_exp(ttisLclosure(o), gco2lcl(val_(o).gc))
+#define clCvalue(o) check_exp(ttisCclosure(o), gco2ccl(val_(o).gc))
#define fvalue(o) check_exp(ttislcf(o), val_(o).f)
-#define hvalue(o) check_exp(ttistable(o), &val_(o).gc->h)
+#define hvalue(o) check_exp(ttistable(o), gco2t(val_(o).gc))
#define bvalue(o) check_exp(ttisboolean(o), val_(o).b)
-#define thvalue(o) check_exp(ttisthread(o), &val_(o).gc->th)
+#define thvalue(o) check_exp(ttisthread(o), gco2th(val_(o).gc))
/* a dead value may get the 'gc' field, but cannot access its contents */
#define deadvalue(o) check_exp(ttisdeadkey(o), cast(void *, val_(o).gc))
@@ -187,7 +187,7 @@ typedef struct lua_TValue TValue;
/* Macros to set values */
#define settt_(o,t) ((o)->tt_=(t))
-#define setnvalue(obj,x) \
+#define setfltvalue(obj,x) \
{ TValue *io=(obj); val_(io).n=(x); settt_(io, LUA_TNUMFLT); }
#define setivalue(obj,x) \
@@ -205,38 +205,37 @@ typedef struct lua_TValue TValue;
{ TValue *io=(obj); val_(io).b=(x); settt_(io, LUA_TBOOLEAN); }
#define setgcovalue(L,obj,x) \
- { TValue *io=(obj); GCObject *i_g=(x); \
- val_(io).gc=i_g; settt_(io, ctb(gch(i_g)->tt)); }
+ { TValue *io = (obj); GCObject *i_g=(x); \
+ val_(io).gc = i_g; settt_(io, ctb(gch(i_g)->tt)); }
#define setsvalue(L,obj,x) \
- { TValue *io=(obj); \
- TString *x_ = (x); \
- val_(io).gc=cast(GCObject *, x_); settt_(io, ctb(x_->tsv.tt)); \
+ { TValue *io = (obj); TString *x_ = (x); \
+ val_(io).gc = obj2gco(x_); settt_(io, ctb(x_->tsv.tt)); \
checkliveness(G(L),io); }
#define setuvalue(L,obj,x) \
- { TValue *io=(obj); \
- val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TUSERDATA)); \
+ { TValue *io = (obj); Udata *x_ = (x); \
+ val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TUSERDATA)); \
checkliveness(G(L),io); }
#define setthvalue(L,obj,x) \
- { TValue *io=(obj); \
- val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TTHREAD)); \
+ { TValue *io = (obj); lua_State *x_ = (x); \
+ val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TTHREAD)); \
checkliveness(G(L),io); }
#define setclLvalue(L,obj,x) \
- { TValue *io=(obj); \
- val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TLCL)); \
+ { TValue *io = (obj); LClosure *x_ = (x); \
+ val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TLCL)); \
checkliveness(G(L),io); }
#define setclCvalue(L,obj,x) \
- { TValue *io=(obj); \
- val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TCCL)); \
+ { TValue *io = (obj); CClosure *x_ = (x); \
+ val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TCCL)); \
checkliveness(G(L),io); }
#define sethvalue(L,obj,x) \
- { TValue *io=(obj); \
- val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TTABLE)); \
+ { TValue *io = (obj); Table *x_ = (x); \
+ val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TTABLE)); \
checkliveness(G(L),io); }
#define setdeadvalue(obj) settt_(obj, LUA_TDEADKEY)
@@ -246,7 +245,7 @@ typedef struct lua_TValue TValue;
#define setobj(L,obj1,obj2) \
{ const TValue *io2=(obj2); TValue *io1=(obj1); \
io1->value_ = io2->value_; io1->tt_ = io2->tt_; \
- checkliveness(G(L),io1); }
+ (void)L; checkliveness(G(L),io1); }
/*
@@ -269,10 +268,6 @@ typedef struct lua_TValue TValue;
#define setsvalue2n setsvalue
-/* check whether a number is valid (useful only for NaN trick) */
-#define luai_checknum(L,o,c) { /* empty */ }
-
-
/*
@@ -310,9 +305,9 @@ typedef union TString {
struct {
CommonHeader;
lu_byte extra; /* reserved words for short strings; "has hash" for longs */
+ unsigned int hash;
size_t len; /* number of characters in string */
union TString *hnext; /* linked list for hash table */
- unsigned int hash;
} tsv;
} TString;
@@ -377,14 +372,9 @@ typedef struct LocVar {
*/
typedef struct Proto {
CommonHeader;
- TValue *k; /* constants used by the function */
- Instruction *code;
- struct Proto **p; /* functions defined inside the function */
- int *lineinfo; /* map from opcodes to source lines (debug information) */
- LocVar *locvars; /* information about local variables (debug information) */
- Upvaldesc *upvalues; /* upvalue information */
- union Closure *cache; /* last created closure with this prototype */
- TString *source; /* used for debug information */
+ lu_byte numparams; /* number of fixed parameters */
+ lu_byte is_vararg;
+ lu_byte maxstacksize; /* maximum stack used by this function */
int sizeupvalues; /* size of 'upvalues' */
int sizek; /* size of `k' */
int sizecode;
@@ -393,10 +383,15 @@ typedef struct Proto {
int sizelocvars;
int linedefined;
int lastlinedefined;
+ TValue *k; /* constants used by the function */
+ Instruction *code;
+ struct Proto **p; /* functions defined inside the function */
+ int *lineinfo; /* map from opcodes to source lines (debug information) */
+ LocVar *locvars; /* information about local variables (debug information) */
+ Upvaldesc *upvalues; /* upvalue information */
+ struct LClosure *cache; /* last created closure with this prototype */
+ TString *source; /* used for debug information */
GCObject *gclist;
- lu_byte numparams; /* number of fixed parameters */
- lu_byte is_vararg;
- lu_byte maxstacksize; /* maximum stack used by this function */
} Proto;
@@ -462,12 +457,12 @@ typedef struct Table {
CommonHeader;
lu_byte flags; /* 1<<p means tagmethod(p) is not present */
lu_byte lsizenode; /* log2 of size of `node' array */
- struct Table *metatable;
+ int sizearray; /* size of `array' array */
TValue *array; /* array part */
Node *node;
Node *lastfree; /* any free position is before this position */
+ struct Table *metatable;
GCObject *gclist;
- int sizearray; /* size of `array' array */
} Table;
@@ -500,8 +495,7 @@ LUAI_FUNC int luaO_utf8esc (char *buff, unsigned int x);
LUAI_FUNC int luaO_ceillog2 (unsigned int x);
LUAI_FUNC void luaO_arith (lua_State *L, int op, const TValue *p1,
const TValue *p2, TValue *res);
-LUAI_FUNC int luaO_str2d (const char *s, size_t len, lua_Number *result);
-LUAI_FUNC int luaO_str2int (const char *s, size_t len, lua_Integer *result);
+LUAI_FUNC size_t luaO_str2num (const char *s, TValue *o);
LUAI_FUNC int luaO_hexavalue (int c);
LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt,
va_list argp);
diff --git a/src/loslib.c b/src/loslib.c
index 776dda57..3be1d999 100644
--- a/src/loslib.c
+++ b/src/loslib.c
@@ -1,5 +1,5 @@
/*
-** $Id: loslib.c,v 1.45 2014/03/20 19:18:54 roberto Exp $
+** $Id: loslib.c,v 1.46 2014/04/29 17:05:13 roberto Exp $
** Standard Operating System library
** See Copyright Notice in lua.h
*/
@@ -59,9 +59,15 @@
#if defined(LUA_USE_POSIX) /* { */
#include <unistd.h>
+
#define LUA_TMPNAMBUFSIZE 32
+
+#if !defined(LUA_TMPNAMTEMPLATE)
+#define LUA_TMPNAMTEMPLATE "/tmp/lua_XXXXXX"
+#endif
+
#define lua_tmpnam(b,e) { \
- strcpy(b, "/tmp/lua_XXXXXX"); \
+ strcpy(b, LUA_TMPNAMTEMPLATE); \
e = mkstemp(b); \
if (e != -1) close(e); \
e = (e == -1); }
diff --git a/src/lparser.c b/src/lparser.c
index 93491497..6c097d7f 100644
--- a/src/lparser.c
+++ b/src/lparser.c
@@ -1,5 +1,5 @@
/*
-** $Id: lparser.c,v 2.138 2013/12/30 20:47:58 roberto Exp $
+** $Id: lparser.c,v 2.139 2014/06/19 18:27:20 roberto Exp $
** Lua Parser
** See Copyright Notice in lua.h
*/
@@ -1618,17 +1618,17 @@ static void mainfunc (LexState *ls, FuncState *fs) {
}
-Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
- Dyndata *dyd, const char *name, int firstchar) {
+LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
+ Dyndata *dyd, const char *name, int firstchar) {
LexState lexstate;
FuncState funcstate;
- Closure *cl = luaF_newLclosure(L, 1); /* create main closure */
+ LClosure *cl = luaF_newLclosure(L, 1); /* create main closure */
setclLvalue(L, L->top, cl); /* anchor it (to avoid being collected) */
incr_top(L);
lexstate.h = luaH_new(L); /* create table for scanner */
sethvalue(L, L->top, lexstate.h); /* anchor it */
incr_top(L);
- funcstate.f = cl->l.p = luaF_newproto(L);
+ funcstate.f = cl->p = luaF_newproto(L);
funcstate.f->source = luaS_new(L, name); /* create and anchor TString */
luaC_objbarrier(L, funcstate.f, funcstate.f->source);
lexstate.buff = buff;
diff --git a/src/lparser.h b/src/lparser.h
index 172d96d2..efceb054 100644
--- a/src/lparser.h
+++ b/src/lparser.h
@@ -1,5 +1,5 @@
/*
-** $Id: lparser.h,v 1.72 2013/08/30 16:01:37 roberto Exp $
+** $Id: lparser.h,v 1.73 2014/06/19 18:27:20 roberto Exp $
** Lua Parser
** See Copyright Notice in lua.h
*/
@@ -113,8 +113,8 @@ typedef struct FuncState {
} FuncState;
-LUAI_FUNC Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
- Dyndata *dyd, const char *name, int firstchar);
+LUAI_FUNC LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
+ Dyndata *dyd, const char *name, int firstchar);
#endif
diff --git a/src/lstate.h b/src/lstate.h
index 7029adb3..add9e95b 100644
--- a/src/lstate.h
+++ b/src/lstate.h
@@ -1,5 +1,5 @@
/*
-** $Id: lstate.h,v 2.102 2014/02/18 13:46:26 roberto Exp $
+** $Id: lstate.h,v 2.107 2014/06/12 19:07:30 roberto Exp $
** Global State
** See Copyright Notice in lua.h
*/
@@ -60,20 +60,18 @@ typedef struct CallInfo {
StkId func; /* function index in the stack */
StkId top; /* top for this function */
struct CallInfo *previous, *next; /* dynamic call link */
+ ptrdiff_t extra;
short nresults; /* expected number of results from this function */
lu_byte callstatus;
- ptrdiff_t extra;
union {
struct { /* only for Lua functions */
StkId base; /* base for this function */
const Instruction *savedpc;
} l;
struct { /* only for C functions */
- int ctx; /* context info. in case of yields */
- lua_CFunction k; /* continuation in case of yields */
+ lua_KFunction k; /* continuation in case of yields */
ptrdiff_t old_errfunc;
- lu_byte old_allowhook;
- lu_byte status;
+ int ctx; /* context info. in case of yields */
} c;
} u;
} CallInfo;
@@ -82,19 +80,21 @@ typedef struct CallInfo {
/*
** Bits in CallInfo status
*/
-#define CIST_LUA (1<<0) /* call is running a Lua function */
-#define CIST_HOOKED (1<<1) /* call is running a debug hook */
-#define CIST_REENTRY (1<<2) /* call is running on same invocation of
+#define CIST_OAH (1<<0) /* original value of 'allowhook' */
+#define CIST_LUA (1<<1) /* call is running a Lua function */
+#define CIST_HOOKED (1<<2) /* call is running a debug hook */
+#define CIST_REENTRY (1<<3) /* call is running on same invocation of
luaV_execute of previous call */
-#define CIST_YIELDED (1<<3) /* call reentered after suspension */
#define CIST_YPCALL (1<<4) /* call is a yieldable protected call */
-#define CIST_STAT (1<<5) /* call has an error status (pcall) */
-#define CIST_TAIL (1<<6) /* call was tail called */
-#define CIST_HOOKYIELD (1<<7) /* last hook called yielded */
-
+#define CIST_TAIL (1<<5) /* call was tail called */
+#define CIST_HOOKYIELD (1<<6) /* last hook called yielded */
#define isLua(ci) ((ci)->callstatus & CIST_LUA)
+/* assume that CIST_OAH has offset 0 and that 'v' is strictly 0/1 */
+#define setoah(st,v) ((st) = ((st) & ~CIST_OAH) | (v))
+#define getoah(st) ((st) & CIST_OAH)
+
/*
** `global state', shared by all threads of this state
diff --git a/src/lstring.c b/src/lstring.c
index bbadb315..c63111a8 100644
--- a/src/lstring.c
+++ b/src/lstring.c
@@ -1,5 +1,5 @@
/*
-** $Id: lstring.c,v 2.38 2014/03/19 18:51:42 roberto Exp $
+** $Id: lstring.c,v 2.40 2014/06/18 22:59:29 roberto Exp $
** String table (keeps all strings handled by Lua)
** See Copyright Notice in lua.h
*/
@@ -90,9 +90,11 @@ void luaS_resize (lua_State *L, int newsize) {
static TString *createstrobj (lua_State *L, const char *str, size_t l,
int tag, unsigned int h) {
TString *ts;
+ GCObject *o;
size_t totalsize; /* total size of TString object */
totalsize = sizeof(TString) + ((l + 1) * sizeof(char));
- ts = &luaC_newobj(L, tag, totalsize)->ts;
+ o = luaC_newobj(L, tag, totalsize);
+ ts = rawgco2ts(o);
ts->tsv.len = l;
ts->tsv.hash = h;
ts->tsv.extra = 0;
@@ -102,7 +104,7 @@ static TString *createstrobj (lua_State *L, const char *str, size_t l,
}
-LUAI_FUNC void luaS_remove (lua_State *L, TString *ts) {
+void luaS_remove (lua_State *L, TString *ts) {
stringtable *tb = &G(L)->strt;
TString **p = &tb->hash[lmod(ts->tsv.hash, tb->size)];
while (*p != ts) /* find previous element */
@@ -165,9 +167,11 @@ TString *luaS_new (lua_State *L, const char *str) {
Udata *luaS_newudata (lua_State *L, size_t s) {
Udata *u;
+ GCObject *o;
if (s > MAX_SIZE - sizeof(Udata))
luaM_toobig(L);
- u = &luaC_newobj(L, LUA_TUSERDATA, sizeof(Udata) + s)->u;
+ o = luaC_newobj(L, LUA_TUSERDATA, sizeof(Udata) + s);
+ u = rawgco2u(o);
u->uv.len = s;
u->uv.metatable = NULL;
setuservalue(L, u, luaO_nilobject);
diff --git a/src/lstrlib.c b/src/lstrlib.c
index d8106c0d..3cbd91b2 100644
--- a/src/lstrlib.c
+++ b/src/lstrlib.c
@@ -1,5 +1,5 @@
/*
-** $Id: lstrlib.c,v 1.189 2014/03/21 14:26:44 roberto Exp $
+** $Id: lstrlib.c,v 1.198 2014/04/27 14:42:26 roberto Exp $
** Standard library for string operations and pattern-matching
** See Copyright Notice in lua.h
*/
@@ -104,8 +104,8 @@ static int str_upper (lua_State *L) {
/* reasonable limit to avoid arithmetic overflow and strings too big */
-#if INT_MAX / 2 <= 0x10000000
-#define MAXSIZE ((size_t)(INT_MAX / 2))
+#if LUA_MAXINTEGER / 2 <= 0x10000000
+#define MAXSIZE ((size_t)(LUA_MAXINTEGER / 2))
#else
#define MAXSIZE ((size_t)0x10000000)
#endif
@@ -946,22 +946,22 @@ static int str_format (lua_State *L) {
** =======================================================
*/
-/* maximum size for the binary representation of an integer */
-#define MAXINTSIZE 8
-
/* number of bits in a character */
#define NB CHAR_BIT
-/* mask for one character (NB ones) */
-#define MC (((lua_Integer)1 << NB) - 1)
-
-/* mask for one character without sign ((NB - 1) ones) */
-#define SM (((lua_Integer)1 << (NB - 1)) - 1)
+/* mask for one character (NB 1's) */
+#define MC ((1 << NB) - 1)
+/* mask for one character without sign bit ((NB - 1) 1's) */
+#define SM (MC >> 1)
+/* size of a lua_Integer */
#define SZINT ((int)sizeof(lua_Integer))
+/* maximum size for the binary representation of an integer */
+#define MAXINTSIZE 12
+
static union {
int dummy;
@@ -975,7 +975,7 @@ static int getendian (lua_State *L, int arg) {
if (*endian == 'n') /* native? */
return nativeendian.little;
luaL_argcheck(L, *endian == 'l' || *endian == 'b', arg,
- "endianess must be 'l'/'b'/'n'");
+ "endianness must be 'l'/'b'/'n'");
return (*endian == 'l');
}
@@ -989,34 +989,43 @@ static int getintsize (lua_State *L, int arg) {
}
-static int packint (char *buff, lua_Integer n, int littleendian, int size) {
+/* mask for all ones in last byte in a lua Integer */
+#define HIGHERBYTE ((lua_Unsigned)MC << (NB * (SZINT - 1)))
+
+
+static int dumpint (char *buff, lua_Integer m, int littleendian, int size) {
int i;
+ lua_Unsigned n = (lua_Unsigned)m;
+ lua_Unsigned mask = (m >= 0) ? 0 : HIGHERBYTE; /* sign extension */
if (littleendian) {
for (i = 0; i < size - 1; i++) {
buff[i] = (n & MC);
- n >>= NB;
+ n = (n >> NB) | mask;
}
}
else {
for (i = size - 1; i > 0; i--) {
buff[i] = (n & MC);
- n >>= NB;
+ n = (n >> NB) | mask;
}
}
buff[i] = (n & MC); /* last byte */
- /* test for overflow: OK if there are only zeros left in higher bytes,
- or if there are only ones left and packed number is negative (signal
- bit, the higher bit in last byte, is one) */
- return ((n & ~MC) == 0 || (n | SM) == ~(lua_Integer)0);
+ if (size < SZINT) { /* need test for overflow? */
+ /* OK if there are only zeros left in higher bytes,
+ or only ones left (excluding non-signal bits in last byte) */
+ return ((n & ~(lua_Unsigned)MC) == 0 ||
+ (n | SM) == ~(lua_Unsigned)0);
+ }
+ else return 1; /* no overflow can occur with full size */
}
-static int packint_l (lua_State *L) {
+static int dumpint_l (lua_State *L) {
char buff[MAXINTSIZE];
lua_Integer n = luaL_checkinteger(L, 1);
int size = getintsize(L, 2);
int endian = getendian(L, 3);
- if (packint(buff, n, endian, size))
+ if (dumpint(buff, n, endian, size))
lua_pushlstring(L, buff, size);
else
luaL_error(L, "integer does not fit into given size (%d)", size);
@@ -1024,15 +1033,13 @@ static int packint_l (lua_State *L) {
}
-/* mask to check higher-order byte in a Lua integer */
-#define HIGHERBYTE (MC << (NB * (SZINT - 1)))
-
/* mask to check higher-order byte + signal bit of next (lower) byte */
-#define HIGHERBYTE1 (HIGHERBYTE | (HIGHERBYTE >> 1))
+#define HIGHERBYTE1 (HIGHERBYTE | (HIGHERBYTE >> 1))
-static int unpackint (const char *buff, lua_Integer *res,
+
+static int undumpint (const char *buff, lua_Integer *res,
int littleendian, int size) {
- lua_Integer n = 0;
+ lua_Unsigned n = 0;
int i;
for (i = 0; i < size; i++) {
if (i >= SZINT) { /* will throw away a byte? */
@@ -1042,23 +1049,23 @@ static int unpackint (const char *buff, lua_Integer *res,
its "signal bit" */
if (!((n & HIGHERBYTE1) == 0 || /* zeros for positive number */
(n & HIGHERBYTE1) == HIGHERBYTE1 || /* ones for negative number */
- ((n & HIGHERBYTE) == 0 && i == size - 1))) /* leading zero */
+ (i == size - 1 && (n & HIGHERBYTE) == 0))) /* leading zero */
return 0; /* overflow */
}
n <<= NB;
- n |= (lua_Integer)(unsigned char)buff[littleendian ? size - 1 - i : i];
+ n |= (lua_Unsigned)(unsigned char)buff[littleendian ? size - 1 - i : i];
}
if (size < SZINT) { /* need sign extension? */
- lua_Integer mask = (~(lua_Integer)0) << (size*NB - 1);
- if (n & mask) /* negative value? */
- n |= mask; /* signal extension */
+ lua_Unsigned mask = (lua_Unsigned)1 << (size*NB - 1);
+ *res = (lua_Integer)((n ^ mask) - mask); /* do sign extension */
}
- *res = n;
+ else
+ *res = (lua_Integer)n;
return 1;
}
-static int unpackint_l (lua_State *L) {
+static int undumpint_l (lua_State *L) {
lua_Integer res;
size_t len;
const char *s = luaL_checklstring(L, 1, &len);
@@ -1067,7 +1074,7 @@ static int unpackint_l (lua_State *L) {
int endian = getendian(L, 4);
luaL_argcheck(L, 1 <= pos && (size_t)pos + size - 1 <= len, 1,
"string too short");
- if(unpackint(s + pos - 1, &res, endian, size))
+ if(undumpint(s + pos - 1, &res, endian, size))
lua_pushinteger(L, res);
else
luaL_error(L, "result does not fit into a Lua integer");
@@ -1075,9 +1082,9 @@ static int unpackint_l (lua_State *L) {
}
-static void correctendianess (lua_State *L, char *b, int size, int endianarg) {
+static void correctendianness (lua_State *L, char *b, int size, int endianarg) {
int endian = getendian(L, endianarg);
- if (endian != nativeendian.little) { /* not native endianess? */
+ if (endian != nativeendian.little) { /* not native endianness? */
int i = 0;
while (i < --size) {
char temp = b[i];
@@ -1097,7 +1104,7 @@ static int getfloatsize (lua_State *L, int arg) {
}
-static int packfloat_l (lua_State *L) {
+static int dumpfloat_l (lua_State *L) {
float f; double d;
char *pn; /* pointer to number */
lua_Number n = luaL_checknumber(L, 1);
@@ -1113,13 +1120,13 @@ static int packfloat_l (lua_State *L) {
d = (double)n;
pn = (char*)&d;
}
- correctendianess(L, pn, size, 3);
+ correctendianness(L, pn, size, 3);
lua_pushlstring(L, pn, size);
return 1;
}
-static int unpackfloat_l (lua_State *L) {
+static int undumpfloat_l (lua_State *L) {
lua_Number res;
size_t len;
const char *s = luaL_checklstring(L, 1, &len);
@@ -1129,19 +1136,19 @@ static int unpackfloat_l (lua_State *L) {
"string too short");
if (size == sizeof(lua_Number)) {
memcpy(&res, s + pos - 1, size);
- correctendianess(L, (char*)&res, size, 4);
+ correctendianness(L, (char*)&res, size, 4);
}
else if (size == sizeof(float)) {
float f;
memcpy(&f, s + pos - 1, size);
- correctendianess(L, (char*)&f, size, 4);
+ correctendianness(L, (char*)&f, size, 4);
res = (lua_Number)f;
}
else { /* native lua_Number may be neither float nor double */
double d;
lua_assert(size == sizeof(double));
memcpy(&d, s + pos - 1, size);
- correctendianess(L, (char*)&d, size, 4);
+ correctendianness(L, (char*)&d, size, 4);
res = (lua_Number)d;
}
lua_pushnumber(L, res);
@@ -1166,10 +1173,10 @@ static const luaL_Reg strlib[] = {
{"reverse", str_reverse},
{"sub", str_sub},
{"upper", str_upper},
- {"packfloat", packfloat_l},
- {"packint", packint_l},
- {"unpackfloat", unpackfloat_l},
- {"unpackint", unpackint_l},
+ {"dumpfloat", dumpfloat_l},
+ {"dumpint", dumpint_l},
+ {"undumpfloat", undumpfloat_l},
+ {"undumpint", undumpint_l},
{NULL, NULL}
};
diff --git a/src/ltable.c b/src/ltable.c
index 15432faa..a7675a57 100644
--- a/src/ltable.c
+++ b/src/ltable.c
@@ -1,5 +1,5 @@
/*
-** $Id: ltable.c,v 2.84 2014/01/27 13:34:32 roberto Exp $
+** $Id: ltable.c,v 2.90 2014/06/18 22:59:29 roberto Exp $
** Lua tables (hash)
** See Copyright Notice in lua.h
*/
@@ -21,6 +21,7 @@
#include <float.h>
#include <math.h>
#include <string.h>
+#include <limits.h>
#define ltable_c
#define LUA_CORE
@@ -39,14 +40,13 @@
/*
-** max size of array part is 2^MAXBITS
+** Maximum size of array part (MAXASIZE) is 2^MAXBITS. (SIZEINT is the
+** minimum between size of int and size of LUA_INTEGER; array indices
+** are limited by both types.)
*/
-#if LUAI_BITSINT >= 32
-#define MAXBITS 30
-#else
-#define MAXBITS (LUAI_BITSINT-2)
-#endif
-
+#define SIZEINT \
+ (sizeof(int) < sizeof(LUA_INTEGER) ? sizeof(int) : sizeof(LUA_INTEGER))
+#define MAXBITS cast_int(SIZEINT * CHAR_BIT - 2)
#define MAXASIZE (1 << MAXBITS)
@@ -67,12 +67,6 @@
#define hashpointer(t,p) hashmod(t, IntPoint(p))
-/* checks whether a float has a value representable as a lua_Integer
- (and does the conversion if so) */
-#define numisinteger(x,i) \
- (((x) == l_floor(x)) && luaV_numtointeger(x, i))
-
-
#define dummynode (&dummynode_)
#define isdummy(n) ((n) == dummynode)
@@ -84,6 +78,17 @@ static const Node dummynode_ = {
/*
+** Checks whether a float has a value representable as a lua_Integer
+** (and does the conversion if so)
+*/
+static int numisinteger (lua_Number x, lua_Integer *p) {
+ if ((x) == l_floor(x)) /* integral value? */
+ return lua_numtointeger(x, p); /* try as an integer */
+ else return 0;
+}
+
+
+/*
** hash for floating-point numbers
*/
static Node *hashfloat (const Table *t, lua_Number n) {
@@ -378,7 +383,8 @@ static void rehash (lua_State *L, Table *t, const TValue *ek) {
Table *luaH_new (lua_State *L) {
- Table *t = &luaC_newobj(L, LUA_TTABLE, sizeof(Table))->h;
+ GCObject *o = luaC_newobj(L, LUA_TTABLE, sizeof(Table));
+ Table *t = gco2t(o);
t->metatable = NULL;
t->flags = cast_byte(~0);
t->array = NULL;
@@ -424,7 +430,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
if (luai_numisnan(n))
luaG_runerror(L, "table index is NaN");
if (numisinteger(n, &k)) { /* index is int? */
- setivalue(&aux, k);
+ setivalue(&aux, k);
key = &aux; /* insert it as an integer */
}
}
@@ -443,10 +449,10 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
/* yes; move colliding node into free position */
while (othern + gnext(othern) != mp) /* find previous */
othern += gnext(othern);
- gnext(othern) = f - othern; /* re-chain with 'f' in place of 'mp' */
+ gnext(othern) = cast_int(f - othern); /* rechain to point to 'f' */
*f = *mp; /* copy colliding node into free pos. (mp->next also goes) */
if (gnext(mp) != 0) {
- gnext(f) += mp - f; /* correct 'next' */
+ gnext(f) += cast_int(mp - f); /* correct 'next' */
gnext(mp) = 0; /* now 'mp' is free */
}
setnilvalue(gval(mp));
@@ -454,9 +460,9 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
else { /* colliding node is in its own main position */
/* new node will go into free position */
if (gnext(mp) != 0)
- gnext(f) = (mp + gnext(mp)) - f; /* chain new position */
+ gnext(f) = cast_int((mp + gnext(mp)) - f); /* chain new position */
else lua_assert(gnext(f) == 0);
- gnext(mp) = f - mp;
+ gnext(mp) = cast_int(f - mp);
mp = f;
}
}
@@ -472,7 +478,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
*/
const TValue *luaH_getint (Table *t, lua_Integer key) {
/* (1 <= key && key <= t->sizearray) */
- if (cast_unsigned(key - 1) < cast_unsigned(t->sizearray))
+ if (l_castS2U(key - 1) < cast(unsigned int, t->sizearray))
return &t->array[key - 1];
else {
Node *n = hashint(t, key);
diff --git a/src/ltablib.c b/src/ltablib.c
index a2801a29..ab0d21e7 100644
--- a/src/ltablib.c
+++ b/src/ltablib.c
@@ -1,10 +1,11 @@
/*
-** $Id: ltablib.c,v 1.66 2014/03/21 13:52:33 roberto Exp $
+** $Id: ltablib.c,v 1.70 2014/05/16 18:53:25 roberto Exp $
** Library for Table Manipulation
** See Copyright Notice in lua.h
*/
+#include <limits.h>
#include <stddef.h>
#define ltablib_c
@@ -39,16 +40,16 @@ static int maxn (lua_State *L) {
static int tinsert (lua_State *L) {
- int e = aux_getn(L, 1) + 1; /* first empty element */
- int pos; /* where to insert new element */
+ lua_Integer e = aux_getn(L, 1) + 1; /* first empty element */
+ lua_Integer pos; /* where to insert new element */
switch (lua_gettop(L)) {
case 2: { /* called with only 2 arguments */
pos = e; /* insert new element at the end */
break;
}
case 3: {
- int i;
- pos = luaL_checkint(L, 2); /* 2nd argument is the position */
+ lua_Integer i;
+ pos = luaL_checkinteger(L, 2); /* 2nd argument is the position */
luaL_argcheck(L, 1 <= pos && pos <= e, 2, "position out of bounds");
for (i = e; i > pos; i--) { /* move up elements */
lua_rawgeti(L, 1, i-1);
@@ -66,8 +67,8 @@ static int tinsert (lua_State *L) {
static int tremove (lua_State *L) {
- int size = aux_getn(L, 1);
- int pos = luaL_optint(L, 2, size);
+ lua_Integer size = aux_getn(L, 1);
+ lua_Integer pos = luaL_optinteger(L, 2, size);
if (pos != size) /* validate 'pos' if given */
luaL_argcheck(L, 1 <= pos && pos <= size + 1, 1, "position out of bounds");
lua_rawgeti(L, 1, pos); /* result = t[pos] */
@@ -81,7 +82,7 @@ static int tremove (lua_State *L) {
}
-static void addfield (lua_State *L, luaL_Buffer *b, int i) {
+static void addfield (lua_State *L, luaL_Buffer *b, lua_Integer i) {
lua_rawgeti(L, 1, i);
if (!lua_isstring(L, -1))
luaL_error(L, "invalid value (%s) at index %d in table for "
@@ -93,11 +94,11 @@ static void addfield (lua_State *L, luaL_Buffer *b, int i) {
static int tconcat (lua_State *L) {
luaL_Buffer b;
size_t lsep;
- int i, last;
+ lua_Integer i, last;
const char *sep = luaL_optlstring(L, 2, "", &lsep);
luaL_checktype(L, 1, LUA_TTABLE);
- i = luaL_optint(L, 3, 1);
- last = luaL_opt(L, luaL_checkint, 4, luaL_len(L, 1));
+ i = luaL_optinteger(L, 3, 1);
+ last = luaL_opt(L, luaL_checkinteger, 4, luaL_len(L, 1));
luaL_buffinit(L, &b);
for (; i < last; i++) {
addfield(L, &b, i);
@@ -117,34 +118,32 @@ static int tconcat (lua_State *L) {
*/
static int pack (lua_State *L) {
+ int i;
int n = lua_gettop(L); /* number of elements to pack */
lua_createtable(L, n, 1); /* create result table */
+ lua_insert(L, 1); /* put it at index 1 */
+ for (i = n; i >= 1; i--) /* assign elements */
+ lua_rawseti(L, 1, i);
lua_pushinteger(L, n);
- lua_setfield(L, -2, "n"); /* t.n = number of elements */
- if (n > 0) { /* at least one element? */
- int i;
- lua_pushvalue(L, 1);
- lua_rawseti(L, -2, 1); /* insert first element */
- lua_replace(L, 1); /* move table into index 1 */
- for (i = n; i >= 2; i--) /* assign other elements */
- lua_rawseti(L, 1, i);
- }
+ lua_setfield(L, 1, "n"); /* t.n = number of elements */
return 1; /* return table */
}
static int unpack (lua_State *L) {
- int i, e, n;
+ lua_Integer i, e;
+ lua_Unsigned n;
luaL_checktype(L, 1, LUA_TTABLE);
- i = luaL_optint(L, 2, 1);
- e = luaL_opt(L, luaL_checkint, 3, luaL_len(L, 1));
+ i = luaL_optinteger(L, 2, 1);
+ e = luaL_opt(L, luaL_checkinteger, 3, luaL_len(L, 1));
if (i > e) return 0; /* empty range */
- n = e - i + 1; /* number of elements */
- if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arithmetic overflow */
+ n = (lua_Unsigned)e - i; /* number of elements minus 1 (avoid overflows) */
+ if (n >= (unsigned int)INT_MAX || !lua_checkstack(L, ++n))
return luaL_error(L, "too many results to unpack");
- lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */
- while (i++ < e) /* push arg[i + 1...e] */
- lua_rawgeti(L, 1, i);
+ do { /* must have at least one element */
+ lua_rawgeti(L, 1, i); /* push arg[i..e] */
+ } while (i++ < e);
+
return n;
}
diff --git a/src/ltm.c b/src/ltm.c
index 84ae10d9..996a73e8 100644
--- a/src/ltm.c
+++ b/src/ltm.c
@@ -1,5 +1,5 @@
/*
-** $Id: ltm.c,v 2.25 2013/12/30 20:47:58 roberto Exp $
+** $Id: ltm.c,v 2.27 2014/06/10 18:53:18 roberto Exp $
** Tag methods
** See Copyright Notice in lua.h
*/
@@ -116,10 +116,12 @@ void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2,
case TM_CONCAT:
luaG_concaterror(L, p1, p2);
case TM_IDIV: case TM_BAND: case TM_BOR: case TM_BXOR:
- case TM_SHL: case TM_SHR: case TM_BNOT:
- if (ttisnumber(p1) && ttisnumber(p2))
+ case TM_SHL: case TM_SHR: case TM_BNOT: {
+ lua_Number dummy;
+ if (tonumber(p1, &dummy) && tonumber(p2, &dummy))
luaG_tointerror(L, p1, p2);
/* else go through */
+ }
default:
luaG_aritherror(L, p1, p2);
}
@@ -127,19 +129,6 @@ void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2,
}
-const TValue *luaT_getequalTM (lua_State *L, Table *mt1, Table *mt2) {
- const TValue *tm1 = fasttm(L, mt1, TM_EQ);
- const TValue *tm2;
- if (tm1 == NULL) return NULL; /* no metamethod */
- if (mt1 == mt2) return tm1; /* same metatables => same metamethods */
- tm2 = fasttm(L, mt2, TM_EQ);
- if (tm2 == NULL) return NULL; /* no metamethod */
- if (luaV_rawequalobj(tm1, tm2)) /* same metamethods? */
- return tm1;
- return NULL;
-}
-
-
int luaT_callorderTM (lua_State *L, const TValue *p1, const TValue *p2,
TMS event) {
if (!luaT_callbinTM(L, p1, p2, L->top, event))
diff --git a/src/ltm.h b/src/ltm.h
index a84c798e..1fd756ae 100644
--- a/src/ltm.h
+++ b/src/ltm.h
@@ -1,5 +1,5 @@
/*
-** $Id: ltm.h,v 2.19 2013/12/30 20:47:58 roberto Exp $
+** $Id: ltm.h,v 2.20 2014/06/10 18:53:18 roberto Exp $
** Tag methods
** See Copyright Notice in lua.h
*/
@@ -67,7 +67,6 @@ LUAI_FUNC int luaT_callbinTM (lua_State *L, const TValue *p1, const TValue *p2,
StkId res, TMS event);
LUAI_FUNC void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2,
StkId res, TMS event);
-LUAI_FUNC const TValue *luaT_getequalTM (lua_State *L, Table *mt1, Table *mt2);
LUAI_FUNC int luaT_callorderTM (lua_State *L, const TValue *p1,
const TValue *p2, TMS event);
diff --git a/src/lua.c b/src/lua.c
index 7a711113..0657b220 100644
--- a/src/lua.c
+++ b/src/lua.c
@@ -1,5 +1,5 @@
/*
-** $Id: lua.c,v 1.210 2014/02/26 15:27:56 roberto Exp $
+** $Id: lua.c,v 1.211 2014/06/05 20:42:06 roberto Exp $
** Lua stand-alone interpreter
** See Copyright Notice in lua.h
*/
@@ -103,17 +103,24 @@ static lua_State *globalL = NULL;
static const char *progname = LUA_PROGNAME;
-
+/*
+** Hook set by signal function to stop the interpreter.
+*/
static void lstop (lua_State *L, lua_Debug *ar) {
(void)ar; /* unused arg. */
- lua_sethook(L, NULL, 0, 0);
+ lua_sethook(L, NULL, 0, 0); /* reset hook */
luaL_error(L, "interrupted!");
}
+/*
+** Function to be called at a C signal. Because a C signal cannot
+** just change a Lua state (as there is no proper syncronization),
+** this function only sets a hook that, when called, will stop the
+** interpreter.
+*/
static void laction (int i) {
- signal(i, SIG_DFL); /* if another SIGINT happens before lstop,
- terminate process (default action) */
+ signal(i, SIG_DFL); /* if another SIGINT happens, terminate process */
lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
}
@@ -139,27 +146,23 @@ static void print_usage (const char *badoption) {
}
+/*
+** Prints an error message, adding the program name in front of it
+** (if present)
+*/
static void l_message (const char *pname, const char *msg) {
if (pname) luai_writestringerror("%s: ", pname);
luai_writestringerror("%s\n", msg);
}
+/*
+** Check whether 'status' is not OK and, if so, prints the error
+** message on the top of the stack. Because this function can be called
+** unprotected, it only accepts actual strings as error messages. (A
+** coercion could raise a memory error.)
+*/
static int report (lua_State *L, int status) {
- if (status != LUA_OK && !lua_isnil(L, -1)) {
- const char *msg = lua_tostring(L, -1);
- if (msg == NULL) msg = "(error object is not a string)";
- l_message(progname, msg);
- lua_pop(L, 1);
- /* force a complete garbage collection in case of errors */
- lua_gc(L, LUA_GCCOLLECT, 0);
- }
- return status;
-}
-
-
-/* the next function is called unprotected, so it must avoid errors */
-static void finalreport (lua_State *L, int status) {
if (status != LUA_OK) {
const char *msg = (lua_type(L, -1) == LUA_TSTRING) ? lua_tostring(L, -1)
: NULL;
@@ -167,31 +170,39 @@ static void finalreport (lua_State *L, int status) {
l_message(progname, msg);
lua_pop(L, 1);
}
+ return status;
}
-static int traceback (lua_State *L) {
+/*
+** Message handler to be used to run all chunks
+*/
+static int msghandler (lua_State *L) {
const char *msg = lua_tostring(L, 1);
- if (msg)
- luaL_traceback(L, L, msg, 1);
- else if (!lua_isnoneornil(L, 1)) { /* is there an error object? */
+ if (msg) /* is error object a string? */
+ luaL_traceback(L, L, msg, 1); /* use standard traceback */
+ else if (!lua_isnoneornil(L, 1)) { /* non-string error object? */
if (!luaL_callmeta(L, 1, "__tostring")) /* try its 'tostring' metamethod */
lua_pushliteral(L, "(no error message)");
- }
+ } /* else no error object, does nothing */
return 1;
}
+/*
+** Interface to 'lua_pcall', which sets appropriate message function
+** and C-signal handler. Used to run all chunks.
+*/
static int docall (lua_State *L, int narg, int nres) {
int status;
int base = lua_gettop(L) - narg; /* function index */
- lua_pushcfunction(L, traceback); /* push traceback function */
- lua_insert(L, base); /* put it under chunk and args */
+ lua_pushcfunction(L, msghandler); /* push message handler */
+ lua_insert(L, base); /* put it under function and args */
globalL = L; /* to be available to 'laction' */
- signal(SIGINT, laction);
+ signal(SIGINT, laction); /* set C-signal handler */
status = lua_pcall(L, narg, nres, base);
- signal(SIGINT, SIG_DFL);
- lua_remove(L, base); /* remove traceback function */
+ signal(SIGINT, SIG_DFL); /* reset C-signal handler */
+ lua_remove(L, base); /* remove message handler from the stack */
return status;
}
@@ -202,38 +213,47 @@ static void print_version (void) {
}
-static int getargs (lua_State *L, char **argv, int n) {
- int narg;
- int i;
- int argc = 0;
- while (argv[argc]) argc++; /* count total number of arguments */
- narg = argc - (n + 1); /* number of arguments to the script */
- luaL_checkstack(L, narg + 3, "too many arguments to script");
- for (i=n+1; i < argc; i++)
- lua_pushstring(L, argv[i]);
- lua_createtable(L, narg, n + 1);
- for (i=0; i < argc; i++) {
+/*
+** Create the 'arg' table, which stores all arguments from the
+** command line ('argv'). It should be aligned so that, at index 0,
+** it has 'argv[script]', which is the script name. The arguments
+** to the script (everything after 'script') go to positive indices;
+** other arguments (before the script name) go to negative indices.
+** If there is no script name, assume interpreter's name as base.
+*/
+static void createargtable (lua_State *L, char **argv, int argc, int script) {
+ int i, narg;
+ if (script == argc) script = 0; /* no script name? */
+ narg = argc - (script + 1); /* number of positive indices */
+ lua_createtable(L, narg, script + 1);
+ for (i = 0; i < argc; i++) {
lua_pushstring(L, argv[i]);
- lua_rawseti(L, -2, i - n);
+ lua_rawseti(L, -2, i - script);
}
- return narg;
+ lua_setglobal(L, "arg");
}
-static int dofile (lua_State *L, const char *name) {
- int status = luaL_loadfile(L, name);
+static int dochunk (lua_State *L, int status) {
if (status == LUA_OK) status = docall(L, 0, 0);
return report(L, status);
}
+static int dofile (lua_State *L, const char *name) {
+ return dochunk(L, luaL_loadfile(L, name));
+}
+
+
static int dostring (lua_State *L, const char *s, const char *name) {
- int status = luaL_loadbuffer(L, s, strlen(s), name);
- if (status == LUA_OK) status = docall(L, 0, 0);
- return report(L, status);
+ return dochunk(L, luaL_loadbuffer(L, s, strlen(s), name));
}
+/*
+** Calls 'require(name)' and stores the result in a global variable
+** with the given name.
+*/
static int dolibrary (lua_State *L, const char *name) {
int status;
lua_getglobal(L, "require");
@@ -245,6 +265,9 @@ static int dolibrary (lua_State *L, const char *name) {
}
+/*
+** Returns the string to be used as a prompt by the interpreter.
+*/
static const char *get_prompt (lua_State *L, int firstline) {
const char *p;
lua_getglobal(L, firstline ? "_PROMPT" : "_PROMPT2");
@@ -257,6 +280,12 @@ static const char *get_prompt (lua_State *L, int firstline) {
#define EOFMARK "<eof>"
#define marklen (sizeof(EOFMARK)/sizeof(char) - 1)
+
+/*
+** Check whether 'status' signals a syntax error and the error
+** message at the top of the stack ends with the above mark for
+** incoplete statements.
+*/
static int incomplete (lua_State *L, int status) {
if (status == LUA_ERRSYNTAX) {
size_t lmsg;
@@ -270,7 +299,9 @@ static int incomplete (lua_State *L, int status) {
}
-/* prompt the user, read a line, and push it into the Lua stack */
+/*
+** Prompt the user, read a line, and push it into the Lua stack.
+*/
static int pushline (lua_State *L, int firstline) {
char buffer[LUA_MAXINPUT];
char *b = buffer;
@@ -292,8 +323,10 @@ static int pushline (lua_State *L, int firstline) {
}
-/* try to compile line on the stack as 'return <line>'; on return, stack
- has either compiled chunk or original line (if compilation failed) */
+/*
+** Try to compile line on the stack as 'return <line>'; on return, stack
+** has either compiled chunk or original line (if compilation failed).
+*/
static int addreturn (lua_State *L) {
int status;
size_t len; const char *line;
@@ -309,14 +342,16 @@ static int addreturn (lua_State *L) {
}
-/* read multiple lines until a complete line */
+/*
+** Read multiple lines until a complete Lua statement
+*/
static int multiline (lua_State *L) {
- for (;;) { /* repeat until gets a complete line */
+ for (;;) { /* repeat until gets a complete statement */
size_t len;
const char *line = lua_tolstring(L, 1, &len); /* get what it has */
int status = luaL_loadbuffer(L, line, len, "=stdin"); /* try it */
if (!incomplete(L, status) || !pushline(L, 0))
- return status; /* cannot/should not try to add continuation line */
+ return status; /* cannot or should not try to add continuation line */
lua_pushliteral(L, "\n"); /* add newline... */
lua_insert(L, -2); /* ...between the two lines */
lua_concat(L, 3); /* join them */
@@ -324,6 +359,12 @@ static int multiline (lua_State *L) {
}
+/*
+** Read a line and try to load (compile) it first as an expression (by
+** adding "return " in front of it) and second as a statement. Return
+** the final status of load/call with the resulting function (if any)
+** in the top of the stack.
+*/
static int loadline (lua_State *L) {
int status;
lua_settop(L, 0);
@@ -331,29 +372,43 @@ static int loadline (lua_State *L) {
return -1; /* no input */
if ((status = addreturn(L)) != LUA_OK) /* 'return ...' did not work? */
status = multiline(L); /* try as command, maybe with continuation lines */
- lua_saveline(L, 1);
- lua_remove(L, 1); /* remove line */
+ lua_saveline(L, 1); /* keep history */
+ lua_remove(L, 1); /* remove line from the stack */
lua_assert(lua_gettop(L) == 1);
return status;
}
-static void dotty (lua_State *L) {
+/*
+** Prints (calling the Lua 'print' function) any values on the stack
+*/
+static void l_print (lua_State *L) {
+ int n = lua_gettop(L);
+ if (n > 0) { /* any result to be printed? */
+ luaL_checkstack(L, LUA_MINSTACK, "too many results to print");
+ lua_getglobal(L, "print");
+ lua_insert(L, 1);
+ if (lua_pcall(L, n, 0, 0) != LUA_OK)
+ l_message(progname, lua_pushfstring(L,
+ "error calling " LUA_QL("print") " (%s)",
+ lua_tostring(L, -1)));
+ }
+}
+
+
+/*
+** Do the REPL: repeatedly read (load) a line, evaluate (call) it, and
+** print any results.
+*/
+static void doREPL (lua_State *L) {
int status;
const char *oldprogname = progname;
- progname = NULL;
+ progname = NULL; /* no 'progname' on errors in interactive mode */
while ((status = loadline(L)) != -1) {
- if (status == LUA_OK) status = docall(L, 0, LUA_MULTRET);
- report(L, status);
- if (status == LUA_OK && lua_gettop(L) > 0) { /* any result to print? */
- luaL_checkstack(L, LUA_MINSTACK, "too many results to print");
- lua_getglobal(L, "print");
- lua_insert(L, 1);
- if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != LUA_OK)
- l_message(progname, lua_pushfstring(L,
- "error calling " LUA_QL("print") " (%s)",
- lua_tostring(L, -1)));
- }
+ if (status == LUA_OK)
+ status = docall(L, 0, LUA_MULTRET);
+ if (status == LUA_OK) l_print(L);
+ else report(L, status);
}
lua_settop(L, 0); /* clear stack */
luai_writeline();
@@ -361,97 +416,109 @@ static void dotty (lua_State *L) {
}
+/*
+** Push on the stack 'n' strings from 'argv'
+*/
+static void pushargs (lua_State *L, char **argv, int n) {
+ int i;
+ luaL_checkstack(L, n + 3, "too many arguments to script");
+ for (i = 1; i < n; i++) /* skip 0 (the script name) */
+ lua_pushstring(L, argv[i]);
+}
+
+
static int handle_script (lua_State *L, char **argv, int n) {
int status;
- const char *fname;
- int narg = getargs(L, argv, n); /* collect arguments */
- lua_setglobal(L, "arg");
- fname = argv[n];
- if (strcmp(fname, "-") == 0 && strcmp(argv[n-1], "--") != 0)
+ const char *fname = argv[0];
+ if (strcmp(fname, "-") == 0 && strcmp(argv[-1], "--") != 0)
fname = NULL; /* stdin */
status = luaL_loadfile(L, fname);
- lua_insert(L, -(narg+1));
- if (status == LUA_OK)
- status = docall(L, narg, LUA_MULTRET);
- else
- lua_pop(L, narg);
+ if (status == LUA_OK) {
+ pushargs(L, argv, n); /* push arguments to script */
+ status = docall(L, n - 1, LUA_MULTRET);
+ }
return report(L, status);
}
-/* check that argument has no extra characters at the end */
-#define noextrachars(x) {if ((x)[2] != '\0') return -1;}
-
-
-/* indices of various argument indicators in array args */
-#define has_i 0 /* -i */
-#define has_v 1 /* -v */
-#define has_e 2 /* -e */
-#define has_E 3 /* -E */
-
-#define num_has 4 /* number of 'has_*' */
+/* bits of various argument indicators in 'args' */
+#define has_error 1 /* bad option */
+#define has_i 2 /* -i */
+#define has_v 4 /* -v */
+#define has_e 8 /* -e */
+#define has_E 16 /* -E */
-static int collectargs (char **argv, int *args) {
+/*
+** Traverses all arguments from 'argv', returning a mask with those
+** needed before running any Lua code (or an error code if it finds
+** any invalid argument). 'first' returns the first not-handled argument
+** (either the script name or a bad argument in case of error).
+*/
+static int collectargs (char **argv, int *first) {
+ int args = 0;
int i;
for (i = 1; argv[i] != NULL; i++) {
+ *first = i;
if (argv[i][0] != '-') /* not an option? */
- return i;
- switch (argv[i][1]) { /* option */
- case '-':
- noextrachars(argv[i]);
- return (argv[i+1] != NULL ? i+1 : 0);
- case '\0':
- return i;
+ return args; /* stop handling options */
+ switch (argv[i][1]) { /* else check option */
+ case '-': /* '--' */
+ if (argv[i][2] != '\0') /* extra characters after '--'? */
+ return has_error; /* invalid option */
+ *first = i + 1;
+ return args;
+ case '\0': /* '-' */
+ return args; /* script "name" is '-' */
case 'E':
- args[has_E] = 1;
+ if (argv[i][2] != '\0') /* extra characters after 1st? */
+ return has_error; /* invalid option */
+ args |= has_E;
break;
case 'i':
- noextrachars(argv[i]);
- args[has_i] = 1; /* go through */
+ args |= has_i; /* goes through (-i implies -v) */
case 'v':
- noextrachars(argv[i]);
- args[has_v] = 1;
+ if (argv[i][2] != '\0') /* extra characters after 1st? */
+ return has_error; /* invalid option */
+ args |= has_v;
break;
case 'e':
- args[has_e] = 1; /* go through */
+ args |= has_e; /* go through */
case 'l': /* both options need an argument */
if (argv[i][2] == '\0') { /* no concatenated argument? */
i++; /* try next 'argv' */
if (argv[i] == NULL || argv[i][0] == '-')
- return -(i - 1); /* no next argument or it is another option */
+ return has_error; /* no next argument or it is another option */
}
break;
- default: /* invalid option; return its index... */
- return -i; /* ...as a negative value */
+ default: /* invalid option */
+ return has_error;
}
}
- return 0;
+ *first = i; /* no script name */
+ return args;
}
+/*
+** Processes options 'e' and 'l', which involve running Lua code.
+** Returns 0 if some code raises an error.
+*/
static int runargs (lua_State *L, char **argv, int n) {
int i;
for (i = 1; i < n; i++) {
- lua_assert(argv[i][0] == '-');
- switch (argv[i][1]) { /* option */
- case 'e': {
- const char *chunk = argv[i] + 2;
- if (*chunk == '\0') chunk = argv[++i];
- lua_assert(chunk != NULL);
- if (dostring(L, chunk, "=(command line)") != LUA_OK)
- return 0;
- break;
- }
- case 'l': {
- const char *filename = argv[i] + 2;
- if (*filename == '\0') filename = argv[++i];
- lua_assert(filename != NULL);
- if (dolibrary(L, filename) != LUA_OK)
- return 0; /* stop if file fails */
- break;
- }
- default: break;
+ int status;
+ int option = argv[i][1];
+ lua_assert(argv[i][0] == '-'); /* already checked */
+ if (option == 'e' || option == 'l') {
+ const char *extra = argv[i] + 2; /* both options need an argument */
+ if (*extra == '\0') extra = argv[++i];
+ lua_assert(extra != NULL);
+ if (option == 'e')
+ status = dostring(L, extra, "=(command line)");
+ else
+ status = dolibrary(L, extra);
+ if (status != LUA_OK) return 0;
}
}
return 1;
@@ -473,40 +540,44 @@ static int handle_luainit (lua_State *L) {
}
+/*
+** Main body of stand-alone interpreter (to be called in protected mode).
+** Reads the options and handles them all.
+*/
static int pmain (lua_State *L) {
int argc = (int)lua_tointeger(L, 1);
char **argv = (char **)lua_touserdata(L, 2);
int script;
- int args[num_has];
- args[has_i] = args[has_v] = args[has_e] = args[has_E] = 0;
+ int args = collectargs(argv, &script);
+ luaL_checkversion(L); /* check that interpreter has correct version */
if (argv[0] && argv[0][0]) progname = argv[0];
- script = collectargs(argv, args);
- if (script < 0) { /* invalid arg? */
- print_usage(argv[-script]);
+ if (args == has_error) { /* bad arg? */
+ print_usage(argv[script]); /* 'script' has index of bad arg. */
return 0;
}
- if (args[has_v]) print_version();
- if (args[has_E]) { /* option '-E'? */
+ if (args & has_v) /* option '-v'? */
+ print_version();
+ if (args & has_E) { /* option '-E'? */
lua_pushboolean(L, 1); /* signal for libraries to ignore env. vars. */
lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");
}
- /* open standard libraries */
- luaL_checkversion(L);
- lua_gc(L, LUA_GCSTOP, 0); /* stop collector during initialization */
- luaL_openlibs(L); /* open libraries */
- lua_gc(L, LUA_GCRESTART, 0);
- if (!args[has_E] && handle_luainit(L) != LUA_OK)
- return 0; /* error running LUA_INIT */
- /* execute arguments -e and -l */
- if (!runargs(L, argv, (script > 0) ? script : argc)) return 0;
- /* execute main script (if there is one) */
- if (script && handle_script(L, argv, script) != LUA_OK) return 0;
- if (args[has_i]) /* -i option? */
- dotty(L);
- else if (script == 0 && !args[has_e] && !args[has_v]) { /* no arguments? */
- if (lua_stdin_is_tty()) {
+ luaL_openlibs(L); /* open standard libraries */
+ createargtable(L, argv, argc, script); /* create table 'arg' */
+ if (!(args & has_E)) { /* no option '-E'? */
+ if (handle_luainit(L) != LUA_OK) /* run LUA_INIT */
+ return 0; /* error running LUA_INIT */
+ }
+ if (!runargs(L, argv, script)) /* execute arguments -e and -l */
+ return 0; /* something failed */
+ if (script < argc && /* execute main script (if there is one) */
+ handle_script(L, argv + script, argc - script) != LUA_OK)
+ return 0;
+ if (args & has_i) /* -i option? */
+ doREPL(L); /* do read-eval-print loop */
+ else if (script == argc && !(args & (has_e | has_v))) { /* no arguments? */
+ if (lua_stdin_is_tty()) { /* running in interactive mode? */
print_version();
- dotty(L);
+ doREPL(L); /* do read-eval-print loop */
}
else dofile(L, NULL); /* executes stdin as a file */
}
@@ -522,13 +593,12 @@ int main (int argc, char **argv) {
l_message(argv[0], "cannot create state: not enough memory");
return EXIT_FAILURE;
}
- /* call 'pmain' in protected mode */
- lua_pushcfunction(L, &pmain);
+ lua_pushcfunction(L, &pmain); /* to call 'pmain' in protected mode */
lua_pushinteger(L, argc); /* 1st argument */
lua_pushlightuserdata(L, argv); /* 2nd argument */
- status = lua_pcall(L, 2, 1, 0);
+ status = lua_pcall(L, 2, 1, 0); /* do the call */
result = lua_toboolean(L, -1); /* get result */
- finalreport(L, status);
+ report(L, status);
lua_close(L);
return (result && status == LUA_OK) ? EXIT_SUCCESS : EXIT_FAILURE;
}
diff --git a/src/lua.h b/src/lua.h
index 5d1a1755..0b76dbd1 100644
--- a/src/lua.h
+++ b/src/lua.h
@@ -1,5 +1,5 @@
/*
-** $Id: lua.h,v 1.302 2014/03/20 19:42:35 roberto Exp $
+** $Id: lua.h,v 1.307 2014/06/10 17:41:38 roberto Exp $
** Lua - A Scripting Language
** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
** See Copyright Notice at the end of this file
@@ -19,7 +19,7 @@
#define LUA_VERSION_MAJOR "5"
#define LUA_VERSION_MINOR "3"
#define LUA_VERSION_NUM 503
-#define LUA_VERSION_RELEASE "0 (work2)"
+#define LUA_VERSION_RELEASE "0 (work3)"
#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE
@@ -53,8 +53,16 @@
typedef struct lua_State lua_State;
+/*
+** Type for C functions registered with Lua
+*/
typedef int (*lua_CFunction) (lua_State *L);
+/*
+** Type for continuation functions
+*/
+typedef int (*lua_KFunction) (lua_State *L, int status, int ctx);
+
/*
** functions that read/write blocks when loading/dumping Lua chunks
@@ -145,8 +153,7 @@ LUA_API int (lua_absindex) (lua_State *L, int idx);
LUA_API int (lua_gettop) (lua_State *L);
LUA_API void (lua_settop) (lua_State *L, int idx);
LUA_API void (lua_pushvalue) (lua_State *L, int idx);
-LUA_API void (lua_remove) (lua_State *L, int idx);
-LUA_API void (lua_insert) (lua_State *L, int idx);
+LUA_API void (lua_rotate) (lua_State *L, int idx, int n);
LUA_API void (lua_replace) (lua_State *L, int idx);
LUA_API void (lua_copy) (lua_State *L, int fromidx, int toidx);
LUA_API int (lua_checkstack) (lua_State *L, int sz);
@@ -238,7 +245,7 @@ LUA_API int (lua_rawgetp) (lua_State *L, int idx, const void *p);
LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec);
LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz);
LUA_API int (lua_getmetatable) (lua_State *L, int objindex);
-LUA_API void (lua_getuservalue) (lua_State *L, int idx);
+LUA_API int (lua_getuservalue) (lua_State *L, int idx);
/*
@@ -258,13 +265,11 @@ LUA_API void (lua_setuservalue) (lua_State *L, int idx);
** 'load' and 'call' functions (load and run Lua code)
*/
LUA_API void (lua_callk) (lua_State *L, int nargs, int nresults, int ctx,
- lua_CFunction k);
+ lua_KFunction k);
#define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL)
-LUA_API int (lua_getctx) (lua_State *L, int *ctx);
-
LUA_API int (lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc,
- int ctx, lua_CFunction k);
+ int ctx, lua_KFunction k);
#define lua_pcall(L,n,r,f) lua_pcallk(L, (n), (r), (f), 0, NULL)
LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt,
@@ -278,10 +283,12 @@ LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data, int strip);
** coroutine functions
*/
LUA_API int (lua_yieldk) (lua_State *L, int nresults, int ctx,
- lua_CFunction k);
+ lua_KFunction k);
#define lua_yield(L,n) lua_yieldk(L, (n), 0, NULL)
LUA_API int (lua_resume) (lua_State *L, lua_State *from, int narg);
LUA_API int (lua_status) (lua_State *L);
+LUA_API int lua_isyieldable (lua_State *L);
+
/*
** garbage-collection function and options
@@ -311,7 +318,7 @@ LUA_API int (lua_next) (lua_State *L, int idx);
LUA_API void (lua_concat) (lua_State *L, int n);
LUA_API void (lua_len) (lua_State *L, int idx);
-LUA_API int (lua_strtonum) (lua_State *L, const char *s, size_t len);
+LUA_API size_t (lua_strtonum) (lua_State *L, const char *s);
LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud);
LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud);
@@ -324,9 +331,9 @@ LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud);
** ===============================================================
*/
-#define lua_tonumber(L,i) lua_tonumberx(L,i,NULL)
-#define lua_tointeger(L,i) lua_tointegerx(L,i,NULL)
-#define lua_tounsigned(L,i) lua_tounsignedx(L,i,NULL)
+#define lua_tonumber(L,i) lua_tonumberx(L,(i),NULL)
+#define lua_tointeger(L,i) lua_tointegerx(L,(i),NULL)
+#define lua_tounsigned(L,i) lua_tounsignedx(L,(i),NULL)
#define lua_pop(L,n) lua_settop(L, -(n)-1)
@@ -354,6 +361,10 @@ LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud);
#define lua_tostring(L,i) lua_tolstring(L, (i), NULL)
+#define lua_insert(L,idx) lua_rotate(L, (idx), 1)
+
+#define lua_remove(L,idx) (lua_rotate(L, (idx), -1), lua_pop(L, 1))
+
/*
** {======================================================================
diff --git a/src/luac.c b/src/luac.c
index 7a7b230f..0764b369 100644
--- a/src/luac.c
+++ b/src/luac.c
@@ -202,10 +202,8 @@ int main(int argc, char* argv[])
return EXIT_SUCCESS;
}
-#define nvalue(x) ((lua_Number)0)
-#define ttypenv(x) ttnov(x)
/*
-** $Id: print.c,v 1.69 2013/07/04 01:03:46 lhf Exp $
+** $Id: print.c,v 1.73 2014/06/12 02:41:25 lhf Exp $
** print bytecodes
** See Copyright Notice in lua.h
*/
@@ -253,7 +251,7 @@ static void PrintString(const TString* ts)
static void PrintConstant(const Proto* f, int i)
{
const TValue* o=&f->k[i];
- switch (ttypenv(o))
+ switch (ttype(o))
{
case LUA_TNIL:
printf("nil");
@@ -261,10 +259,13 @@ static void PrintConstant(const Proto* f, int i)
case LUA_TBOOLEAN:
printf(bvalue(o) ? "true" : "false");
break;
- case LUA_TNUMBER:
- printf(LUA_NUMBER_FMT,nvalue(o));
+ case LUA_TNUMFLT:
+ printf(LUA_NUMBER_FMT,fltvalue(o));
break;
- case LUA_TSTRING:
+ case LUA_TNUMINT:
+ printf(LUA_INTEGER_FMT,ivalue(o));
+ break;
+ case LUA_TSHRSTR: case LUA_TLNGSTR:
PrintString(rawtsvalue(o));
break;
default: /* cannot happen */
@@ -339,8 +340,14 @@ static void PrintCode(const Proto* f)
case OP_ADD:
case OP_SUB:
case OP_MUL:
- case OP_DIV:
case OP_POW:
+ case OP_DIV:
+ case OP_IDIV:
+ case OP_BAND:
+ case OP_BOR:
+ case OP_BXOR:
+ case OP_SHL:
+ case OP_SHR:
case OP_EQ:
case OP_LT:
case OP_LE:
diff --git a/src/luaconf.h b/src/luaconf.h
index 3d6390a2..2bceab1c 100644
--- a/src/luaconf.h
+++ b/src/luaconf.h
@@ -1,5 +1,5 @@
/*
-** $Id: luaconf.h,v 1.193 2014/03/21 14:27:16 roberto Exp $
+** $Id: luaconf.h,v 1.207 2014/06/10 19:21:20 roberto Exp $
** Configuration file for Lua
** See Copyright Notice in lua.h
*/
@@ -21,16 +21,15 @@
/*
** ===================================================================
-@@ LUA_INT_INT / LUA_INT_LONG / LUA_INT_LONGLONG defines size for
-@* Lua integers;
-@@ LUA_REAL_FLOAT / LUA_REAL_DOUBLE / LUA_REAL_LONGDOUBLE defines size for
-@* Lua floats.
+@@ LUA_INT_INT / LUA_INT_LONG / LUA_INT_LONGLONG defines type for
+@@ Lua integers;
+@@ LUA_REAL_FLOAT / LUA_REAL_DOUBLE / LUA_REAL_LONGDOUBLE defines
+@@ type for Lua floats.
**
** These definitions set the numeric types for Lua. Lua should work
-** fine with 32-bit or 64-bit integers mixed with 32-bit or 64-bit
-** floats. The usual configurations are 64-bit integers and floats (the
-** default) and 32-bit integers and floats (Small Lua, for restricted
-** hardware).
+** fine with any mix of these previous options.
+** The usual configurations are 64-bit integers and floats (the default)
+** and 32-bit integers and floats (Small Lua, for restricted hardware).
** =====================================================================
*/
#define LUA_INT_LONGLONG
@@ -74,7 +73,7 @@
/*
-@@ LUA_USE_C99 includes all functionality from C 99.
+@@ LUA_USE_C99 includes all functionality that depends on C 99.
** CHANGE it (define it) if your system is compatible.
*/
#if defined(LUA_USE_C99)
@@ -84,7 +83,7 @@
/*
@@ LUA_USE_POSIX includes all functionality listed as X/Open System
-@* Interfaces Extension (XSI).
+@@ Interfaces Extension (XSI).
** CHANGE it (define it) if your system is XSI compatible.
*/
#if defined(LUA_USE_POSIX)
@@ -94,33 +93,37 @@
/*
@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for
-@* Lua libraries.
+@@ Lua libraries.
@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for
-@* C libraries.
+@@ C libraries.
** CHANGE them if your machine has a non-conventional directory
** hierarchy or if you want to install your libraries in
** non-conventional directories.
*/
-#if defined(_WIN32) /* { */
+#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
+#if defined(_WIN32) /* { */
/*
** In Windows, any exclamation mark ('!') in the path is replaced by the
** path of the directory of the executable file of the current process.
*/
#define LUA_LDIR "!\\lua\\"
#define LUA_CDIR "!\\"
+#define LUA_SHRDIR "!\\..\\share\\lua\\" LUA_VDIR "\\"
#define LUA_PATH_DEFAULT \
LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \
LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" \
+ LUA_SHRDIR"?.lua;" LUA_SHRDIR"?\\init.lua;" \
".\\?.lua;" ".\\?\\init.lua"
#define LUA_CPATH_DEFAULT \
- LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll;" ".\\?.dll"
+ LUA_CDIR"?.dll;" \
+ LUA_CDIR"..\\lib\\lua\\" LUA_VDIR "\\?.dll;" \
+ LUA_CDIR"loadall.dll;" ".\\?.dll"
#else /* }{ */
-#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR "/"
#define LUA_ROOT "/usr/local/"
-#define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR
-#define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR
+#define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR "/"
+#define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR "/"
#define LUA_PATH_DEFAULT \
LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \
LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" \
@@ -181,10 +184,10 @@
/*
@@ LUAI_FUNC is a mark for all extern functions that are not to be
-@* exported to outside modules.
+@@ exported to outside modules.
@@ LUAI_DDEF and LUAI_DDEC are marks for all extern (const) variables
-@* that are not to be exported to outside modules (LUAI_DDEF for
-@* definitions and LUAI_DDEC for declarations).
+@@ that are not to be exported to outside modules (LUAI_DDEF for
+@@ definitions and LUAI_DDEC for declarations).
** CHANGE them if you need to mark them in some special way. Elf/gcc
** (versions 3.2 and later) mark them as "hidden" to optimize access
** when Lua is compiled as a shared library. Not all elf targets support
@@ -217,7 +220,7 @@
/*
@@ LUA_IDSIZE gives the maximum size for the description of the source
-@* of a function in debug information.
+@@ of a function in debug information.
** CHANGE it if you want a different size.
*/
#define LUA_IDSIZE 60
@@ -259,17 +262,38 @@
*/
/*
-@@ LUA_COMPAT_ALL controls all compatibility options.
+@@ LUA_COMPAT_5_2 controls other macros for compatibility with Lua 5.2.
+@@ LUA_COMPAT_5_1 controls other macros for compatibility with Lua 5.1.
** You can define it to get all options, or change specific options
** to fit your specific needs.
*/
-#if defined(LUA_COMPAT_ALL) /* { */
+#if defined(LUA_COMPAT_5_2) /* { */
+
+/*
+@@ LUA_COMPAT_MATHLIB controls the presence of several deprecated
+** functions in the mathematical library.
+*/
+#define LUA_COMPAT_MATHLIB
/*
@@ LUA_COMPAT_BITLIB controls the presence of library 'bit32'.
*/
#define LUA_COMPAT_BITLIB
+
+/*
+@@ LUA_COMPAT_FLOATSTRING makes Lua format integral floats without a
+@@ a float mark ('.0').
+** This macro is not on by default even in compatibility mode,
+** because this is not really an incompatibility.
+*/
+/* #define LUA_COMPAT_FLOATSTRING */
+
+#endif /* } */
+
+
+#if defined(LUA_COMPAT_5_1) /* { */
+
/*
@@ LUA_COMPAT_UNPACK controls the presence of global 'unpack'.
** You can replace it with 'table.unpack'.
@@ -352,9 +376,9 @@
/*
@@ LUA_INT32 is an signed integer with exactly 32 bits.
@@ LUAI_UMEM is an unsigned integer big enough to count the total
-@* memory used by Lua.
+@@ memory used by Lua.
@@ LUAI_MEM is a signed integer big enough to count the total memory
-@* used by Lua.
+@@ used by Lua.
** CHANGE here if for some weird reason the default definitions are not
** good enough for your machine. Probably you do not need to change
** this.
@@ -408,10 +432,9 @@
@@ LUA_NUMBER is the floating-point type used by Lua.
**
@@ LUAI_UACNUMBER is the result of an 'usual argument conversion'
-@* over a floating number.
+@@ over a floating number.
**
@@ LUA_NUMBER_FRMLEN is the length modifier for writing floats.
-@@ LUA_NUMBER_SCAN is the format for reading floats.
@@ LUA_NUMBER_FMT is the format for writing floats.
@@ lua_number2str converts a float to a string.
**
@@ -427,7 +450,6 @@
#define LUAI_UACNUMBER double
#define LUA_NUMBER_FRMLEN ""
-#define LUA_NUMBER_SCAN "%f"
#define LUA_NUMBER_FMT "%.7g"
#define l_mathop(op) op##f
@@ -442,7 +464,6 @@
#define LUAI_UACNUMBER long double
#define LUA_NUMBER_FRMLEN "L"
-#define LUA_NUMBER_SCAN "%Lf"
#define LUA_NUMBER_FMT "%.19Lg"
#define l_mathop(op) op##l
@@ -456,7 +477,6 @@
#define LUAI_UACNUMBER double
#define LUA_NUMBER_FRMLEN ""
-#define LUA_NUMBER_SCAN "%lf"
#define LUA_NUMBER_FMT "%.14g"
#define l_mathop(op) op
@@ -490,14 +510,29 @@
/*
+@@ lua_numtointeger converts a float number to an integer, or
+** returns 0 if float is not within the range of a lua_Integer.
+** (The range comparisons are tricky because of rounding. The tests
+** here assume a two-complement representation, where MININTEGER always
+** has an exact representation as a float; MAXINTEGER may not have one,
+** and therefore its conversion to float may have an ill-defined value.)
+*/
+#define lua_numtointeger(n,p) \
+ ((n) >= (LUA_NUMBER)(LUA_MININTEGER) && \
+ (n) < -(LUA_NUMBER)(LUA_MININTEGER) && \
+ (*(p) = (LUA_INTEGER)(n), 1))
+
+
+/*
@@ The luai_num* macros define the primitive operations over numbers.
-@* They should work for any size of floating numbers.
+** They should work for any size of floating numbers.
*/
/* the following operations need the math library */
#if defined(lobject_c) || defined(lvm_c)
#include <math.h>
-#define luai_nummod(L,a,b) ((void)L, (a) - l_floor((a)/(b))*(b))
+#define luai_nummod(L,a,b,m) \
+ { (m) = l_mathop(fmod)(a,b); if ((m) != 0 && (a)*(b) < 0) (m) += (b); }
#define luai_numpow(L,a,b) ((void)L, l_mathop(pow)(a,b))
#endif
@@ -528,44 +563,99 @@
**
@@ LUA_UNSIGNED is the unsigned version of LUA_INTEGER.
**
+@@ LUAI_UACINT is the result of an 'usual argument conversion'
+@@ over a lUA_INTEGER.
@@ LUA_INTEGER_FRMLEN is the length modifier for reading/writing integers.
-@@ LUA_INTEGER_SCAN is the format for reading integers.
@@ LUA_INTEGER_FMT is the format for writing integers.
+@@ LUA_MAXINTEGER is the maximum value for a LUA_INTEGER.
+@@ LUA_MININTEGER is the minimum value for a LUA_INTEGER.
+@@ LUA_MAXUNSIGNED is the maximum value for a LUA_UNSIGNED.
@@ lua_integer2str converts an integer to a string.
*/
+
+/* The following definitions are good for most cases here */
+
+#define LUA_INTEGER_FMT "%" LUA_INTEGER_FRMLEN "d"
+#define lua_integer2str(s,n) sprintf((s), LUA_INTEGER_FMT, (n))
+
+#define LUAI_UACINT LUA_INTEGER
+
+/*
+** use LUAI_UACINT here to avoid problems with promotions (which
+** can turn a comparison between unsigneds into a signed comparison)
+*/
+#define LUA_UNSIGNED unsigned LUAI_UACINT
+
+
+/* now the variable definitions */
+
#if defined(LUA_INT_INT) /* { int */
#define LUA_INTEGER int
#define LUA_INTEGER_FRMLEN ""
+#define LUA_MAXUNSIGNED UINT_MAX
+#define LUA_MAXINTEGER INT_MAX
+#define LUA_MININTEGER INT_MIN
+
#elif defined(LUA_INT_LONG) /* }{ long */
#define LUA_INTEGER long
#define LUA_INTEGER_FRMLEN "l"
+#define LUA_MAXUNSIGNED ULONG_MAX
+#define LUA_MAXINTEGER LONG_MAX
+#define LUA_MININTEGER LONG_MIN
+
#elif defined(LUA_INT_LONGLONG) /* }{ long long */
#if defined(_WIN32)
+
#define LUA_INTEGER __int64
#define LUA_INTEGER_FRMLEN "I64"
+
+#define LUA_MAXUNSIGNED _UI64_MAX
+#define LUA_MAXINTEGER _I64_MAX
+#define LUA_MININTEGER _I64_MIN
+
#else
+
#define LUA_INTEGER long long
#define LUA_INTEGER_FRMLEN "ll"
+
+#define LUA_MAXUNSIGNED ULLONG_MAX
+#define LUA_MAXINTEGER LLONG_MAX
+#define LUA_MININTEGER LLONG_MIN
+
#endif
-#else /* }{ */
+#elif defined(LUA_INT_SHORT) /* }{ short int */
+/*
+** this option is for tests only; it is not particularly useful and
+** it does not pass the test suit.
+*/
-#error "numeric integer type not defined"
+#define LUA_INTEGER short int
+#define LUA_INTEGER_FRMLEN ""
-#endif /* } */
+#define LUA_MAXUNSIGNED ((LUA_UNSIGNED)USHRT_MAX)
+#define LUA_MAXINTEGER SHRT_MAX
+#define LUA_MININTEGER SHRT_MIN
+#undef LUAI_UACINT
+#define LUAI_UACINT int
-#define LUA_INTEGER_SCAN "%" LUA_INTEGER_FRMLEN "d"
-#define LUA_INTEGER_FMT "%" LUA_INTEGER_FRMLEN "d"
-#define lua_integer2str(s,n) sprintf((s), LUA_INTEGER_FMT, (n))
+#undef LUAI_MAXSTACK
+#define LUAI_MAXSTACK 15000
-#define LUA_UNSIGNED unsigned LUA_INTEGER
+#define l_castS2U(x) ((LUA_UNSIGNED)(unsigned short)(x))
+
+#else /* }{ */
+
+#error "numeric integer type not defined"
+
+#endif /* } */
/* }================================================================== */
diff --git a/src/lundump.c b/src/lundump.c
index 72467e0f..0cdca1af 100644
--- a/src/lundump.c
+++ b/src/lundump.c
@@ -1,5 +1,5 @@
/*
-** $Id: lundump.c,v 2.34 2014/03/11 18:56:27 roberto Exp $
+** $Id: lundump.c,v 2.40 2014/06/19 18:27:20 roberto Exp $
** load precompiled Lua chunks
** See Copyright Notice in lua.h
*/
@@ -42,7 +42,7 @@ static l_noret error(LoadState *S, const char *why) {
/*
** All high-level loads go through LoadVector; you can change it to
-** adapt to the endianess of the input
+** adapt to the endianness of the input
*/
#define LoadVector(S,b,n) LoadBlock(S,b,(n)*sizeof((b)[0]))
@@ -105,12 +105,12 @@ static void LoadCode (LoadState *S, Proto *f) {
}
-static void LoadFunction(LoadState *S, Proto *f);
+static void LoadFunction(LoadState *S, Proto *f, TString *psource);
static void LoadConstants (LoadState *S, Proto *f) {
- int i, n;
- n = LoadInt(S);
+ int i;
+ int n = LoadInt(S);
f->k = luaM_newvector(S->L, n, TValue);
f->sizek = n;
for (i = 0; i < n; i++)
@@ -126,7 +126,7 @@ static void LoadConstants (LoadState *S, Proto *f) {
setbvalue(o, LoadByte(S));
break;
case LUA_TNUMFLT:
- setnvalue(o, LoadNumber(S));
+ setfltvalue(o, LoadNumber(S));
break;
case LUA_TNUMINT:
setivalue(o, LoadInteger(S));
@@ -139,14 +139,19 @@ static void LoadConstants (LoadState *S, Proto *f) {
lua_assert(0);
}
}
- n = LoadInt(S);
+}
+
+
+static void LoadProtos (LoadState *S, Proto *f) {
+ int i;
+ int n = LoadInt(S);
f->p = luaM_newvector(S->L, n, Proto *);
f->sizep = n;
for (i = 0; i < n; i++)
f->p[i] = NULL;
for (i = 0; i < n; i++) {
f->p[i] = luaF_newproto(S->L);
- LoadFunction(S, f->p[i]);
+ LoadFunction(S, f->p[i], f->source);
}
}
@@ -167,7 +172,6 @@ static void LoadUpvalues (LoadState *S, Proto *f) {
static void LoadDebug (LoadState *S, Proto *f) {
int i, n;
- f->source = LoadString(S);
n = LoadInt(S);
f->lineinfo = luaM_newvector(S->L, n, int);
f->sizelineinfo = n;
@@ -188,7 +192,10 @@ static void LoadDebug (LoadState *S, Proto *f) {
}
-static void LoadFunction (LoadState *S, Proto *f) {
+static void LoadFunction (LoadState *S, Proto *f, TString *psource) {
+ f->source = LoadString(S);
+ if (f->source == NULL) /* no source in dump? */
+ f->source = psource; /* reuse parent's source */
f->linedefined = LoadInt(S);
f->lastlinedefined = LoadInt(S);
f->numparams = LoadByte(S);
@@ -197,13 +204,14 @@ static void LoadFunction (LoadState *S, Proto *f) {
LoadCode(S, f);
LoadConstants(S, f);
LoadUpvalues(S, f);
+ LoadProtos(S, f);
LoadDebug(S, f);
}
static void checkliteral (LoadState *S, const char *s, const char *msg) {
char buff[sizeof(LUA_SIGNATURE) + sizeof(LUAC_DATA)]; /* larger than both */
- int len = strlen(s);
+ size_t len = strlen(s);
LoadVector(S, buff, len);
if (memcmp(s, buff, len) != 0)
error(S, msg);
@@ -231,7 +239,7 @@ static void checkHeader (LoadState *S) {
checksize(S, lua_Integer);
checksize(S, lua_Number);
if (LoadInteger(S) != LUAC_INT)
- error(S, "endianess mismatch in");
+ error(S, "endianness mismatch in");
if (LoadNumber(S) != LUAC_NUM)
error(S, "float format mismatch in");
}
@@ -240,10 +248,10 @@ static void checkHeader (LoadState *S) {
/*
** load precompiled chunk
*/
-Closure *luaU_undump(lua_State *L, ZIO *Z, Mbuffer *buff,
- const char *name) {
+LClosure *luaU_undump(lua_State *L, ZIO *Z, Mbuffer *buff,
+ const char *name) {
LoadState S;
- Closure *cl;
+ LClosure *cl;
if (*name == '@' || *name == '=')
S.name = name + 1;
else if (*name == LUA_SIGNATURE[0])
@@ -257,10 +265,10 @@ Closure *luaU_undump(lua_State *L, ZIO *Z, Mbuffer *buff,
cl = luaF_newLclosure(L, LoadByte(&S));
setclLvalue(L, L->top, cl);
incr_top(L);
- cl->l.p = luaF_newproto(L);
- LoadFunction(&S, cl->l.p);
- lua_assert(cl->l.nupvalues == cl->l.p->sizeupvalues);
- luai_verifycode(L, buff, cl->l.p);
+ cl->p = luaF_newproto(L);
+ LoadFunction(&S, cl->p, NULL);
+ lua_assert(cl->nupvalues == cl->p->sizeupvalues);
+ luai_verifycode(L, buff, cl->p);
return cl;
}
diff --git a/src/lundump.h b/src/lundump.h
index 8f64ca40..ef43d512 100644
--- a/src/lundump.h
+++ b/src/lundump.h
@@ -1,5 +1,5 @@
/*
-** $Id: lundump.h,v 1.42 2014/03/11 14:22:54 roberto Exp $
+** $Id: lundump.h,v 1.44 2014/06/19 18:27:20 roberto Exp $
** load precompiled Lua chunks
** See Copyright Notice in lua.h
*/
@@ -15,7 +15,7 @@
/* data to catch conversion errors */
#define LUAC_DATA "\x19\x93\r\n\x1a\n"
-#define LUAC_INT cast_integer(0xABCD)
+#define LUAC_INT 0x5678
#define LUAC_NUM cast_num(370.5)
#define MYINT(s) (s[0]-'0')
@@ -23,8 +23,8 @@
#define LUAC_FORMAT 0 /* this is the official format */
/* load one chunk; from lundump.c */
-LUAI_FUNC Closure* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff,
- const char* name);
+LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff,
+ const char* name);
/* dump one chunk; from ldump.c */
LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w,
diff --git a/src/lutf8lib.c b/src/lutf8lib.c
index d78a6752..747c018d 100644
--- a/src/lutf8lib.c
+++ b/src/lutf8lib.c
@@ -1,5 +1,5 @@
/*
-** $Id: lutf8lib.c,v 1.4 2014/03/20 19:36:02 roberto Exp $
+** $Id: lutf8lib.c,v 1.9 2014/05/14 18:33:37 roberto Exp $
** Standard library for UTF-8 manipulation
** See Copyright Notice in lua.h
*/
@@ -32,7 +32,7 @@ static lua_Integer u_posrelat (lua_Integer pos, size_t len) {
/*
-** Decode an UTF-8 sequence, returning NULL if byte sequence is invalid.
+** Decode one UTF-8 sequence, returning NULL if byte sequence is invalid.
*/
static const char *utf8_decode (const char *o, int *val) {
static unsigned int limits[] = {0xFF, 0x7F, 0x7FF, 0xFFFF};
@@ -61,32 +61,38 @@ static const char *utf8_decode (const char *o, int *val) {
/*
-** utf8len(s, [i]) --> number of codepoints in 's' after 'i';
-** nil if 's' not well formed
+** utf8len(s [, i [, j]]) --> number of characters that start in the
+** range [i,j], or nil + current position if 's' is not well formed in
+** that interval
*/
static int utflen (lua_State *L) {
int n = 0;
- const char *ends;
size_t len;
const char *s = luaL_checklstring(L, 1, &len);
- lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), 1);
- luaL_argcheck(L, 1 <= posi && posi <= (lua_Integer)len, 1,
+ lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len);
+ lua_Integer posj = u_posrelat(luaL_optinteger(L, 3, -1), len);
+ luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 2,
"initial position out of string");
- ends = s + len;
- s += posi - 1;
- while (s < ends && (s = utf8_decode(s, NULL)) != NULL)
+ luaL_argcheck(L, --posj < (lua_Integer)len, 3,
+ "final position out of string");
+ while (posi <= posj) {
+ const char *s1 = utf8_decode(s + posi, NULL);
+ if (s1 == NULL) { /* conversion error? */
+ lua_pushnil(L); /* return nil ... */
+ lua_pushinteger(L, posi + 1); /* ... and current position */
+ return 2;
+ }
+ posi = s1 - s;
n++;
- if (s == ends)
- lua_pushinteger(L, n);
- else
- lua_pushnil(L);
+ }
+ lua_pushinteger(L, n);
return 1;
}
/*
** codepoint(s, [i, [j]]) -> returns codepoints for all characters
-** between i and j
+** that start in the range [i,j]
*/
static int codepoint (lua_State *L) {
size_t len;
@@ -145,41 +151,46 @@ static int utfchar (lua_State *L) {
/*
-** offset(s, n, [i]) -> index where n-th character *after*
+** offset(s, n, [i]) -> index where n-th character counting from
** position 'i' starts; 0 means character at 'i'.
*/
static int byteoffset (lua_State *L) {
size_t len;
const char *s = luaL_checklstring(L, 1, &len);
int n = luaL_checkint(L, 2);
- lua_Integer posi = u_posrelat(luaL_optinteger(L, 3, 1), len) - 1;
- luaL_argcheck(L, 0 <= posi && posi <= (lua_Integer)len, 3,
+ lua_Integer posi = (n >= 0) ? 1 : len + 1;
+ posi = u_posrelat(luaL_optinteger(L, 3, posi), len);
+ luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 3,
"position out of range");
if (n == 0) {
/* find beginning of current byte sequence */
while (posi > 0 && iscont(s + posi)) posi--;
}
- else if (n < 0) {
- while (n < 0 && posi > 0) { /* move back */
- do { /* find beginning of previous character */
- posi--;
- } while (posi > 0 && iscont(s + posi));
- n++;
- }
- }
else {
- n--; /* do not move for 1st character */
- while (n > 0 && posi < (lua_Integer)len) {
- do { /* find beginning of next character */
- posi++;
- } while (iscont(s + posi)); /* ('\0' is not continuation) */
- n--;
- }
+ if (iscont(s + posi))
+ luaL_error(L, "initial position is a continuation byte");
+ if (n < 0) {
+ while (n < 0 && posi > 0) { /* move back */
+ do { /* find beginning of previous character */
+ posi--;
+ } while (posi > 0 && iscont(s + posi));
+ n++;
+ }
+ }
+ else {
+ n--; /* do not move for 1st character */
+ while (n > 0 && posi < (lua_Integer)len) {
+ do { /* find beginning of next character */
+ posi++;
+ } while (iscont(s + posi)); /* (cannot pass final '\0') */
+ n--;
+ }
+ }
}
- if (n == 0)
+ if (n == 0) /* did it find given character? */
lua_pushinteger(L, posi + 1);
- else
- lua_pushnil(L); /* no such position */
+ else /* no such character */
+ lua_pushnil(L);
return 1;
}
@@ -187,7 +198,7 @@ static int byteoffset (lua_State *L) {
static int iter_aux (lua_State *L) {
size_t len;
const char *s = luaL_checklstring(L, 1, &len);
- int n = lua_tointeger(L, 2) - 1;
+ lua_Integer n = lua_tointeger(L, 2) - 1;
if (n < 0) /* first iteration? */
n = 0; /* start from here */
else if (n < (lua_Integer)len) {
@@ -231,7 +242,7 @@ static struct luaL_Reg funcs[] = {
};
-int luaopen_utf8 (lua_State *L) {
+LUAMOD_API int luaopen_utf8 (lua_State *L) {
luaL_newlib(L, funcs);
lua_pushliteral(L, UTF8PATT);
lua_setfield(L, -2, "charpatt");
diff --git a/src/lvm.c b/src/lvm.c
index a99e26b6..125be1ef 100644
--- a/src/lvm.c
+++ b/src/lvm.c
@@ -1,5 +1,5 @@
/*
-** $Id: lvm.c,v 2.190 2014/03/15 12:29:48 roberto Exp $
+** $Id: lvm.c,v 2.216 2014/06/19 18:27:20 roberto Exp $
** Lua virtual machine
** See Copyright Notice in lua.h
*/
@@ -37,25 +37,100 @@
#define MAXNUMBER2STR 50
+/*
+** Similar to 'tonumber', but does not attempt to convert strings and
+** ensure correct precision (no extra bits). Used in comparisons.
+*/
+static int tofloat (const TValue *obj, lua_Number *n) {
+ if (ttisfloat(obj)) *n = fltvalue(obj);
+ else if (ttisinteger(obj)) {
+ volatile lua_Number x = cast_num(ivalue(obj)); /* avoid extra precision */
+ *n = x;
+ }
+ else {
+ *n = 0; /* to avoid warnings */
+ return 0;
+ }
+ return 1;
+}
+
+
+/*
+** Try to convert a value to a float. Check 'isinteger' first, because
+** in general the float case is already handled by the macro 'tonumber'.
+*/
int luaV_tonumber_ (const TValue *obj, lua_Number *n) {
- lua_assert(!ttisfloat(obj));
+ TValue v;
+ again:
if (ttisinteger(obj)) {
*n = cast_num(ivalue(obj));
return 1;
}
- else
- return (ttisstring(obj) && luaO_str2d(svalue(obj), tsvalue(obj)->len, n));
+ else if (ttisfloat(obj)) {
+ *n = fltvalue(obj);
+ return 1;
+ }
+ else if (ttisstring(obj) && /* string convertible to number? */
+ luaO_str2num(svalue(obj), &v) == tsvalue(obj)->len + 1) {
+ obj = &v;
+ goto again; /* convert result from 'luaO_str2num' to a float */
+ }
+ return 0; /* conversion failed */
+}
+
+
+/*
+** try to convert a value to an integer, rounding up if 'up' is true
+*/
+static int tointeger_aux (const TValue *obj, lua_Integer *p, int up) {
+ TValue v;
+ again:
+ if (ttisfloat(obj)) {
+ lua_Number n = fltvalue(obj);
+ n = (up ? -l_floor(-n) : l_floor(n));
+ return lua_numtointeger(n, p);
+ }
+ else if (ttisinteger(obj)) {
+ *p = ivalue(obj);
+ return 1;
+ }
+ else if (ttisstring(obj) &&
+ luaO_str2num(svalue(obj), &v) == tsvalue(obj)->len + 1) {
+ obj = &v;
+ goto again; /* convert result from 'luaO_str2num' to an integer */
+ }
+ return 0; /* conversion failed */
}
+/*
+** try to convert a non-integer value to an integer, rounding down
+*/
+int luaV_tointeger_ (const TValue *obj, lua_Integer *p) {
+ return tointeger_aux(obj, p, 0);
+}
+
+
+/*
+** Convert a number object to a string
+*/
int luaV_tostring (lua_State *L, StkId obj) {
if (!ttisnumber(obj))
return 0;
else {
char buff[MAXNUMBER2STR];
- size_t len = (ttisinteger(obj))
- ? lua_integer2str(buff, ivalue(obj))
- : lua_number2str(buff, fltvalue(obj));
+ size_t len;
+ if (ttisinteger(obj))
+ len = lua_integer2str(buff, ivalue(obj));
+ else {
+ len = lua_number2str(buff, fltvalue(obj));
+#if !defined(LUA_COMPAT_FLOATSTRING)
+ if (buff[strspn(buff, "-0123456789")] == '\0') { /* looks like an int? */
+ buff[len++] = '.';
+ buff[len++] = '0'; /* adds '.0' to result */
+ }
+#endif
+ }
setsvalue2s(L, obj, luaS_newlstr(L, buff, len));
return 1;
}
@@ -63,37 +138,46 @@ int luaV_tostring (lua_State *L, StkId obj) {
/*
-** Check whether a float number is within the range of a lua_Integer.
-** (The comparisons are tricky because of rounding, which can or
-** not occur depending on the relative sizes of floats and integers.)
-** This function should be called only when 'n' has an integral value.
+** Try to convert a 'for' limit to an integer, preserving the
+** semantics of the loop.
+** (The following explanation assumes a non-negative step; it is valid
+** for negative steps mutatis mutandis.)
+** If the limit can be converted to an integer, rounding down, that is
+** it.
+** Otherwise, check whether the limit can be converted to a number. If
+** the number is too large, it is OK to set the limit as LUA_MAXINTEGER,
+** which means no limit. If the number is too negative, the loop
+** should not run, because any initial integer value is larger than the
+** limit. So, it sets the limit to LUA_MININTEGER. 'stopnow' corrects
+** the extreme case when the initial value is LUA_MININTEGER, in which
+** case the LUA_MININTEGER limit would still run the loop once.
*/
-int luaV_numtointeger (lua_Number n, lua_Integer *p) {
- if (cast_num(MIN_INTEGER) <= n && n < (MAX_INTEGER + cast_num(1))) {
- *p = cast_integer(n);
- lua_assert(cast_num(*p) == n);
- return 1;
+static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step,
+ int *stopnow) {
+ *stopnow = 0; /* usually, let loops run */
+ if (!tointeger_aux(obj, p, (step < 0))) { /* does not fit in integer? */
+ lua_Number n; /* try to convert to float */
+ if (!tonumber(obj, &n)) /* cannot convert to float? */
+ return 0; /* not a number */
+ if (n > 0) { /* if true, float is larger than max integer */
+ *p = LUA_MAXINTEGER;
+ if (step < 0) *stopnow = 1;
+ }
+ else { /* float is smaller than min integer */
+ *p = LUA_MININTEGER;
+ if (step >= 0) *stopnow = 1;
+ }
}
- return 0; /* number is outside integer limits */
+ return 1;
}
/*
-** try to convert a non-integer value to an integer
+** Main function for table access (invoking metamethods if needed).
+** Compute 'val = t[key]'
*/
-int luaV_tointeger_ (const TValue *obj, lua_Integer *p) {
- lua_Number n;
- lua_assert(!ttisinteger(obj));
- if (tonumber(obj, &n)) {
- n = l_floor(n);
- return luaV_numtointeger(n, p);
- }
- else return 0;
-}
-
-
void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {
- int loop;
+ int loop; /* counter to avoid infinite loops */
for (loop = 0; loop < MAXTAGLOOP; loop++) {
const TValue *tm;
if (ttistable(t)) { /* `t' is a table? */
@@ -101,32 +185,36 @@ void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {
const TValue *res = luaH_get(h, key); /* do a primitive get */
if (!ttisnil(res) || /* result is not nil? */
(tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */
- setobj2s(L, val, res);
+ setobj2s(L, val, res); /* result is the raw get */
return;
}
- /* else will try the tag method */
+ /* else will try metamethod */
}
else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX)))
- luaG_typeerror(L, t, "index");
- if (ttisfunction(tm)) {
+ luaG_typeerror(L, t, "index"); /* no metamethod */
+ if (ttisfunction(tm)) { /* metamethod is a function */
luaT_callTM(L, tm, t, key, val, 1);
return;
}
- t = tm; /* else repeat with 'tm' */
+ t = tm; /* else repeat access over 'tm' */
}
luaG_runerror(L, "gettable chain too long; possible loop");
}
+/*
+** Main function for table assignment (invoking metamethods if needed).
+** Compute 't[key] = val'
+*/
void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
- int loop;
+ int loop; /* counter to avoid infinite loops */
for (loop = 0; loop < MAXTAGLOOP; loop++) {
const TValue *tm;
if (ttistable(t)) { /* `t' is a table? */
Table *h = hvalue(t);
TValue *oldval = cast(TValue *, luaH_get(h, key));
/* if previous value is not nil, there must be a previous entry
- in the table; moreover, a metamethod has no relevance */
+ in the table; a metamethod has no relevance */
if (!ttisnil(oldval) ||
/* previous value is nil; must check the metamethod */
((tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL &&
@@ -146,32 +234,40 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
else /* not a table; check metamethod */
if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))
luaG_typeerror(L, t, "index");
- /* there is a metamethod */
+ /* try the metamethod */
if (ttisfunction(tm)) {
luaT_callTM(L, tm, t, key, val, 0);
return;
}
- t = tm; /* else repeat with 'tm' */
+ t = tm; /* else repeat assginment over 'tm' */
}
luaG_runerror(L, "settable chain too long; possible loop");
}
+/*
+** Compare two strings 'ls' x 'rs', returning an integer smaller-equal-
+** -larger than zero if 'ls' is smaller-equal-larger than 'rs'.
+** The code is a little tricky because it allows '\0' in the strings
+** and it uses 'strcoll' (to respect locales) for each segments
+** of the strings.
+*/
static int l_strcmp (const TString *ls, const TString *rs) {
const char *l = getstr(ls);
size_t ll = ls->tsv.len;
const char *r = getstr(rs);
size_t lr = rs->tsv.len;
- for (;;) {
+ for (;;) { /* for each segment */
int temp = strcoll(l, r);
- if (temp != 0) return temp;
- else { /* strings are equal up to a `\0' */
+ if (temp != 0) /* not equal? */
+ return temp; /* done */
+ else { /* strings are equal up to a '\0' */
size_t len = strlen(l); /* index of first `\0' in both strings */
- if (len == lr) /* r is finished? */
- return (len == ll) ? 0 : 1;
- else if (len == ll) /* l is finished? */
- return -1; /* l is smaller than r (because r is not finished) */
- /* both strings longer than `len'; go on comparing (after the `\0') */
+ if (len == lr) /* 'rs' is finished? */
+ return (len == ll) ? 0 : 1; /* check 'ls' */
+ else if (len == ll) /* 'ls' is finished? */
+ return -1; /* 'ls' is smaller than 'rs' ('rs' is not finished) */
+ /* both strings longer than `len'; go on comparing after the '\0' */
len++;
l += len; ll -= len; r += len; lr -= len;
}
@@ -179,29 +275,35 @@ static int l_strcmp (const TString *ls, const TString *rs) {
}
+/*
+** Main operation less than; return 'l < r'.
+*/
int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
int res;
lua_Number nl, nr;
- if (ttisinteger(l) && ttisinteger(r))
+ if (ttisinteger(l) && ttisinteger(r)) /* both operands are integers? */
return (ivalue(l) < ivalue(r));
- else if (tonumber(l, &nl) && tonumber(r, &nr))
+ else if (tofloat(l, &nl) && tofloat(r, &nr)) /* both are numbers? */
return luai_numlt(nl, nr);
- else if (ttisstring(l) && ttisstring(r))
+ else if (ttisstring(l) && ttisstring(r)) /* both are strings? */
return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0;
- else if ((res = luaT_callorderTM(L, l, r, TM_LT)) < 0)
- luaG_ordererror(L, l, r);
+ else if ((res = luaT_callorderTM(L, l, r, TM_LT)) < 0) /* no metamethod? */
+ luaG_ordererror(L, l, r); /* error */
return res;
}
+/*
+** Main operation less than or equal to; return 'l <= r'.
+*/
int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) {
int res;
lua_Number nl, nr;
- if (ttisinteger(l) && ttisinteger(r))
+ if (ttisinteger(l) && ttisinteger(r)) /* both operands are integers? */
return (ivalue(l) <= ivalue(r));
- else if (tonumber(l, &nl) && tonumber(r, &nr))
+ else if (tofloat(l, &nl) && tofloat(r, &nr)) /* both are numbers? */
return luai_numle(nl, nr);
- else if (ttisstring(l) && ttisstring(r))
+ else if (ttisstring(l) && ttisstring(r)) /* both are strings? */
return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0;
else if ((res = luaT_callorderTM(L, l, r, TM_LE)) >= 0) /* first try `le' */
return res;
@@ -212,17 +314,18 @@ int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) {
/*
-** equality of Lua values. L == NULL means raw equality (no metamethods)
+** Main operation for equality of Lua values; return 't1 == t2'.
+** L == NULL means raw equality (no metamethods)
*/
int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) {
const TValue *tm;
- if (ttype(t1) != ttype(t2)) {
+ if (ttype(t1) != ttype(t2)) { /* not the same variant? */
if (ttnov(t1) != ttnov(t2) || ttnov(t1) != LUA_TNUMBER)
return 0; /* only numbers can be equal with different variants */
else { /* two numbers with different variants */
- lua_Number n1, n2;
+ lua_Number n1, n2; /* compare them as floats */
lua_assert(ttisnumber(t1) && ttisnumber(t2));
- cast_void(tonumber(t1, &n1)); cast_void(tonumber(t2, &n2));
+ cast_void(tofloat(t1, &n1)); cast_void(tofloat(t2, &n2));
return luai_numeq(n1, n2);
}
}
@@ -239,24 +342,36 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) {
case LUA_TUSERDATA: {
if (uvalue(t1) == uvalue(t2)) return 1;
else if (L == NULL) return 0;
- tm = luaT_getequalTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable);
+ tm = fasttm(L, uvalue(t1)->metatable, TM_EQ);
+ if (tm == NULL)
+ tm = fasttm(L, uvalue(t2)->metatable, TM_EQ);
break; /* will try TM */
}
case LUA_TTABLE: {
if (hvalue(t1) == hvalue(t2)) return 1;
else if (L == NULL) return 0;
- tm = luaT_getequalTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable);
+ tm = fasttm(L, hvalue(t1)->metatable, TM_EQ);
+ if (tm == NULL)
+ tm = fasttm(L, hvalue(t2)->metatable, TM_EQ);
break; /* will try TM */
}
default:
return gcvalue(t1) == gcvalue(t2);
}
- if (tm == NULL) return 0; /* no TM? */
+ if (tm == NULL) /* no TM? */
+ return 0; /* objects are different */
luaT_callTM(L, tm, t1, t2, L->top, 1); /* call TM */
return !l_isfalse(L->top);
}
+/* macro used by 'luaV_concat' to ensure that element at 'o' is a string */
+#define tostring(L,o) (ttisstring(o) || (luaV_tostring(L, o)))
+
+/*
+** Main operation for concatenation: concat 'total' values in the stack,
+** from 'L->top - total' up to 'L->top - 1'.
+*/
void luaV_concat (lua_State *L, int total) {
lua_assert(total >= 2);
do {
@@ -284,12 +399,12 @@ void luaV_concat (lua_State *L, int total) {
buffer = luaZ_openspace(L, &G(L)->buff, tl);
tl = 0;
n = i;
- do { /* concat all strings */
+ do { /* copy all strings to buffer */
size_t l = tsvalue(top-i)->len;
memcpy(buffer+tl, svalue(top-i), l * sizeof(char));
tl += l;
} while (--i > 0);
- setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl));
+ setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); /* create result */
}
total -= n-1; /* got 'n' strings to create 1 new */
L->top -= n-1; /* popped 'n' strings and pushed one */
@@ -297,6 +412,9 @@ void luaV_concat (lua_State *L, int total) {
}
+/*
+** Main operation 'ra' = #rb'.
+*/
void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) {
const TValue *tm;
switch (ttnov(rb)) {
@@ -322,15 +440,19 @@ void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) {
}
-lua_Integer luaV_div (lua_State *L, lua_Integer x, lua_Integer y) {
- if (cast_unsigned(y) + 1 <= 1U) { /* special cases: -1 or 0 */
- if (y == 0)
+/*
+** Integer division; return 'm // n'. (Assume that C division with
+** negative operands follows C99 behavior.)
+*/
+lua_Integer luaV_div (lua_State *L, lua_Integer m, lua_Integer n) {
+ if (l_castS2U(n) + 1u <= 1u) { /* special cases: -1 or 0 */
+ if (n == 0)
luaG_runerror(L, "attempt to divide by zero");
- return intop(-, 0, x); /* y==-1; avoid overflow with 0x80000...//-1 */
+ return intop(-, 0, m); /* n==-1; avoid overflow with 0x80000...//-1 */
}
else {
- lua_Integer d = x / y; /* perform division */
- if ((x ^ y) >= 0 || x % y == 0) /* same signal or no rest? */
+ lua_Integer d = m / n; /* perform division */
+ if ((m ^ n) >= 0 || m % n == 0) /* same signal or no rest? */
return d;
else
return d - 1; /* correct 'div' for negative case */
@@ -338,36 +460,22 @@ lua_Integer luaV_div (lua_State *L, lua_Integer x, lua_Integer y) {
}
-lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y) {
- if (cast_unsigned(y) + 1 <= 1U) { /* special cases: -1 or 0 */
- if (y == 0)
+/*
+** Integer modulus; return 'm % n'. (Assume that C '%' with
+** negative operands follows C99 behavior.)
+*/
+lua_Integer luaV_mod (lua_State *L, lua_Integer m, lua_Integer n) {
+ if (l_castS2U(n) + 1u <= 1u) { /* special cases: -1 or 0 */
+ if (n == 0)
luaG_runerror(L, "attempt to perform 'n%%0'");
- return 0; /* y==-1; avoid overflow with 0x80000...%-1 */
+ return 0; /* m % -1 == 0; avoid overflow with 0x80000...%-1 */
}
else {
- lua_Integer r = x % y;
- if (r == 0 || (x ^ y) >= 0)
+ lua_Integer r = m % n;
+ if (r == 0 || (m ^ n) >= 0) /* no rest or same signal? */
return r;
else
- return r + y; /* correct 'mod' for negative case */
- }
-}
-
-
-lua_Integer luaV_pow (lua_State *L, lua_Integer x, lua_Integer y) {
- if (y <= 0) { /* special cases: 0 or negative exponent */
- if (y < 0)
- luaG_runerror(L, "integer exponentiation with negative exponent");
- return 1; /* x^0 == 1 */
- }
- else {
- lua_Integer r = 1;
- for (; y > 1; y >>= 1) {
- if (y & 1) r = intop(*, r, x);
- x = intop(*, x, x);
- }
- r = intop(*, r, x);
- return r;
+ return r + n; /* correct 'mod' for negative case */
}
}
@@ -375,14 +483,17 @@ lua_Integer luaV_pow (lua_State *L, lua_Integer x, lua_Integer y) {
/* number of bits in an integer */
#define NBITS cast_int(sizeof(lua_Integer) * CHAR_BIT)
-LUAI_FUNC lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y) {
+/*
+** Shift left operation. (Shift right just negates 'y'.)
+*/
+lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y) {
if (y < 0) { /* shift right? */
if (y <= -NBITS) return 0;
- else return cast_integer(cast_unsigned(x) >> (-y));
+ else return intop(>>, x, -y);
}
else { /* shift left */
if (y >= NBITS) return 0;
- else return x << y;
+ else return intop(<<, x, y);
}
}
@@ -392,15 +503,15 @@ LUAI_FUNC lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y) {
** whether there is a cached closure with the same upvalues needed by
** new closure to be created.
*/
-static Closure *getcached (Proto *p, UpVal **encup, StkId base) {
- Closure *c = p->cache;
+static LClosure *getcached (Proto *p, UpVal **encup, StkId base) {
+ LClosure *c = p->cache;
if (c != NULL) { /* is there a cached closure? */
int nup = p->sizeupvalues;
Upvaldesc *uv = p->upvalues;
int i;
for (i = 0; i < nup; i++) { /* check whether it has right upvalues */
TValue *v = uv[i].instack ? base + uv[i].idx : encup[uv[i].idx]->v;
- if (c->l.upvals[i]->v != v)
+ if (c->upvals[i]->v != v)
return NULL; /* wrong upvalue; cannot reuse closure */
}
}
@@ -419,15 +530,15 @@ static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base,
int nup = p->sizeupvalues;
Upvaldesc *uv = p->upvalues;
int i;
- Closure *ncl = luaF_newLclosure(L, nup);
- ncl->l.p = p;
+ LClosure *ncl = luaF_newLclosure(L, nup);
+ ncl->p = p;
setclLvalue(L, ra, ncl); /* anchor new closure in stack */
for (i = 0; i < nup; i++) { /* fill in its upvalues */
if (uv[i].instack) /* upvalue refers to local variable? */
- ncl->l.upvals[i] = luaF_findupval(L, base + uv[i].idx);
+ ncl->upvals[i] = luaF_findupval(L, base + uv[i].idx);
else /* get upvalue from enclosing function */
- ncl->l.upvals[i] = encup[uv[i].idx];
- ncl->l.upvals[i]->refcount++;
+ ncl->upvals[i] = encup[uv[i].idx];
+ ncl->upvals[i]->refcount++;
/* new closure is white, so we do not need a barrier here */
}
if (!isblack(obj2gco(p))) /* cache will not break GC invariant? */
@@ -497,6 +608,14 @@ void luaV_finishOp (lua_State *L) {
+
+/*
+** {==================================================================
+** Function 'luaV_execute': main interpreter loop
+** ===================================================================
+*/
+
+
/*
** some macros for common tasks in `luaV_execute'
*/
@@ -633,7 +752,7 @@ void luaV_execute (lua_State *L) {
setivalue(ra, intop(+, ib, ic));
}
else if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
- setnvalue(ra, luai_numadd(L, nb, nc));
+ setfltvalue(ra, luai_numadd(L, nb, nc));
}
else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_ADD)); }
)
@@ -646,7 +765,7 @@ void luaV_execute (lua_State *L) {
setivalue(ra, intop(-, ib, ic));
}
else if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
- setnvalue(ra, luai_numsub(L, nb, nc));
+ setfltvalue(ra, luai_numsub(L, nb, nc));
}
else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SUB)); }
)
@@ -659,7 +778,7 @@ void luaV_execute (lua_State *L) {
setivalue(ra, intop(*, ib, ic));
}
else if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
- setnvalue(ra, luai_nummul(L, nb, nc));
+ setfltvalue(ra, luai_nummul(L, nb, nc));
}
else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_MUL)); }
)
@@ -668,7 +787,7 @@ void luaV_execute (lua_State *L) {
TValue *rc = RKC(i);
lua_Number nb; lua_Number nc;
if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
- setnvalue(ra, luai_numdiv(L, nb, nc));
+ setfltvalue(ra, luai_numdiv(L, nb, nc));
}
else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_DIV)); }
)
@@ -735,7 +854,9 @@ void luaV_execute (lua_State *L) {
setivalue(ra, luaV_mod(L, ib, ic));
}
else if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
- setnvalue(ra, luai_nummod(L, nb, nc));
+ lua_Number m;
+ luai_nummod(L, nb, nc, m);
+ setfltvalue(ra, m);
}
else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_MOD)); }
)
@@ -743,12 +864,8 @@ void luaV_execute (lua_State *L) {
TValue *rb = RKB(i);
TValue *rc = RKC(i);
lua_Number nb; lua_Number nc;
- if (ttisinteger(rb) && ttisinteger(rc)) {
- lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc);
- setivalue(ra, luaV_pow(L, ib, ic));
- }
- else if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
- setnvalue(ra, luai_numpow(L, nb, nc));
+ if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
+ setfltvalue(ra, luai_numpow(L, nb, nc));
}
else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_POW)); }
)
@@ -760,7 +877,7 @@ void luaV_execute (lua_State *L) {
setivalue(ra, intop(-, 0, ib));
}
else if (tonumber(rb, &nb)) {
- setnvalue(ra, luai_numunm(L, nb));
+ setfltvalue(ra, luai_numunm(L, nb));
}
else {
Protect(luaT_trybinTM(L, rb, rb, ra, TM_UNM));
@@ -770,7 +887,7 @@ void luaV_execute (lua_State *L) {
TValue *rb = RB(i);
lua_Integer ib;
if (tointeger(rb, &ib)) {
- setivalue(ra, intop(^, cast_integer(-1), ib));
+ setivalue(ra, intop(^, ~l_castS2U(0), ib));
}
else {
Protect(luaT_trybinTM(L, rb, rb, ra, TM_BNOT));
@@ -916,8 +1033,8 @@ void luaV_execute (lua_State *L) {
if (luai_numlt(0, step) ? luai_numle(idx, limit)
: luai_numle(limit, idx)) {
ci->u.l.savedpc += GETARG_sBx(i); /* jump back */
- setnvalue(ra, idx); /* update internal index... */
- setnvalue(ra + 3, idx); /* ...and external index */
+ setfltvalue(ra, idx); /* update internal index... */
+ setfltvalue(ra + 3, idx); /* ...and external index */
}
}
)
@@ -925,21 +1042,26 @@ void luaV_execute (lua_State *L) {
TValue *init = ra;
TValue *plimit = ra + 1;
TValue *pstep = ra + 2;
- if (ttisinteger(init) && ttisinteger(plimit) && ttisinteger(pstep)) {
+ lua_Integer ilimit;
+ int stopnow;
+ if (ttisinteger(init) && ttisinteger(pstep) &&
+ forlimit(plimit, &ilimit, ivalue(pstep), &stopnow)) {
/* all values are integer */
- setivalue(init, ivalue(init) - ivalue(pstep));
+ lua_Integer initv = (stopnow ? 0 : ivalue(init));
+ setivalue(plimit, ilimit);
+ setivalue(init, initv - ivalue(pstep));
}
else { /* try making all values floats */
lua_Number ninit; lua_Number nlimit; lua_Number nstep;
if (!tonumber(plimit, &nlimit))
luaG_runerror(L, LUA_QL("for") " limit must be a number");
- setnvalue(plimit, nlimit);
+ setfltvalue(plimit, nlimit);
if (!tonumber(pstep, &nstep))
luaG_runerror(L, LUA_QL("for") " step must be a number");
- setnvalue(pstep, nstep);
+ setfltvalue(pstep, nstep);
if (!tonumber(init, &ninit))
luaG_runerror(L, LUA_QL("for") " initial value must be a number");
- setnvalue(init, luai_numsub(L, ninit, nstep));
+ setfltvalue(init, luai_numsub(L, ninit, nstep));
}
ci->u.l.savedpc += GETARG_sBx(i);
)
@@ -987,7 +1109,7 @@ void luaV_execute (lua_State *L) {
)
vmcase(OP_CLOSURE,
Proto *p = cl->p->p[GETARG_Bx(i)];
- Closure *ncl = getcached(p, cl->upvals, base); /* cached closure */
+ LClosure *ncl = getcached(p, cl->upvals, base); /* cached closure */
if (ncl == NULL) /* no match? */
pushclosure(L, p, cl->upvals, base, ra); /* create a new one */
else
@@ -1020,3 +1142,5 @@ void luaV_execute (lua_State *L) {
}
}
+/* }================================================================== */
+
diff --git a/src/lvm.h b/src/lvm.h
index 20e24b32..36e78e68 100644
--- a/src/lvm.h
+++ b/src/lvm.h
@@ -1,5 +1,5 @@
/*
-** $Id: lvm.h,v 2.25 2013/12/30 20:47:58 roberto Exp $
+** $Id: lvm.h,v 2.31 2014/05/26 17:10:22 roberto Exp $
** Lua virtual machine
** See Copyright Notice in lua.h
*/
@@ -13,16 +13,13 @@
#include "ltm.h"
-#define tostring(L,o) (ttisstring(o) || (luaV_tostring(L, o)))
-
#define tonumber(o,n) \
(ttisfloat(o) ? (*(n) = fltvalue(o), 1) : luaV_tonumber_(o,n))
#define tointeger(o,i) \
(ttisinteger(o) ? (*(i) = ivalue(o), 1) : luaV_tointeger_(o,i))
-#define intop(op,v1,v2) \
- cast_integer(cast_unsigned(v1) op cast_unsigned(v2))
+#define intop(op,v1,v2) l_castU2S(l_castS2U(v1) op l_castS2U(v2))
#define luaV_rawequalobj(t1,t2) luaV_equalobj(NULL,t1,t2)
@@ -32,7 +29,6 @@ LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r);
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_tointeger_ (const TValue *obj, lua_Integer *p);
-LUAI_FUNC int luaV_numtointeger (lua_Number n, lua_Integer *p);
LUAI_FUNC int luaV_tostring (lua_State *L, StkId obj);
LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key,
StkId val);
@@ -43,7 +39,6 @@ LUAI_FUNC void luaV_execute (lua_State *L);
LUAI_FUNC void luaV_concat (lua_State *L, int total);
LUAI_FUNC lua_Integer luaV_div (lua_State *L, lua_Integer x, lua_Integer y);
LUAI_FUNC lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y);
-LUAI_FUNC lua_Integer luaV_pow (lua_State *L, lua_Integer x, lua_Integer y);
LUAI_FUNC lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y);
LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb);