summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--README2
-rw-r--r--doc/contents.html12
-rw-r--r--doc/manual.html353
-rw-r--r--doc/readme.html16
-rw-r--r--src/.fix2
-rw-r--r--src/Makefile9
-rw-r--r--src/lapi.c141
-rw-r--r--src/lauxlib.c47
-rw-r--r--src/lauxlib.h14
-rw-r--r--src/lbaselib.c71
-rw-r--r--src/lbitlib.c18
-rw-r--r--src/lcode.c126
-rw-r--r--src/lcode.h6
-rw-r--r--src/ldblib.c15
-rw-r--r--src/ldebug.c70
-rw-r--r--src/ldebug.h9
-rw-r--r--src/ldo.c15
-rw-r--r--src/ldump.c20
-rw-r--r--src/lgc.c13
-rw-r--r--src/liolib.c45
-rw-r--r--src/llex.c57
-rw-r--r--src/llex.h8
-rw-r--r--src/llimits.h113
-rw-r--r--src/lmathlib.c56
-rw-r--r--src/lobject.c161
-rw-r--r--src/lobject.h143
-rw-r--r--src/lopcodes.c4
-rw-r--r--src/lopcodes.h3
-rw-r--r--src/loslib.c10
-rw-r--r--src/lparser.c19
-rw-r--r--src/lparser.h8
-rw-r--r--src/lstring.c6
-rw-r--r--src/lstrlib.c109
-rw-r--r--src/ltable.c83
-rw-r--r--src/ltable.h7
-rw-r--r--src/ltm.c74
-rw-r--r--src/ltm.h17
-rw-r--r--src/lua.h24
-rw-r--r--src/luac.c6
-rw-r--r--src/luaconf.h200
-rw-r--r--src/lundump.c16
-rw-r--r--src/lvm.c418
-rw-r--r--src/lvm.h25
-rw-r--r--src/lzio.h6
45 files changed, 1549 insertions, 1032 deletions
diff --git a/Makefile b/Makefile
index bd9515fd..e8092654 100644
--- a/Makefile
+++ b/Makefile
@@ -45,8 +45,8 @@ TO_LIB= liblua.a
TO_MAN= lua.1 luac.1
# Lua version and release.
-V= 5.2
-R= $V.1
+V= 5.3
+R= $V.0
# Targets start here.
all: $(PLAT)
diff --git a/README b/README
index 6e2aee6c..70ec4137 100644
--- a/README
+++ b/README
@@ -1,5 +1,5 @@
-This is Lua 5.2.2, released on 21 Mar 2013.
+This is Lua 5.3.0 (work1), released on 5 Jul 2013.
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 0ce297da..fb115939 100644
--- a/doc/contents.html
+++ b/doc/contents.html
@@ -1,7 +1,7 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML>
<HEAD>
-<TITLE>Lua 5.2 Reference Manual - contents</TITLE>
+<TITLE>Lua 5.3 Reference Manual - contents</TITLE>
<LINK REL="stylesheet" TYPE="text/css" HREF="lua.css">
<META HTTP-EQUIV="content-type" CONTENT="text/html; charset=iso-8859-1">
<STYLE TYPE="text/css">
@@ -17,7 +17,7 @@ ul {
<HR>
<H1>
<A HREF="http://www.lua.org/"><IMG SRC="logo.gif" ALT="" BORDER=0></A>
-Lua 5.2 Reference Manual
+Lua 5.3 Reference Manual
</H1>
<P>
@@ -73,7 +73,7 @@ Freely available under the terms of the
<LI><A HREF="manual.html#3.4">3.4 &ndash; Expressions</A>
<UL>
<LI><A HREF="manual.html#3.4.1">3.4.1 &ndash; Arithmetic Operators</A>
-<LI><A HREF="manual.html#3.4.2">3.4.2 &ndash; Coercion</A>
+<LI><A HREF="manual.html#3.4.2">3.4.2 &ndash; Coercions and Conversions</A>
<LI><A HREF="manual.html#3.4.3">3.4.3 &ndash; Relational Operators</A>
<LI><A HREF="manual.html#3.4.4">3.4.4 &ndash; Logical Operators</A>
<LI><A HREF="manual.html#3.4.5">3.4.5 &ndash; Concatenation</A>
@@ -250,6 +250,8 @@ Freely available under the terms of the
<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>
@@ -523,10 +525,10 @@ Freely available under the terms of the
<HR>
<SMALL CLASS="footer">
Last update:
-Tue Mar 12 11:22:18 BRT 2013
+Fri Jul 5 23:06:54 BRT 2013
</SMALL>
<!--
-Last change: revised for Lua 5.2.2
+Last change: updated for Lua 5.3.0 (work1)
-->
</BODY>
diff --git a/doc/manual.html b/doc/manual.html
index 85365363..eeacdcc9 100644
--- a/doc/manual.html
+++ b/doc/manual.html
@@ -2,7 +2,7 @@
<html>
<head>
-<title>Lua 5.2 Reference Manual</title>
+<title>Lua 5.3 Reference Manual</title>
<link rel="stylesheet" type="text/css" href="lua.css">
<link rel="stylesheet" type="text/css" href="manual.css">
<META HTTP-EQUIV="content-type" CONTENT="text/html; charset=iso-8859-1">
@@ -13,7 +13,7 @@
<hr>
<h1>
<a href="http://www.lua.org/"><img src="logo.gif" alt="" border="0"></a>
-Lua 5.2 Reference Manual
+Lua 5.3 Reference Manual
</h1>
by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes
@@ -33,7 +33,7 @@ Freely available under the terms of the
<!-- ====================================================================== -->
<p>
-<!-- $Id: manual.of,v 1.103 2013/03/14 18:51:56 roberto Exp $ -->
+<!-- $Id: manual.of,v 1.105 2013/07/05 18:48:52 roberto Exp $ -->
@@ -119,14 +119,11 @@ it usually represents the absence of a useful value.
<em>Boolean</em> is the type of the values <b>false</b> and <b>true</b>.
Both <b>nil</b> and <b>false</b> make a condition false;
any other value makes it true.
-<em>Number</em> represents real (double-precision floating-point) numbers.
-Operations on numbers follow the same rules of
-the underlying C&nbsp;implementation,
-which, in turn, usually follows the IEEE 754 standard.
-(It is easy to build Lua interpreters that use other
-internal representations for numbers,
-such as single-precision floats or long integers;
-see file <code>luaconf.h</code>.)
+<em>Number</em> represents both integer numbers and
+real (floating-point) numbers.
+Standard Lua uses 64-bit integers and double-precision floats,
+but it is easy to compile Lua so that it
+uses 32-bit integers and single-precision floats.
<em>String</em> represents immutable sequences of bytes.
Lua is 8-bit clean:
@@ -829,7 +826,7 @@ the collector directly (e.g., stop and restart it).
<p>
-As an experimental feature in Lua 5.2,
+As an experimental feature in Lua 5.3,
you can change the collector's operation mode
from incremental to <em>generational</em>.
A <em>generational collector</em> assumes that most objects die young,
@@ -1293,11 +1290,19 @@ which start with <code>0x</code> or <code>0X</code>.
Hexadecimal constants also accept an optional fractional part
plus an optional binary exponent,
marked by a letter '<code>p</code>' or '<code>P</code>'.
-Examples of valid numerical constants are
+A numeric constant with an fractional dot or an exponent
+denotes a floating-point number;
+otherwise it denotes an integer number.
+Examples of valid integer constants are
<pre>
- 3 3.0 3.1416 314.16e-2 0.31416E1
- 0xff 0x0.1E 0xA23p-4 0X1.921FB54442D18P+1
+ 3 345 0xff 0xBEBADA
+</pre><p>
+Examples of valid floating-point constants are
+
+<pre>
+ 3.0 3.1416 314.16e-2 0.31416E1 34e1
+ 0x0.1E 0xA23p-4 0X1.921FB54442D18P+1
</pre>
<p>
@@ -1923,38 +1928,113 @@ 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 usual arithmetic operators:
+Lua supports the following arithmetic operators:
the binary <code>+</code> (addition),
<code>-</code> (subtraction), <code>*</code> (multiplication),
-<code>/</code> (division), <code>%</code> (modulo), and <code>^</code> (exponentiation);
+<code>/</code> (division), <code>//</code> (integer division),
+<code>%</code> (modulo), and <code>^</code> (exponentiation);
and unary <code>-</code> (mathematical negation).
-If the operands are numbers, or strings that can be converted to
+Modulo is defined as the remainder of a division
+that rounds the quotient towards minus infinite (floor).
+
+
+<p>
+With the exception of division, integer division, 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.
+Otherwise, if both operands are numbers
+or strings that can be converted to
numbers (see <a href="#3.4.2">&sect;3.4.2</a>),
-then all operations have the usual meaning.
-Exponentiation works for any exponent.
-For instance, <code>x^(-0.5)</code> computes the inverse of the square root of <code>x</code>.
-Modulo is defined as
+then they are converted to floating-point numbers,
+the operation is performed following the usual rules
+for floating-point arithmetic
+(usually following the IEEE 754 standard),
+and the result is a floating-point number.
-<pre>
- a % b == a - math.floor(a/b)*b
-</pre><p>
-That is, it is the remainder of a division that rounds
-the quotient towards minus infinity.
+
+<p>
+Division (<code>/</code>) always converts its operands to floating-point numbers
+and its result is always a floating-point number.
+
+
+<p>
+Integer division (<code>//</code>) converts its operands to integer numbers
+(see <a href="#3.4.2">&sect;3.4.2</a>)
+and its result is always an integer number.
+The result is always rounded towards minus infinite (floor).
+<p>
+Exponentiation (<code>^</code>) checks whether both operands are integers and
+the exponent is non-negative.
+In that case, the exponentiation is performed as an integer operation
+and the result is an integer number.
+Otherwise, it is performed as a floatint-point operation (<code>pow</code>).
+
+
+<p>
+In case of overflows in integer arithmetic,
+all operations <em>wrap around</em>,
+according to the usual rules of two-complement arithmetic.
-<h3>3.4.2 &ndash; <a name="3.4.2">Coercion</a></h3>
+
+
+<h3>3.4.2 &ndash; <a name="3.4.2">Coercions and Conversions</a></h3>
<p>
-Lua provides automatic conversion between
-string and number values at run time.
-Any arithmetic operation applied to a string tries to convert
-this string to a number, following the rules of the Lua lexer.
+Lua provides some automatic conversions between types at run time.
+Most binary 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,
+and integer division always convert floating operands to integers.
+The C API also converts both integers to floats and
+floats to integers, as needed.
+Moreover, string concatenation accepts numbers as arguments,
+besides strings.
+
+
+<p>
+Lua also converts strings to numbers,
+whenever a number is expected.
+(This conversion may be deprecated in future versions.)
+
+
+<p>
+In a conversion from integer to float,
+if the integer value has an exact representation as a float,
+that is the result.
+Otherwise,
+the conversion gets the nearest higher or lower representable value.
+This kind of conversion never fails.
+
+
+<p>
+The conversion from float to integer
+first takes the floor of the float number.
+If that value can be represented as an integer number
+(that is, it is in the range of integer numbers),
+that is the result.
+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.)
-Conversely, whenever a number is used where a string is expected,
-the number is converted to a string, in a reasonable format.
+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 an then the float to an integer.
+
+
+<p>
+The conversion from numbers to strings use a reasonable,
+non-specified format.
+Floating-point numbers always produce strings with some
+floating-point indication (either a decimal dot or an exponent).
For complete control over how numbers are converted to strings,
use the <code>format</code> function from the string library
(see <a href="#pdf-string.format"><code>string.format</code></a>).
@@ -1976,7 +2056,15 @@ These operators always result in <b>false</b> or <b>true</b>.
Equality (<code>==</code>) first compares the type of its operands.
If the types are different, then the result is <b>false</b>.
Otherwise, the values of the operands are compared.
-Numbers and strings are compared in the usual way.
+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 floating-point numbers
+and compared as such.
+
+
+<p>
Tables, userdata, and threads
are compared by reference:
two objects are considered equal only if they are the same object.
@@ -1994,8 +2082,8 @@ by using the "eq" metamethod (see <a href="#2.4">&sect;2.4</a>).
<p>
-The conversion rules of <a href="#3.4.2">&sect;3.4.2</a>
-do not apply to equality comparisons.
+Equality comparisons never convert strings to numbers
+or vice versa.
Thus, <code>"0"==0</code> evaluates to <b>false</b>,
and <code>t[0]</code> and <code>t["0"]</code> denote different
entries in a table.
@@ -2007,7 +2095,9 @@ The operator <code>~=</code> is exactly the negation of equality (<code>==</code
<p>
The order operators work as follows.
-If both arguments are numbers, then they are compared as such.
+If both arguments are numbers,
+then they are compared following
+the usual rule for binary operations.
Otherwise, if both arguments are strings,
then their values are compared according to the current locale.
Otherwise, Lua tries to call the "lt" or the "le"
@@ -2088,7 +2178,7 @@ the length of a table <code>t</code> is only defined if the
table is a <em>sequence</em>,
that is,
the set of its positive numeric keys is equal to <em>{1..n}</em>
-for some integer <em>n</em>.
+for some non-negative integer <em>n</em>.
In that case, <em>n</em> is its length.
Note that a table like
@@ -2116,7 +2206,7 @@ from lower to higher priority:
&lt; &gt; &lt;= &gt;= ~= ==
..
+ -
- * / %
+ * / // %
not # - (unary)
^
</pre><p>
@@ -3511,13 +3601,14 @@ because a pseudo-index is not an actual stack position.
<pre>typedef ptrdiff_t lua_Integer;</pre>
<p>
-The type used by the Lua API to represent signed integral values.
+The type of integer numbers in Lua.
<p>
-By default it is a <code>ptrdiff_t</code>,
-which is usually the largest signed integral type the machine handles
-"comfortably".
+By default it is defined as <code>long long</code>,
+usually a 64-bit two-complement integer,
+but it can also be <code>long</code> or <code>int</code>,
+usually a 32-bit two-complement integer.
@@ -3559,6 +3650,19 @@ Returns 1 if the value at the given index is a function
+<hr><h3><a name="lua_isinteger"><code>lua_isinteger</code></a></h3><p>
+<span class="apii">[-0, +0, &ndash;]</span>
+<pre>int lua_isinteger (lua_State *L, int index);</pre>
+
+<p>
+Returns 1 if the value at the given index is an integer
+(that is, the value is a number and is represented as an integer),
+and 0&nbsp;otherwise.
+
+
+
+
+
<hr><h3><a name="lua_islightuserdata"><code>lua_islightuserdata</code></a></h3><p>
<span class="apii">[-0, +0, &ndash;]</span>
<pre>int lua_islightuserdata (lua_State *L, int index);</pre>
@@ -3762,7 +3866,7 @@ this upvalue will be the <code>_ENV</code> variable (see <a href="#2.2">&sect;2.
<p>
Creates a new thread running in a new, independent state.
-Returns <code>NULL</code> if cannot create the thread or the state
+Returns <code>NULL</code> if it cannot create the thread or the state
(due to lack of memory).
The argument <code>f</code> is the allocator function;
Lua does all memory allocation for this state through this function.
@@ -3869,10 +3973,9 @@ the table during its traversal.
<pre>typedef double lua_Number;</pre>
<p>
-The type of numbers in Lua.
-By default, it is double, but that can be changed in <code>luaconf.h</code>.
-Through this configuration file you can change
-Lua to operate with another type for numbers (e.g., float or long).
+The type of floating-point numbers in Lua.
+By default, it is double,
+but that can be changed in <code>luaconf.h</code> to a single float.
@@ -4109,7 +4212,7 @@ Pushes the global environment onto the stack.
<pre>void lua_pushinteger (lua_State *L, lua_Integer n);</pre>
<p>
-Pushes a number with value <code>n</code> onto the stack.
+Pushes an integer with value <code>n</code> onto the stack.
@@ -4293,7 +4396,7 @@ Similar to <a href="#lua_gettable"><code>lua_gettable</code></a>, but does a raw
<hr><h3><a name="lua_rawgeti"><code>lua_rawgeti</code></a></h3><p>
<span class="apii">[-0, +1, &ndash;]</span>
-<pre>void lua_rawgeti (lua_State *L, int index, int n);</pre>
+<pre>void lua_rawgeti (lua_State *L, int index, lua_Integer n);</pre>
<p>
Pushes onto the stack the value <code>t[n]</code>,
@@ -4351,7 +4454,7 @@ Similar to <a href="#lua_settable"><code>lua_settable</code></a>, but does a raw
<hr><h3><a name="lua_rawseti"><code>lua_rawseti</code></a></h3><p>
<span class="apii">[-1, +0, <em>e</em>]</span>
-<pre>void lua_rawseti (lua_State *L, int index, int n);</pre>
+<pre>void lua_rawseti (lua_State *L, int index, lua_Integer n);</pre>
<p>
Does the equivalent of <code>t[n] = v</code>,
@@ -4648,6 +4751,23 @@ 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>
+
+<p>
+Converts the string <code>s</code> (with length <code>len</code>) to a number and
+pushes that number into the stack.
+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.
+If the string is not a valid numeral,
+returns 0 and pushes nothing.
+
+
+
+
+
<hr><h3><a name="lua_toboolean"><code>lua_toboolean</code></a></h3><p>
<span class="apii">[-0, +0, &ndash;]</span>
<pre>int lua_toboolean (lua_State *L, int index);</pre>
@@ -4697,17 +4817,12 @@ Equivalent to <a href="#lua_tointegerx"><code>lua_tointegerx</code></a> with <co
<p>
Converts the Lua value at the given index
to the signed integral type <a href="#lua_Integer"><code>lua_Integer</code></a>.
-The Lua value must be a number or a string convertible to a number
-(see <a href="#3.4.2">&sect;3.4.2</a>);
+The Lua value must be an integer,
+or a number or string convertible to an integer (see <a href="#3.4.2">&sect;3.4.2</a>);
otherwise, <code>lua_tointegerx</code> returns&nbsp;0.
<p>
-If the number is not an integer,
-it is truncated in some non-specified way.
-
-
-<p>
If <code>isnum</code> is not <code>NULL</code>,
its referent is assigned a boolean value that
indicates whether the operation succeeded.
@@ -4842,16 +4957,18 @@ Equivalent to <a href="#lua_tounsignedx"><code>lua_tounsignedx</code></a> with <
<p>
Converts the Lua value at the given index
to the unsigned integral type <a href="#lua_Unsigned"><code>lua_Unsigned</code></a>.
-The Lua value must be a number or a string convertible to a number
+The Lua value must be an integer,
+or a float,
+or a string convertible to a number
(see <a href="#3.4.2">&sect;3.4.2</a>);
otherwise, <code>lua_tounsignedx</code> returns&nbsp;0.
<p>
If the number is not an integer,
-it is truncated in some non-specified way.
-If the number is outside the range of representable values,
-it is normalized to the remainder of its division by
+it is rounded towards minus infinite (floor).
+If the result is outside the range of representable values,
+it is normalized to the module of its division by
one more than the maximum representable value.
@@ -4919,13 +5036,7 @@ which must be one the values returned by <a href="#lua_type"><code>lua_type</cod
<pre>typedef unsigned long lua_Unsigned;</pre>
<p>
-The type used by the Lua API to represent unsigned integral values.
-It must have at least 32 bits.
-
-
-<p>
-By default it is an <code>unsigned int</code> or an <code>unsigned long</code>,
-whichever can hold 32-bit values.
+The unsigned version of <a href="#lua_Integer"><code>lua_Integer</code></a>.
@@ -5861,8 +5972,9 @@ of any type (including <b>nil</b>) at position <code>arg</code>.
<pre>int luaL_checkint (lua_State *L, int arg);</pre>
<p>
-Checks whether the function argument <code>arg</code> is a number
-and returns this number cast to an <code>int</code>.
+Checks whether the function argument <code>arg</code> is an integer
+(or can be converted to an integer)
+and returns this integer cast to an <code>int</code>.
@@ -5873,8 +5985,9 @@ and returns this number cast to an <code>int</code>.
<pre>lua_Integer luaL_checkinteger (lua_State *L, int arg);</pre>
<p>
-Checks whether the function argument <code>arg</code> is a number
-and returns this number cast to a <a href="#lua_Integer"><code>lua_Integer</code></a>.
+Checks whether the function argument <code>arg</code> is an integer
+(or can be converted to an integer)
+and returns this integer cast to a <a href="#lua_Integer"><code>lua_Integer</code></a>.
@@ -5885,8 +5998,9 @@ and returns this number cast to a <a href="#lua_Integer"><code>lua_Integer</code
<pre>long luaL_checklong (lua_State *L, int arg);</pre>
<p>
-Checks whether the function argument <code>arg</code> is a number
-and returns this number cast to a <code>long</code>.
+Checks whether the function argument <code>arg</code> is an integer
+(or can be converted to an integer)
+and returns this integer cast to a <code>long</code>.
@@ -6016,7 +6130,7 @@ returns the userdata address (see <a href="#lua_touserdata"><code>lua_touserdata
<p>
Checks whether the function argument <code>arg</code> is a number
-and returns this number cast to a <a href="#lua_Unsigned"><code>lua_Unsigned</code></a>.
+and returns this number converted to a <a href="#lua_Unsigned"><code>lua_Unsigned</code></a>.
@@ -6185,13 +6299,13 @@ Pushes the resulting string on the stack and returns it.
<hr><h3><a name="luaL_len"><code>luaL_len</code></a></h3><p>
<span class="apii">[-0, +0, <em>e</em>]</span>
-<pre>int luaL_len (lua_State *L, int index);</pre>
+<pre>lua_Integer luaL_len (lua_State *L, int index);</pre>
<p>
Returns the "length" of the value at the given index
as a number;
it is equivalent to the '<code>#</code>' operator in Lua (see <a href="#3.4.6">&sect;3.4.6</a>).
-Raises an error if the result of the operation is not a number.
+Raises an error if the result of the operation is not an integer.
(This case only can happen through metamethods.)
@@ -6413,8 +6527,9 @@ Otherwise, raises an error.
lua_Integer d);</pre>
<p>
-If the function argument <code>arg</code> is a number,
-returns this number cast to a <a href="#lua_Integer"><code>lua_Integer</code></a>.
+If the function argument <code>arg</code> is an integer
+(or convertible to an integer),
+returns this integer.
If this argument is absent or is <b>nil</b>,
returns <code>d</code>.
Otherwise, raises an error.
@@ -6428,8 +6543,9 @@ Otherwise, raises an error.
<pre>long luaL_optlong (lua_State *L, int arg, long d);</pre>
<p>
-If the function argument <code>arg</code> is a number,
-returns this number cast to a <code>long</code>.
+If the function argument <code>arg</code> is an integer
+(or convertible to an integer),
+returns this integer cast to a <code>long</code>.
If this argument is absent or is <b>nil</b>,
returns <code>d</code>.
Otherwise, raises an error.
@@ -6501,7 +6617,7 @@ Otherwise, raises an error.
<p>
If the function argument <code>arg</code> is a number,
-returns this number cast to a <a href="#lua_Unsigned"><code>lua_Unsigned</code></a>.
+returns this number converted to a <a href="#lua_Unsigned"><code>lua_Unsigned</code></a>.
If this argument is absent or is <b>nil</b>,
returns <code>u</code>.
Otherwise, raises an error.
@@ -7273,12 +7389,18 @@ This function returns <code>table</code>.
When called with no <code>base</code>,
<code>tonumber</code> tries to convert its argument to a number.
If the argument is already a number or
-a string convertible to a number (see <a href="#3.4.2">&sect;3.4.2</a>),
+a string convertible to a number,
then <code>tonumber</code> returns this number;
otherwise, it returns <b>nil</b>.
<p>
+The conversion of strings can result in integers or floats,
+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.)
+
+
+<p>
When called with <code>base</code>,
then <code>e</code> should be a string to be interpreted as
an integer numeral in that base.
@@ -7329,7 +7451,7 @@ and "<code>userdata</code>".
<hr><h3><a name="pdf-_VERSION"><code>_VERSION</code></a></h3>
A global variable (not a function) that
holds a string containing the current interpreter version.
-The current contents of this variable is "<code>Lua 5.2</code>".
+The current contents of this variable is "<code>Lua 5.3</code>".
@@ -8478,6 +8600,9 @@ By default, <code>i</code> is&nbsp;1 and <code>j</code> is <code>#list</code>.
<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
+floating-point numbers.
<p>
@@ -8629,6 +8754,29 @@ a value larger than or equal to any other numerical value.
<p>
+<hr><h3><a name="pdf-math.ifloor"><code>math.ifloor (x)</code></a></h3>
+
+
+<p>
+Returns the largest integer smaller than or equal to <code>x</code>
+as an integer number.
+If the value does not fit in an integer,
+returns <b>nil</b>.
+
+
+
+
+<p>
+<hr><h3><a name="pdf-math.isfloat"><code>math.isfloat (x)</code></a></h3>
+
+
+<p>
+Returns whether <code>x</code> is a floating-point number.
+
+
+
+
+<p>
<hr><h3><a name="pdf-math.ldexp"><code>math.ldexp (m, e)</code></a></h3>
@@ -8724,14 +8872,12 @@ pseudo-random generator function <code>rand</code> provided by Standard&nbsp;C.
<p>
When called without arguments,
-returns a uniform pseudo-random real number
+returns a uniform pseudo-random float number
in the range <em>[0,1)</em>.
-When called with an integer number <code>m</code>,
-<code>math.random</code> returns
-a uniform pseudo-random integer in the range <em>[1, m]</em>.
-When called with two integer numbers <code>m</code> and <code>n</code>,
+When called with two integer values <code>m</code> and <code>n</code>,
<code>math.random</code> returns a uniform pseudo-random
-integer in the range <em>[m, n]</em>.
+integer number in the range <em>[m, n]</em>.
+The call <code>math.random(n)</code> is equivalent to <code>math.random(1,n)</code>.
@@ -9886,6 +10032,18 @@ 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 integer (if <code>t</code> is "<code>i</code>")
+or float numbers (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>
@@ -9893,7 +10051,7 @@ returns <b>nil</b>.
Sets the given function as a hook.
The string <code>mask</code> and the number <code>count</code> describe
when the hook will be called.
-The string mask may have the following characters,
+The string mask may have any combination of the following characters,
with the given meaning:
<ul>
@@ -9901,8 +10059,9 @@ with the given meaning:
<li><b>'<code>r</code>': </b> the hook is called every time Lua returns from a function;</li>
<li><b>'<code>l</code>': </b> the hook is called every time Lua enters a new line of code.</li>
</ul><p>
-With a <code>count</code> different from zero,
-the hook is called after every <code>count</code> instructions.
+Moreover,
+with a <code>count</code> different from zero,
+the hook is called also after every <code>count</code> instructions.
<p>
@@ -10497,10 +10656,10 @@ Here is the complete syntax of Lua in extended BNF.
<HR>
<SMALL CLASS="footer">
Last update:
-Thu Mar 21 12:58:59 BRT 2013
+Fri Jul 5 23:09:01 BRT 2013
</SMALL>
<!--
-Last change: revised for Lua 5.2.2
+Last change: updated for Lua 5.3.0 (work1)
-->
</body></html>
diff --git a/doc/readme.html b/doc/readme.html
index 5b9e47ec..e3ff5850 100644
--- a/doc/readme.html
+++ b/doc/readme.html
@@ -1,7 +1,7 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML>
<HEAD>
-<TITLE>Lua 5.2 readme</TITLE>
+<TITLE>Lua 5.3 readme</TITLE>
<LINK REL="stylesheet" TYPE="text/css" HREF="lua.css">
<META HTTP-EQUIV="content-type" CONTENT="text/html; charset=iso-8859-1">
<STYLE TYPE="text/css">
@@ -30,7 +30,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.2
+Welcome to Lua 5.3 (work1)
</H1>
<P>
@@ -69,7 +69,7 @@ and
updated
<A HREF="http://www.lua.org/docs.html">documentation</A>,
especially the
-<A HREF="http://www.lua.org/manual/5.2/">reference manual</A>,
+<A HREF="http://www.lua.org/manual/5.3/">reference manual</A>,
which may differ slightly from the
<A HREF="contents.html">local copy</A>
distributed in this package.
@@ -109,7 +109,7 @@ Here are the details.
<OL>
<LI>
Open a terminal window and move to
-the top-level directory, which is named <TT>lua-5.2.2</TT>.
+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.
<P>
<LI>
@@ -261,7 +261,7 @@ compiler:
<H2><A NAME="changes">Changes since Lua 5.1</A></H2>
<P>
-Here are the main changes introduced in Lua 5.2.
+Here are the main changes introduced in Lua 5.3.
The
<A HREF="contents.html">reference manual</A>
lists the
@@ -279,7 +279,7 @@ lists the
<LI> finalizers for tables
</UL>
-Here are the other changes introduced in Lua 5.2:
+Here are the other changes introduced in Lua 5.3:
<H3>Language</H3>
<UL>
<LI> no more fenv for threads or functions
@@ -402,10 +402,10 @@ THE SOFTWARE.
<HR>
<SMALL CLASS="footer">
Last update:
-Fri Feb 22 09:24:20 BRT 2013
+Mon Jun 3 23:13:40 BRT 2013
</SMALL>
<!--
-Last change: revised for Lua 5.2.2
+Last change: revised for Lua 5.3.0
-->
</BODY>
diff --git a/src/.fix b/src/.fix
new file mode 100644
index 00000000..b390c3ca
--- /dev/null
+++ b/src/.fix
@@ -0,0 +1,2 @@
+#define nvalue(x) 0
+#define ttypenv(x) ttnov(x)
diff --git a/src/Makefile b/src/Makefile
index fea895bc..ca156758 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -7,7 +7,7 @@
PLAT= none
CC= gcc
-CFLAGS= -O2 -Wall -DLUA_COMPAT_ALL $(SYSCFLAGS) $(MYCFLAGS)
+CFLAGS= -O2 -Wall -Wextra -DLUA_COMPAT_ALL $(SYSCFLAGS) $(MYCFLAGS)
LDFLAGS= $(SYSLDFLAGS) $(MYLDFLAGS)
LIBS= -lm $(SYSLIBS) $(MYLIBS)
@@ -106,7 +106,7 @@ linux:
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -ldl -lreadline"
macosx:
- $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_MACOSX" SYSLIBS="-lreadline"
+ $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_MACOSX" SYSLIBS="-lreadline" CC=cc
mingw:
$(MAKE) "LUA_A=lua52.dll" "LUA_T=lua.exe" \
@@ -173,8 +173,8 @@ lstrlib.o: lstrlib.c lua.h luaconf.h lauxlib.h lualib.h
ltable.o: ltable.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \
ltm.h lzio.h lmem.h ldo.h lgc.h lstring.h ltable.h lvm.h
ltablib.o: ltablib.c lua.h luaconf.h lauxlib.h lualib.h
-ltm.o: ltm.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h lzio.h \
- lmem.h lstring.h lgc.h ltable.h
+ltm.o: ltm.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \
+ lzio.h lmem.h ldo.h lstring.h lgc.h ltable.h lvm.h
lua.o: lua.c lua.h luaconf.h lauxlib.h lualib.h
luac.o: luac.c lua.h luaconf.h lauxlib.h lobject.h llimits.h lstate.h \
ltm.h lzio.h lmem.h lundump.h ldebug.h lopcodes.h
@@ -185,3 +185,4 @@ lvm.o: lvm.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \
lzio.o: lzio.c lua.h luaconf.h llimits.h lmem.h lstate.h lobject.h ltm.h \
lzio.h
+# (end of Makefile)
diff --git a/src/lapi.c b/src/lapi.c
index 791d8545..a8c3e1c8 100644
--- a/src/lapi.c
+++ b/src/lapi.c
@@ -1,10 +1,11 @@
/*
-** $Id: lapi.c,v 2.171 2013/03/16 21:10:18 roberto Exp $
+** $Id: lapi.c,v 2.185 2013/07/05 14:29:51 roberto Exp $
** Lua API
** See Copyright Notice in lua.h
*/
+#include <math.h>
#include <stdarg.h>
#include <string.h>
@@ -248,7 +249,7 @@ LUA_API void lua_pushvalue (lua_State *L, int idx) {
LUA_API int lua_type (lua_State *L, int idx) {
StkId o = index2addr(L, idx);
- return (isvalid(o) ? ttypenv(o) : LUA_TNONE);
+ return (isvalid(o) ? ttnov(o) : LUA_TNONE);
}
@@ -264,8 +265,14 @@ LUA_API int lua_iscfunction (lua_State *L, int idx) {
}
+LUA_API int lua_isinteger (lua_State *L, int idx) {
+ StkId o = index2addr(L, idx);
+ return ttisinteger(o);
+}
+
+
LUA_API int lua_isnumber (lua_State *L, int idx) {
- TValue n;
+ lua_Number n;
const TValue *o = index2addr(L, idx);
return tonumber(o, &n);
}
@@ -291,8 +298,6 @@ LUA_API int lua_rawequal (lua_State *L, int index1, int index2) {
LUA_API void lua_arith (lua_State *L, int op) {
- StkId o1; /* 1st operand */
- StkId o2; /* 2nd operand */
lua_lock(L);
if (op != LUA_OPUNM) /* all other operations expect two operands */
api_checknelems(L, 2);
@@ -301,14 +306,9 @@ LUA_API void lua_arith (lua_State *L, int op) {
setobjs2s(L, L->top, L->top - 1);
L->top++;
}
- o1 = L->top - 2;
- o2 = L->top - 1;
- if (ttisnumber(o1) && ttisnumber(o2)) {
- setnvalue(o1, luaO_arith(op, nvalue(o1), nvalue(o2)));
- }
- else
- luaV_arith(L, o1, o1, o2, cast(TMS, op - LUA_OPADD + TM_ADD));
- L->top--;
+ /* first operand at top - 2, second at top - 1; result go to top - 2 */
+ luaO_arith(L, op, L->top - 2, L->top - 1, L->top - 2);
+ L->top--; /* remove second operand */
lua_unlock(L);
}
@@ -321,7 +321,7 @@ LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) {
o2 = index2addr(L, index2);
if (isvalid(o1) && isvalid(o2)) {
switch (op) {
- case LUA_OPEQ: i = equalobj(L, o1, o2); break;
+ case LUA_OPEQ: i = luaV_equalobj(L, o1, o2); break;
case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break;
case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break;
default: api_check(L, 0, "invalid option");
@@ -332,51 +332,74 @@ LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) {
}
-LUA_API lua_Number lua_tonumberx (lua_State *L, int idx, int *isnum) {
- TValue n;
- const TValue *o = index2addr(L, idx);
- if (tonumber(o, &n)) {
- if (isnum) *isnum = 1;
- return nvalue(o);
+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 (isnum) *isnum = 0;
- return 0;
+ 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 lua_Integer lua_tointegerx (lua_State *L, int idx, int *isnum) {
- TValue n;
+LUA_API lua_Number lua_tonumberx (lua_State *L, int idx, int *pisnum) {
+ lua_Number n;
const TValue *o = index2addr(L, idx);
- if (tonumber(o, &n)) {
- lua_Integer res;
- lua_Number num = nvalue(o);
- lua_number2integer(res, num);
- if (isnum) *isnum = 1;
- return res;
- }
- else {
- if (isnum) *isnum = 0;
- return 0;
- }
+ int isnum = tonumber(o, &n);
+ if (!isnum)
+ n = 0; /* call to 'tonumber' may change 'n' even if it fails */
+ if (pisnum) *pisnum = isnum;
+ return n;
}
-LUA_API lua_Unsigned lua_tounsignedx (lua_State *L, int idx, int *isnum) {
- TValue n;
+LUA_API lua_Integer lua_tointegerx (lua_State *L, int idx, int *pisnum) {
+ lua_Integer res;
const TValue *o = index2addr(L, idx);
- if (tonumber(o, &n)) {
- lua_Unsigned res;
- lua_Number num = nvalue(o);
- lua_number2unsigned(res, num);
- if (isnum) *isnum = 1;
- return res;
- }
- else {
- if (isnum) *isnum = 0;
- return 0;
+ int isnum = tointeger(o, &res);
+ if (!isnum)
+ res = 0; /* call to 'tointeger' may change 'n' even if it fails */
+ if (pisnum) *pisnum = isnum;
+ return res;
+}
+
+
+LUA_API lua_Unsigned lua_tounsignedx (lua_State *L, int idx, int *pisnum) {
+ lua_Unsigned res = 0;
+ const TValue *o = index2addr(L, idx);
+ int isnum = 0;
+ switch (ttype(o)) {
+ case LUA_TNUMINT: {
+ res = cast_unsigned(ivalue(o));
+ isnum = 1;
+ break;
+ }
+ case LUA_TNUMFLT: {
+ const lua_Number twop = (~(lua_Unsigned)0) + cast_num(1);
+ lua_Number n = fltvalue(o);
+ int neg = 0;
+ n = l_floor(n);
+ if (n < 0) {
+ neg = 1;
+ n = -n;
+ }
+ n = l_mathop(fmod)(n, twop);
+ if (luai_numisnan(L,n)) /* not a number? */
+ break; /* not an integer, too */
+ res = cast_unsigned(n);
+ if (neg) res = 0u - res;
+ isnum = 1;
+ break;
+ }
+ default: break;
}
+ if (pisnum) *pisnum = isnum;
+ return res;
}
@@ -406,7 +429,7 @@ LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) {
LUA_API size_t lua_rawlen (lua_State *L, int idx) {
StkId o = index2addr(L, idx);
- switch (ttypenv(o)) {
+ switch (ttnov(o)) {
case LUA_TSTRING: return tsvalue(o)->len;
case LUA_TUSERDATA: return uvalue(o)->len;
case LUA_TTABLE: return luaH_getn(hvalue(o));
@@ -426,7 +449,7 @@ LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) {
LUA_API void *lua_touserdata (lua_State *L, int idx) {
StkId o = index2addr(L, idx);
- switch (ttypenv(o)) {
+ switch (ttnov(o)) {
case LUA_TUSERDATA: return (rawuvalue(o) + 1);
case LUA_TLIGHTUSERDATA: return pvalue(o);
default: return NULL;
@@ -482,17 +505,15 @@ LUA_API void lua_pushnumber (lua_State *L, lua_Number n) {
LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) {
lua_lock(L);
- setnvalue(L->top, cast_num(n));
+ setivalue(L->top, n);
api_incr_top(L);
lua_unlock(L);
}
LUA_API void lua_pushunsigned (lua_State *L, lua_Unsigned u) {
- lua_Number n;
lua_lock(L);
- n = lua_unsigned2number(u);
- setnvalue(L->top, n);
+ setivalue(L->top, cast_integer(u));
api_incr_top(L);
lua_unlock(L);
}
@@ -646,7 +667,7 @@ LUA_API void lua_rawget (lua_State *L, int idx) {
}
-LUA_API void lua_rawgeti (lua_State *L, int idx, int n) {
+LUA_API void lua_rawgeti (lua_State *L, int idx, lua_Integer n) {
StkId t;
lua_lock(L);
t = index2addr(L, idx);
@@ -689,7 +710,7 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) {
int res;
lua_lock(L);
obj = index2addr(L, objindex);
- switch (ttypenv(obj)) {
+ switch (ttnov(obj)) {
case LUA_TTABLE:
mt = hvalue(obj)->metatable;
break;
@@ -697,7 +718,7 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) {
mt = uvalue(obj)->metatable;
break;
default:
- mt = G(L)->mt[ttypenv(obj)];
+ mt = G(L)->mt[ttnov(obj)];
break;
}
if (mt == NULL)
@@ -781,7 +802,7 @@ LUA_API void lua_rawset (lua_State *L, int idx) {
}
-LUA_API void lua_rawseti (lua_State *L, int idx, int n) {
+LUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) {
StkId t;
lua_lock(L);
api_checknelems(L, 1);
@@ -821,7 +842,7 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) {
api_check(L, ttistable(L->top - 1), "table expected");
mt = hvalue(L->top - 1);
}
- switch (ttypenv(obj)) {
+ switch (ttnov(obj)) {
case LUA_TTABLE: {
hvalue(obj)->metatable = mt;
if (mt) {
@@ -839,7 +860,7 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) {
break;
}
default: {
- G(L)->mt[ttypenv(obj)] = mt;
+ G(L)->mt[ttnov(obj)] = mt;
break;
}
}
diff --git a/src/lauxlib.c b/src/lauxlib.c
index 2e989d66..68373b0a 100644
--- a/src/lauxlib.c
+++ b/src/lauxlib.c
@@ -1,5 +1,5 @@
/*
-** $Id: lauxlib.c,v 1.248 2013/03/21 13:54:57 roberto Exp $
+** $Id: lauxlib.c,v 1.255 2013/06/27 18:32:33 roberto Exp $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/
@@ -386,11 +386,20 @@ LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) {
}
+static void interror (lua_State *L, int narg) {
+ if (lua_type(L, narg) == LUA_TNUMBER)
+ luaL_argerror(L, narg, "float value out of range");
+ else
+ tag_error(L, narg, LUA_TNUMBER);
+}
+
+
LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) {
int isnum;
lua_Integer d = lua_tointegerx(L, narg, &isnum);
- if (!isnum)
- tag_error(L, narg, LUA_TNUMBER);
+ if (!isnum) {
+ interror(L, narg);
+ }
return d;
}
@@ -399,7 +408,7 @@ LUALIB_API lua_Unsigned luaL_checkunsigned (lua_State *L, int narg) {
int isnum;
lua_Unsigned d = lua_tounsignedx(L, narg, &isnum);
if (!isnum)
- tag_error(L, narg, LUA_TNUMBER);
+ interror(L, narg);
return d;
}
@@ -722,13 +731,13 @@ LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) {
}
-LUALIB_API int luaL_len (lua_State *L, int idx) {
- int l;
+LUALIB_API lua_Integer luaL_len (lua_State *L, int idx) {
+ lua_Integer l;
int isnum;
lua_len(L, idx);
- l = (int)lua_tointegerx(L, -1, &isnum);
+ l = lua_tointegerx(L, -1, &isnum);
if (!isnum)
- luaL_error(L, "object length is not a number");
+ luaL_error(L, "object length is not an integer");
lua_pop(L, 1); /* remove object */
return l;
}
@@ -737,7 +746,12 @@ LUALIB_API int luaL_len (lua_State *L, int idx) {
LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) {
if (!luaL_callmeta(L, idx, "__tostring")) { /* no metafield? */
switch (lua_type(L, idx)) {
- case LUA_TNUMBER:
+ case LUA_TNUMBER: { /* concatenate with empty string to convert */
+ lua_pushvalue(L, idx);
+ lua_pushliteral(L, "");
+ lua_concat(L, 2);
+ break;
+ }
case LUA_TSTRING:
lua_pushvalue(L, idx);
break;
@@ -846,7 +860,6 @@ LUALIB_API void luaL_openlib (lua_State *L, const char *libname,
** Returns with only the table at the stack.
*/
LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
- luaL_checkversion(L);
luaL_checkstack(L, nup, "too many upvalues");
for (; l->name != NULL; l++) { /* fill the table with given functions */
int i;
@@ -941,19 +954,15 @@ LUALIB_API lua_State *luaL_newstate (void) {
}
-LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver) {
+LUALIB_API void luaL_checkversion_ (lua_State *L, int 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 %f, Lua core provides %f",
+ luaL_error(L, "version mismatch: app. needs %d, Lua core provides %f",
ver, *v);
- /* check conversions number -> integer types */
- lua_pushnumber(L, -(lua_Number)0x1234);
- if (lua_tointeger(L, -1) != -0x1234 ||
- lua_tounsigned(L, -1) != (lua_Unsigned)-0x1234)
- luaL_error(L, "bad conversion number->int;"
- " must recompile Lua with proper settings");
- lua_pop(L, 1);
+ /* check numeric types */
+ if (sz != LUAL_NUMSIZES)
+ luaL_error(L, "core and library have incompatible numeric types");
}
diff --git a/src/lauxlib.h b/src/lauxlib.h
index ac4d15fb..6b345e28 100644
--- a/src/lauxlib.h
+++ b/src/lauxlib.h
@@ -1,5 +1,5 @@
/*
-** $Id: lauxlib.h,v 1.120 2011/11/29 15:55:08 roberto Exp $
+** $Id: lauxlib.h,v 1.122 2013/06/27 18:32:33 roberto Exp $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/
@@ -26,8 +26,11 @@ typedef struct luaL_Reg {
} luaL_Reg;
-LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver);
-#define luaL_checkversion(L) luaL_checkversion_(L, LUA_VERSION_NUM)
+#define LUAL_NUMSIZES (sizeof(lua_Integer)*16 + sizeof(lua_Number))
+
+LUALIB_API void (luaL_checkversion_) (lua_State *L, int ver, size_t sz);
+#define luaL_checkversion(L) \
+ luaL_checkversion_(L, LUA_VERSION_NUM, LUAL_NUMSIZES)
LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e);
LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e);
@@ -83,7 +86,7 @@ LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s);
LUALIB_API lua_State *(luaL_newstate) (void);
-LUALIB_API int (luaL_len) (lua_State *L, int idx);
+LUALIB_API lua_Integer (luaL_len) (lua_State *L, int idx);
LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p,
const char *r);
@@ -108,7 +111,8 @@ LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname,
#define luaL_newlibtable(L,l) \
lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1)
-#define luaL_newlib(L,l) (luaL_newlibtable(L,l), luaL_setfuncs(L,l,0))
+#define luaL_newlib(L,l) \
+ (luaL_checkversion(L), luaL_newlibtable(L,l), luaL_setfuncs(L,l,0))
#define luaL_argcheck(L, cond,numarg,extramsg) \
((void)((cond) || luaL_argerror(L, (numarg), (extramsg))))
diff --git a/src/lbaselib.c b/src/lbaselib.c
index 540e9a5c..d074b92d 100644
--- a/src/lbaselib.c
+++ b/src/lbaselib.c
@@ -1,5 +1,5 @@
/*
-** $Id: lbaselib.c,v 1.276 2013/02/21 13:44:53 roberto Exp $
+** $Id: lbaselib.c,v 1.279 2013/07/05 14:39:15 roberto Exp $
** Basic library
** See Copyright Notice in lua.h
*/
@@ -45,42 +45,57 @@ 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) {
+ 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;
+ do {
+ int digit = (isdigit((unsigned char)*s)) ? *s - '0'
+ : toupper((unsigned char)*s) - 'A' + 10;
+ if (digit >= base) return 0; /* 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;
+ *pn = (neg) ? -(lua_Integer)n : (lua_Integer)n;
+ return 1;
+}
+
+
static int luaB_tonumber (lua_State *L) {
if (lua_isnoneornil(L, 2)) { /* standard conversion */
- int isnum;
- lua_Number n = lua_tonumberx(L, 1, &isnum);
- if (isnum) {
- lua_pushnumber(L, n);
- return 1;
- } /* else not a number; must be something */
luaL_checkany(L, 1);
+ if (lua_type(L, 1) == LUA_TNUMBER) { /* already a number? */
+ lua_settop(L, 1); /* yes; return it */
+ return 1;
+ }
+ 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;
+ /* else not a number */
+ }
}
else {
size_t l;
- const char *s = luaL_checklstring(L, 1, &l);
- const char *e = s + l; /* end point for 's' */
+ const char *s;
+ lua_Integer n;
int base = luaL_checkint(L, 2);
- int neg = 0;
+ 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");
- s += strspn(s, SPACECHARS); /* skip initial spaces */
- if (*s == '-') { s++; neg = 1; } /* handle signal */
- else if (*s == '+') s++;
- if (isalnum((unsigned char)*s)) {
- lua_Number n = 0;
- do {
- int digit = (isdigit((unsigned char)*s)) ? *s - '0'
- : toupper((unsigned char)*s) - 'A' + 10;
- if (digit >= base) break; /* invalid numeral; force a fail */
- n = n * (lua_Number)base + (lua_Number)digit;
- s++;
- } while (isalnum((unsigned char)*s));
- s += strspn(s, SPACECHARS); /* skip trailing spaces */
- if (s == e) { /* no invalid trailing characters? */
- lua_pushnumber(L, (neg) ? -n : n);
- return 1;
- } /* else not a number */
+ if (b_str2int(s, s + l, base, &n)) {
+ lua_pushinteger(L, n);
+ return 1;
} /* else not a number */
- }
+ } /* else not a number */
lua_pushnil(L); /* not a number */
return 1;
}
diff --git a/src/lbitlib.c b/src/lbitlib.c
index 9637532e..d6d436bc 100644
--- a/src/lbitlib.c
+++ b/src/lbitlib.c
@@ -1,5 +1,5 @@
/*
-** $Id: lbitlib.c,v 1.18 2013/03/19 13:19:12 roberto Exp $
+** $Id: lbitlib.c,v 1.20 2013/06/21 17:27:24 roberto Exp $
** Standard library for bitwise operations
** See Copyright Notice in lua.h
*/
@@ -19,7 +19,12 @@
#endif
-#define ALLONES (~(((~(lua_Unsigned)0) << (LUA_NBITS - 1)) << 1))
+/* type with (at least) LUA_NBITS bits */
+typedef unsigned long b_uint;
+
+
+#define ALLONES (~(((~(b_uint)0) << (LUA_NBITS - 1)) << 1))
+
/* macro to trim extra bits */
#define trim(x) ((x) & ALLONES)
@@ -29,9 +34,6 @@
#define mask(n) (~((ALLONES << 1) << ((n) - 1)))
-typedef lua_Unsigned b_uint;
-
-
static b_uint andaux (lua_State *L) {
int i, n = lua_gettop(L);
@@ -118,7 +120,7 @@ static int b_arshift (lua_State *L) {
else { /* arithmetic shift for 'negative' number */
if (i >= LUA_NBITS) r = ALLONES;
else
- r = trim((r >> i) | ~(~(b_uint)0 >> i)); /* add signal bit */
+ r = trim((r >> i) | ~(trim(~(b_uint)0) >> i)); /* add signal bit */
lua_pushunsigned(L, r);
return 1;
}
@@ -165,7 +167,7 @@ static int fieldargs (lua_State *L, int farg, int *width) {
static int b_extract (lua_State *L) {
int w;
- b_uint r = luaL_checkunsigned(L, 1);
+ b_uint r = trim(luaL_checkunsigned(L, 1));
int f = fieldargs(L, 2, &w);
r = (r >> f) & mask(w);
lua_pushunsigned(L, r);
@@ -175,7 +177,7 @@ static int b_extract (lua_State *L) {
static int b_replace (lua_State *L) {
int w;
- b_uint r = luaL_checkunsigned(L, 1);
+ b_uint r = trim(luaL_checkunsigned(L, 1));
b_uint v = luaL_checkunsigned(L, 2);
int f = fieldargs(L, 3, &w);
int m = mask(w);
diff --git a/src/lcode.c b/src/lcode.c
index 56c26ac8..261090e0 100644
--- a/src/lcode.c
+++ b/src/lcode.c
@@ -1,10 +1,11 @@
/*
-** $Id: lcode.c,v 2.62 2012/08/16 17:34:28 roberto Exp $
+** $Id: lcode.c,v 2.71 2013/06/25 18:57:18 roberto Exp $
** Code generator for Lua
** See Copyright Notice in lua.h
*/
+#include <math.h>
#include <stdlib.h>
#define lcode_c
@@ -26,11 +27,29 @@
#include "lvm.h"
+/* test for x == -0 */
+#if defined(signbit)
+#define isminuszero(x) ((x) == 0.0 && signbit(x))
+#else
+#define isminuszero(x) ((x) == 0.0 && 1.0/(x) < 0.0)
+#endif
+
+
#define hasjumps(e) ((e)->t != (e)->f)
-static int isnumeral(expdesc *e) {
- return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP);
+static int tonumeral(expdesc *e, TValue *v) {
+ if (e->t != NO_JUMP || e->f != NO_JUMP)
+ return 0; /* not a numeral */
+ switch (e->k) {
+ case VKINT:
+ if (v) setivalue(v, e->u.ival);
+ return 1;
+ case VKFLT:
+ if (v) setnvalue(v, e->u.nval);
+ return 1;
+ default: return 0;
+ }
}
@@ -293,9 +312,8 @@ static int addk (FuncState *fs, TValue *key, TValue *v) {
TValue *idx = luaH_set(L, fs->h, key);
Proto *f = fs->f;
int k, oldsize;
- if (ttisnumber(idx)) {
- lua_Number n = nvalue(idx);
- lua_number2int(k, n);
+ if (ttisinteger(idx)) {
+ k = ivalue(idx);
if (luaV_rawequalobj(&f->k[k], v))
return k;
/* else may be a collision (e.g., between 0.0 and "\0\0\0\0\0\0\0\0");
@@ -306,7 +324,7 @@ static int addk (FuncState *fs, TValue *key, TValue *v) {
k = fs->nk;
/* numerical value does not need GC barrier;
table has no metatable, so it does not need to invalidate cache */
- setnvalue(idx, cast_num(k));
+ setivalue(idx, k);
luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants");
while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]);
setobj(L, &f->k[k], v);
@@ -323,20 +341,28 @@ int luaK_stringK (FuncState *fs, TString *s) {
}
-int luaK_numberK (FuncState *fs, lua_Number r) {
- int n;
- lua_State *L = fs->ls->L;
+/*
+** use userdata as key to avoid collision with float with same value;
+** conversion to 'void*' used only for hash, no "precision" problems
+*/
+int luaK_intK (FuncState *fs, lua_Integer n) {
+ TValue k, o;
+ setpvalue(&k, cast(void*, cast(size_t, n)));
+ setivalue(&o, n);
+ return addk(fs, &k, &o);
+}
+
+
+/*
+** 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.)
+*/
+static int luaK_numberK (FuncState *fs, lua_Number r) {
TValue o;
+ lua_assert(!luai_numisnan(NULL, r) && !isminuszero(r));
setnvalue(&o, r);
- if (r == 0 || luai_numisnan(NULL, r)) { /* handle -0 and NaN */
- /* use raw representation as key to avoid numeric problems */
- setsvalue(L, L->top++, luaS_newlstr(L, (char *)&r, sizeof(r)));
- n = addk(fs, L->top - 1, &o);
- L->top--;
- }
- else
- n = addk(fs, &o, &o); /* regular case */
- return n;
+ return addk(fs, &o, &o);
}
@@ -433,10 +459,14 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
luaK_codek(fs, reg, e->u.info);
break;
}
- case VKNUM: {
+ case VKFLT: {
luaK_codek(fs, reg, luaK_numberK(fs, e->u.nval));
break;
}
+ case VKINT: {
+ luaK_codek(fs, reg, luaK_intK(fs, e->u.ival));
+ break;
+ }
case VRELOCABLE: {
Instruction *pc = &getcode(fs, e);
SETARG_A(*pc, reg);
@@ -538,12 +568,18 @@ int luaK_exp2RK (FuncState *fs, expdesc *e) {
}
else break;
}
- case VKNUM: {
+ case VKINT: {
+ e->u.info = luaK_intK(fs, e->u.ival);
+ e->k = VK;
+ goto vk;
+ }
+ case VKFLT: {
e->u.info = luaK_numberK(fs, e->u.nval);
e->k = VK;
/* go through */
}
case VK: {
+ vk:
if (e->u.info <= MAXINDEXRK) /* constant fits in argC? */
return RKASK(e->u.info);
else break;
@@ -627,7 +663,7 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) {
pc = e->u.info;
break;
}
- case VK: case VKNUM: case VTRUE: {
+ case VK: case VKFLT: case VKINT: case VTRUE: {
pc = NO_JUMP; /* always true; do nothing */
break;
}
@@ -672,7 +708,7 @@ static void codenot (FuncState *fs, expdesc *e) {
e->k = VTRUE;
break;
}
- case VK: case VKNUM: case VTRUE: {
+ case VK: case VKFLT: case VKINT: case VTRUE: {
e->k = VFALSE;
break;
}
@@ -711,21 +747,34 @@ void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
static int constfolding (OpCode op, expdesc *e1, expdesc *e2) {
- lua_Number r;
- if (!isnumeral(e1) || !isnumeral(e2)) return 0;
- if ((op == OP_DIV || op == OP_MOD) && e2->u.nval == 0)
- return 0; /* do not attempt to divide by 0 */
- r = luaO_arith(op - OP_ADD + LUA_OPADD, e1->u.nval, e2->u.nval);
- e1->u.nval = r;
+ TValue v1, v2, res;
+ lua_Integer i;
+ if (!tonumeral(e1, &v1) || !tonumeral(e2, &v2))
+ return 0;
+ if (op == OP_IDIV &&
+ (!tointeger(&v1, &i) || !tointeger(&v2, &i) || i == 0))
+ return 0; /* avoid division by 0 and conversion errors */
+ if (op == OP_MOD && ttisinteger(&v1) && ttisinteger(&v2) && ivalue(&v2) == 0)
+ return 0; /* avoid module by 0 at compile time */
+ luaO_arith(NULL, op - OP_ADD + LUA_OPADD, &v1, &v2, &res);
+ if (ttisinteger(&res)) {
+ e1->k = VKINT;
+ e1->u.ival = ivalue(&res);
+ }
+ else {
+ lua_Number n = fltvalue(&res);
+ if (luai_numisnan(NULL, n) || isminuszero(n))
+ return 0; /* folds neither NaN nor -0 */
+ e1->k = VKFLT;
+ e1->u.nval = n;
+ }
return 1;
}
static void codearith (FuncState *fs, OpCode op,
expdesc *e1, expdesc *e2, int line) {
- if (constfolding(op, e1, e2))
- return;
- else {
+ if (!constfolding(op, e1, e2)) { /* could not fold operation? */
int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0;
int o1 = luaK_exp2RK(fs, e1);
if (o1 > o2) {
@@ -761,12 +810,10 @@ static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1,
void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) {
expdesc e2;
- e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0;
+ e2.t = e2.f = NO_JUMP; e2.k = VKFLT; e2.u.nval = 0;
switch (op) {
case OPR_MINUS: {
- if (isnumeral(e)) /* minus constant? */
- e->u.nval = luai_numunm(NULL, e->u.nval); /* fold it */
- else {
+ if (!constfolding(OP_UNM, e, e)) { /* cannot fold it? */
luaK_exp2anyreg(fs, e);
codearith(fs, OP_UNM, e, &e2, line);
}
@@ -797,9 +844,10 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */
break;
}
- case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV:
+ case OPR_ADD: case OPR_SUB:
+ case OPR_MUL: case OPR_DIV: case OPR_IDIV:
case OPR_MOD: case OPR_POW: {
- if (!isnumeral(v)) luaK_exp2RK(fs, v);
+ if (!tonumeral(v, NULL)) luaK_exp2RK(fs, v);
break;
}
default: {
@@ -842,7 +890,7 @@ void luaK_posfix (FuncState *fs, BinOpr op,
break;
}
case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV:
- case OPR_MOD: case OPR_POW: {
+ case OPR_IDIV: case OPR_MOD: case OPR_POW: {
codearith(fs, cast(OpCode, op - OPR_ADD + OP_ADD), e1, e2, line);
break;
}
diff --git a/src/lcode.h b/src/lcode.h
index 5a1fa9fe..07d451b4 100644
--- a/src/lcode.h
+++ b/src/lcode.h
@@ -1,5 +1,5 @@
/*
-** $Id: lcode.h,v 1.58 2011/08/30 16:26:41 roberto Exp $
+** $Id: lcode.h,v 1.60 2013/04/26 13:07:53 roberto Exp $
** Code generator for Lua
** See Copyright Notice in lua.h
*/
@@ -24,7 +24,7 @@
** grep "ORDER OPR" if you change these enums (ORDER OP)
*/
typedef enum BinOpr {
- OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW,
+ OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_IDIV, OPR_MOD, OPR_POW,
OPR_CONCAT,
OPR_EQ, OPR_LT, OPR_LE,
OPR_NE, OPR_GT, OPR_GE,
@@ -52,7 +52,7 @@ LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n);
LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n);
LUAI_FUNC void luaK_checkstack (FuncState *fs, int n);
LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s);
-LUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r);
+LUAI_FUNC int luaK_intK (FuncState *fs, lua_Integer n);
LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e);
LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e);
LUAI_FUNC void luaK_exp2anyregup (FuncState *fs, expdesc *e);
diff --git a/src/ldblib.c b/src/ldblib.c
index c0226945..30499a62 100644
--- a/src/ldblib.c
+++ b/src/ldblib.c
@@ -1,5 +1,5 @@
/*
-** $Id: ldblib.c,v 1.132 2012/01/19 20:14:44 roberto Exp $
+** $Id: ldblib.c,v 1.133 2013/06/25 19:37:00 roberto Exp $
** Interface from Lua to its debug API
** See Copyright Notice in lua.h
*/
@@ -22,6 +22,18 @@
+static int db_numbits (lua_State *L) {
+ 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;
+}
+
+
static int db_getregistry (lua_State *L) {
lua_pushvalue(L, LUA_REGISTRYINDEX);
return 1;
@@ -379,6 +391,7 @@ 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/ldebug.c b/src/ldebug.c
index 7e04f9d0..c9b88803 100644
--- a/src/ldebug.c
+++ b/src/ldebug.c
@@ -1,5 +1,5 @@
/*
-** $Id: ldebug.c,v 2.90 2012/08/16 17:34:28 roberto Exp $
+** $Id: ldebug.c,v 2.95 2013/05/06 17:21:59 roberto Exp $
** Debug Interface
** See Copyright Notice in lua.h
*/
@@ -453,6 +453,7 @@ static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {
case OP_SUB: tm = TM_SUB; break;
case OP_MUL: tm = TM_MUL; break;
case OP_DIV: tm = TM_DIV; break;
+ case OP_IDIV: tm = TM_IDIV; break;
case OP_MOD: tm = TM_MOD; break;
case OP_POW: tm = TM_POW; break;
case OP_UNM: tm = TM_UNM; break;
@@ -497,10 +498,9 @@ static const char *getupvalname (CallInfo *ci, const TValue *o,
}
-l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
+static const char *varinfo (lua_State *L, const TValue *o) {
+ const char *name;
CallInfo *ci = L->ci;
- const char *name = NULL;
- const char *t = objtypename(o);
const char *kind = NULL;
if (isLua(ci)) {
kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */
@@ -508,29 +508,40 @@ l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
kind = getobjname(ci_func(ci)->p, currentpc(ci),
cast_int(o - ci->u.l.base), &name);
}
- if (kind)
- luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)",
- op, kind, name, t);
- else
- luaG_runerror(L, "attempt to %s a %s value", op, t);
+ return (kind) ? luaO_pushfstring(L, " (%s " LUA_QS ")", kind, name) : "";
+}
+
+
+l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
+ const char *t = objtypename(o);
+ luaG_runerror(L, "attempt to %s a %s value%s", op, t, varinfo(L, o));
}
-l_noret luaG_concaterror (lua_State *L, StkId p1, StkId p2) {
+l_noret luaG_concaterror (lua_State *L, const TValue *p1, const TValue *p2) {
if (ttisstring(p1) || ttisnumber(p1)) p1 = p2;
- lua_assert(!ttisstring(p1) && !ttisnumber(p2));
+ lua_assert(!ttisstring(p1) && !ttisnumber(p1));
luaG_typeerror(L, p1, "concatenate");
}
l_noret luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) {
- TValue temp;
- if (luaV_tonumber(p1, &temp) == NULL)
+ lua_Number temp;
+ if (!tonumber(p1, &temp))
p2 = p1; /* first operand is wrong */
luaG_typeerror(L, p2, "perform arithmetic on");
}
+l_noret luaG_tointerror (lua_State *L, const TValue *p1, const TValue *p2) {
+ lua_Integer temp;
+ if (!tointeger(p1, &temp))
+ p2 = p1;
+ luaG_runerror(L, "attempt to convert an out of range float%s to an integer",
+ varinfo(L, p2));
+}
+
+
l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) {
const char *t1 = objtypename(p1);
const char *t2 = objtypename(p2);
@@ -578,3 +589,36 @@ l_noret luaG_runerror (lua_State *L, const char *fmt, ...) {
luaG_errormsg(L);
}
+
+void luaG_traceexec (lua_State *L) {
+ CallInfo *ci = L->ci;
+ lu_byte mask = L->hookmask;
+ int counthook = ((mask & LUA_MASKCOUNT) && L->hookcount == 0);
+ if (counthook)
+ resethookcount(L); /* reset count */
+ if (ci->callstatus & CIST_HOOKYIELD) { /* called hook last time? */
+ ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */
+ return; /* do not call hook again (VM yielded, so it did not move) */
+ }
+ if (counthook)
+ luaD_hook(L, LUA_HOOKCOUNT, -1); /* call count hook */
+ if (mask & LUA_MASKLINE) {
+ Proto *p = ci_func(ci)->p;
+ int npc = pcRel(ci->u.l.savedpc, p);
+ int newline = getfuncline(p, npc);
+ if (npc == 0 || /* call linehook when enter a new function, */
+ ci->u.l.savedpc <= L->oldpc || /* when jump back (loop), or when */
+ newline != getfuncline(p, pcRel(L->oldpc, p))) /* enter a new line */
+ luaD_hook(L, LUA_HOOKLINE, newline); /* call line hook */
+ }
+ L->oldpc = ci->u.l.savedpc;
+ if (L->status == LUA_YIELD) { /* did hook yield? */
+ if (counthook)
+ L->hookcount = 1; /* undo decrement to zero */
+ ci->u.l.savedpc--; /* undo increment (resume will increment it again) */
+ ci->callstatus |= CIST_HOOKYIELD; /* mark that it yielded */
+ ci->func = L->top - 1; /* protect stack below results */
+ luaD_throw(L, LUA_YIELD);
+ }
+}
+
diff --git a/src/ldebug.h b/src/ldebug.h
index fe39556b..c668e1e4 100644
--- a/src/ldebug.h
+++ b/src/ldebug.h
@@ -1,5 +1,5 @@
/*
-** $Id: ldebug.h,v 2.7 2011/10/07 20:45:19 roberto Exp $
+** $Id: ldebug.h,v 2.10 2013/05/06 17:19:11 roberto Exp $
** Auxiliary functions from Debug Interface module
** See Copyright Notice in lua.h
*/
@@ -23,12 +23,17 @@
LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o,
const char *opname);
-LUAI_FUNC l_noret luaG_concaterror (lua_State *L, StkId p1, StkId p2);
+LUAI_FUNC l_noret luaG_concaterror (lua_State *L, const TValue *p1,
+ const TValue *p2);
LUAI_FUNC l_noret luaG_aritherror (lua_State *L, const TValue *p1,
const TValue *p2);
+LUAI_FUNC l_noret luaG_tointerror (lua_State *L, const TValue *p1,
+ const TValue *p2);
LUAI_FUNC l_noret luaG_ordererror (lua_State *L, const TValue *p1,
const TValue *p2);
LUAI_FUNC l_noret luaG_runerror (lua_State *L, const char *fmt, ...);
LUAI_FUNC l_noret luaG_errormsg (lua_State *L);
+LUAI_FUNC void luaG_traceexec (lua_State *L);
+
#endif
diff --git a/src/ldo.c b/src/ldo.c
index aafa3dca..abf082d4 100644
--- a/src/ldo.c
+++ b/src/ldo.c
@@ -1,5 +1,5 @@
/*
-** $Id: ldo.c,v 2.108 2012/10/01 14:05:04 roberto Exp $
+** $Id: ldo.c,v 2.109 2013/04/19 21:05:04 roberto Exp $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
@@ -260,6 +260,7 @@ static StkId adjust_varargs (lua_State *L, Proto *p, int actual) {
StkId base, fixed;
lua_assert(actual >= nfixargs);
/* move fixed parameters to final position */
+ luaD_checkstack(L, p->maxstacksize); /* check again for new 'base' */
fixed = L->top - actual; /* first fixed argument */
base = L->top; /* final position of first argument */
for (i=0; i<nfixargs; i++) {
@@ -324,12 +325,18 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
case LUA_TLCL: { /* Lua function: prepare its call */
StkId base;
Proto *p = clLvalue(func)->p;
- luaD_checkstack(L, p->maxstacksize);
- func = restorestack(L, funcr);
n = cast_int(L->top - func) - 1; /* number of real arguments */
+ luaD_checkstack(L, p->maxstacksize);
for (; n < p->numparams; n++)
setnilvalue(L->top++); /* complete missing arguments */
- base = (!p->is_vararg) ? func + 1 : adjust_varargs(L, p, n);
+ if (!p->is_vararg) {
+ func = restorestack(L, funcr);
+ base = func + 1;
+ }
+ else {
+ base = adjust_varargs(L, p, n);
+ func = restorestack(L, funcr); /* previous call can change stack */
+ }
ci = next_ci(L); /* now 'enter' new function */
ci->nresults = nresults;
ci->func = func;
diff --git a/src/ldump.c b/src/ldump.c
index d5e6a47c..b3a25624 100644
--- a/src/ldump.c
+++ b/src/ldump.c
@@ -1,5 +1,5 @@
/*
-** $Id: ldump.c,v 2.17 2012/01/23 23:02:10 roberto Exp $
+** $Id: ldump.c,v 2.19 2013/04/26 18:48:35 roberto Exp $
** save precompiled Lua chunks
** See Copyright Notice in lua.h
*/
@@ -52,6 +52,11 @@ static void DumpNumber(lua_Number x, DumpState* D)
DumpVar(x,D);
}
+static void DumpInteger(lua_Integer x, DumpState* D)
+{
+ DumpVar(x,D);
+}
+
static void DumpVector(const void* b, int n, size_t size, DumpState* D)
{
DumpInt(n,D);
@@ -84,18 +89,21 @@ static void DumpConstants(const Proto* f, DumpState* D)
for (i=0; i<n; i++)
{
const TValue* o=&f->k[i];
- DumpChar(ttypenv(o),D);
- switch (ttypenv(o))
+ DumpChar(ttype(o),D);
+ switch (ttype(o))
{
case LUA_TNIL:
break;
case LUA_TBOOLEAN:
DumpChar(bvalue(o),D);
break;
- case LUA_TNUMBER:
- DumpNumber(nvalue(o),D);
+ case LUA_TNUMFLT:
+ DumpNumber(fltvalue(o),D);
+ break;
+ case LUA_TNUMINT:
+ DumpInteger(ivalue(o),D);
break;
- case LUA_TSTRING:
+ case LUA_TSHRSTR: case LUA_TLNGSTR:
DumpString(rawtsvalue(o),D);
break;
default: lua_assert(0);
diff --git a/src/lgc.c b/src/lgc.c
index 535e988a..5e305fb3 100644
--- a/src/lgc.c
+++ b/src/lgc.c
@@ -1,5 +1,5 @@
/*
-** $Id: lgc.c,v 2.140 2013/03/16 21:10:18 roberto Exp $
+** $Id: lgc.c,v 2.141 2013/04/26 18:26:49 roberto Exp $
** Garbage Collector
** See Copyright Notice in lua.h
*/
@@ -493,17 +493,24 @@ static lu_mem traverseLclosure (global_State *g, LClosure *cl) {
static lu_mem traversestack (global_State *g, lua_State *th) {
+ int n = 0;
StkId o = th->stack;
if (o == NULL)
return 1; /* stack not completely built yet */
- for (; o < th->top; o++)
+ for (; o < th->top; o++) /* mark live elements in the stack */
markvalue(g, o);
if (g->gcstate == GCSatomic) { /* final traversal? */
StkId lim = th->stack + th->stacksize; /* real end of stack */
for (; o < lim; o++) /* clear not-marked stack slice */
setnilvalue(o);
}
- return sizeof(lua_State) + sizeof(TValue) * th->stacksize;
+ else { /* count call infos to compute size */
+ CallInfo *ci;
+ for (ci = &th->base_ci; ci != th->ci; ci = ci->next)
+ n++;
+ }
+ return sizeof(lua_State) + sizeof(TValue) * th->stacksize +
+ sizeof(CallInfo) * n;
}
diff --git a/src/liolib.c b/src/liolib.c
index 3f80db19..2c6202af 100644
--- a/src/liolib.c
+++ b/src/liolib.c
@@ -1,17 +1,17 @@
/*
-** $Id: liolib.c,v 2.111 2013/03/21 13:57:27 roberto Exp $
+** $Id: liolib.c,v 2.114 2013/06/07 19:01:35 roberto Exp $
** Standard I/O (and system) library
** See Copyright Notice in lua.h
*/
/*
-** POSIX idiosyncrasy!
** This definition must come before the inclusion of 'stdio.h'; it
** should not affect non-POSIX systems
*/
#if !defined(_FILE_OFFSET_BITS)
-#define _FILE_OFFSET_BITS 64
+#define _LARGEFILE_SOURCE 1
+#define _FILE_OFFSET_BITS 64
#endif
@@ -80,36 +80,37 @@
/*
** {======================================================
-** lua_fseek/lua_ftell: configuration for longer offsets
+** lua_fseek: configuration for longer offsets
** =======================================================
*/
-#if !defined(lua_fseek) /* { */
+#if !defined(lua_fseek) && !defined(LUA_ANSI) /* { */
-#if defined(LUA_USE_POSIX)
+#if defined(LUA_USE_POSIX) /* { */
#define l_fseek(f,o,w) fseeko(f,o,w)
#define l_ftell(f) ftello(f)
#define l_seeknum off_t
#elif defined(LUA_WIN) && !defined(_CRTIMP_TYPEINFO) \
- && defined(_MSC_VER) && (_MSC_VER >= 1400)
+ && defined(_MSC_VER) && (_MSC_VER >= 1400) /* }{ */
/* Windows (but not DDK) and Visual C++ 2005 or higher */
#define l_fseek(f,o,w) _fseeki64(f,o,w)
#define l_ftell(f) _ftelli64(f)
#define l_seeknum __int64
-#else
+#endif /* } */
+#endif /* } */
+
+
+#if !defined(l_fseek) /* default definitions */
#define l_fseek(f,o,w) fseek(f,o,w)
#define l_ftell(f) ftell(f)
#define l_seeknum long
-
#endif
-#endif /* } */
-
/* }====================================================== */
@@ -346,6 +347,19 @@ 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;
+ }
+ else {
+ lua_pushnil(L); /* "result" to be removed */
+ return 0; /* read fails */
+ }
+}
+
+
static int read_number (lua_State *L, FILE *f) {
lua_Number d;
if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) {
@@ -441,6 +455,9 @@ static int g_read (lua_State *L, FILE *f, int first) {
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;
case 'n': /* number */
success = read_number(L, f);
break;
@@ -516,8 +533,10 @@ static int g_write (lua_State *L, FILE *f, int arg) {
for (; nargs--; arg++) {
if (lua_type(L, arg) == LUA_TNUMBER) {
/* optimization: could be done exactly as for strings */
- status = status &&
- fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
+ int len = lua_isinteger(L, arg)
+ ? fprintf(f, LUA_INTEGER_FMT, lua_tointeger(L, arg))
+ : fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg));
+ status = status && (len > 0);
}
else {
size_t l;
diff --git a/src/llex.c b/src/llex.c
index 1a32e348..e1a54c7d 100644
--- a/src/llex.c
+++ b/src/llex.c
@@ -1,5 +1,5 @@
/*
-** $Id: llex.c,v 2.63 2013/03/16 21:10:18 roberto Exp $
+** $Id: llex.c,v 2.67 2013/06/19 14:27:00 roberto Exp $
** Lexical Analyzer
** See Copyright Notice in lua.h
*/
@@ -38,8 +38,8 @@ static const char *const luaX_tokens [] = {
"end", "false", "for", "function", "goto", "if",
"in", "local", "nil", "not", "or", "repeat",
"return", "then", "true", "until", "while",
- "..", "...", "==", ">=", "<=", "~=", "::", "<eof>",
- "<number>", "<name>", "<string>"
+ "//", "..", "...", "==", ">=", "<=", "~=", "::", "<eof>",
+ "<number>", "<number>", "<name>", "<string>"
};
@@ -53,7 +53,7 @@ static void save (LexState *ls, int c) {
Mbuffer *b = ls->buff;
if (luaZ_bufflen(b) + 1 > luaZ_sizebuffer(b)) {
size_t newsize;
- if (luaZ_sizebuffer(b) >= MAX_SIZET/2)
+ if (luaZ_sizebuffer(b) >= MAX_SIZE/2)
lexerror(ls, "lexical element too long", 0);
newsize = luaZ_sizebuffer(b) * 2;
luaZ_resizebuffer(ls->L, b, newsize);
@@ -90,9 +90,8 @@ const char *luaX_token2str (LexState *ls, int token) {
static const char *txtToken (LexState *ls, int token) {
switch (token) {
- case TK_NAME:
- case TK_STRING:
- case TK_NUMBER:
+ case TK_NAME: case TK_STRING:
+ case TK_FLT: case TK_INT:
save(ls, '\0');
return luaO_pushfstring(ls->L, LUA_QS, luaZ_buffer(ls->buff));
default:
@@ -216,7 +215,7 @@ static void trydecpoint (LexState *ls, SemInfo *seminfo) {
if (!buff2d(ls->buff, &seminfo->r)) {
/* format error with correct decimal point: no more options */
buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */
- lexerror(ls, "malformed number", TK_NUMBER);
+ lexerror(ls, "malformed number", TK_FLT);
}
}
@@ -224,9 +223,10 @@ 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.
+** will reject ill-formed numerals. 'isf' means the numeral is not
+** an integer (it has a dot or an exponent).
*/
-static void read_numeral (LexState *ls, SemInfo *seminfo) {
+static int read_numeral (LexState *ls, SemInfo *seminfo, int isf) {
const char *expo = "Ee";
int first = ls->current;
lua_assert(lisdigit(ls->current));
@@ -234,16 +234,31 @@ static void read_numeral (LexState *ls, SemInfo *seminfo) {
if (first == '0' && check_next(ls, "Xx")) /* hexadecimal? */
expo = "Pp";
for (;;) {
- if (check_next(ls, expo)) /* exponent part? */
+ if (check_next(ls, expo)) { /* exponent part? */
check_next(ls, "+-"); /* optional exponent sign */
- if (lisxdigit(ls->current) || ls->current == '.')
+ isf = 1;
+ }
+ if (lisxdigit(ls->current))
+ save_and_next(ls);
+ else if (ls->current == '.') {
save_and_next(ls);
- else break;
+ isf = 1;
+ }
+ else break;
}
save(ls, '\0');
- 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 */
+ if (!isf) {
+ if (!luaO_str2int(luaZ_buffer(ls->buff), luaZ_bufflen(ls->buff) - 1,
+ &seminfo->i))
+ lexerror(ls, "malformed number", TK_INT);
+ 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 */
+ return TK_FLT;
+ }
}
@@ -450,6 +465,11 @@ static int llex (LexState *ls, SemInfo *seminfo) {
if (ls->current != '=') return '>';
else { next(ls); return TK_GE; }
}
+ case '/': {
+ next(ls);
+ if (ls->current != '/') return '/';
+ else { next(ls); return TK_IDIV; }
+ }
case '~': {
next(ls);
if (ls->current != '=') return '~';
@@ -472,12 +492,11 @@ static int llex (LexState *ls, SemInfo *seminfo) {
else return TK_CONCAT; /* '..' */
}
else if (!lisdigit(ls->current)) return '.';
- /* else go through */
+ else return read_numeral(ls, seminfo, 1);
}
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': {
- read_numeral(ls, seminfo);
- return TK_NUMBER;
+ return read_numeral(ls, seminfo, 0);
}
case EOZ: {
return TK_EOS;
diff --git a/src/llex.h b/src/llex.h
index 9ca8a299..7cba9906 100644
--- a/src/llex.h
+++ b/src/llex.h
@@ -1,5 +1,5 @@
/*
-** $Id: llex.h,v 1.72 2011/11/30 12:43:51 roberto Exp $
+** $Id: llex.h,v 1.74 2013/04/26 13:07:53 roberto Exp $
** Lexical Analyzer
** See Copyright Notice in lua.h
*/
@@ -26,8 +26,9 @@ enum RESERVED {
TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,
TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,
/* other terminal symbols */
- TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_DBCOLON, TK_EOS,
- TK_NUMBER, TK_NAME, TK_STRING
+ TK_IDIV, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE,
+ TK_DBCOLON, TK_EOS,
+ TK_FLT, TK_INT, TK_NAME, TK_STRING
};
/* number of reserved words */
@@ -36,6 +37,7 @@ enum RESERVED {
typedef union {
lua_Number r;
+ lua_Integer i;
TString *ts;
} SemInfo; /* semantics information */
diff --git a/src/llimits.h b/src/llimits.h
index 1b8c79bd..c4416f89 100644
--- a/src/llimits.h
+++ b/src/llimits.h
@@ -1,5 +1,5 @@
/*
-** $Id: llimits.h,v 1.103 2013/02/20 14:08:56 roberto Exp $
+** $Id: llimits.h,v 1.108 2013/06/19 14:27:00 roberto Exp $
** Limits, basic types, and some other `installation-dependent' definitions
** See Copyright Notice in lua.h
*/
@@ -27,8 +27,14 @@ typedef LUAI_MEM l_mem;
typedef unsigned char lu_byte;
+/* maximum value for size_t */
#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_LUMEM ((lu_mem)(~(lu_mem)0)-2)
#define MAX_LMEM ((l_mem) ((MAX_LUMEM >> 1) - 2))
@@ -36,6 +42,12 @@ typedef unsigned char lu_byte;
#define MAX_INT (INT_MAX-2) /* maximum value of an int (-2 for safety) */
+
+/* minimum and maximum values for lua_Integer */
+#define MAX_INTEGER ((lua_Integer)(~(lua_Unsigned)0 >> 1))
+#define MIN_INTEGER (~MAX_INTEGER)
+
+
/*
** conversion of pointer to integer
** this is for hashing only; there is no problem if the integer
@@ -96,6 +108,8 @@ 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))
/*
@@ -190,103 +204,6 @@ typedef lu_int32 Instruction;
#define luai_userstateyield(L,n) ((void)L)
#endif
-/*
-** lua_number2int is a macro to convert lua_Number to int.
-** lua_number2integer is a macro to convert lua_Number to lua_Integer.
-** lua_number2unsigned is a macro to convert a lua_Number to a lua_Unsigned.
-** lua_unsigned2number is a macro to convert a lua_Unsigned to a lua_Number.
-** luai_hashnum is a macro to hash a lua_Number value into an integer.
-** The hash must be deterministic and give reasonable values for
-** both small and large values (outside the range of integers).
-*/
-
-#if defined(MS_ASMTRICK) || defined(LUA_MSASMTRICK) /* { */
-/* trick with Microsoft assembler for X86 */
-
-#define lua_number2int(i,n) __asm {__asm fld n __asm fistp i}
-#define lua_number2integer(i,n) lua_number2int(i, n)
-#define lua_number2unsigned(i,n) \
- {__int64 l; __asm {__asm fld n __asm fistp l} i = (unsigned int)l;}
-
-
-#elif defined(LUA_IEEE754TRICK) /* }{ */
-/* the next trick should work on any machine using IEEE754 with
- a 32-bit int type */
-
-union luai_Cast { double l_d; LUA_INT32 l_p[2]; };
-
-#if !defined(LUA_IEEEENDIAN) /* { */
-#define LUAI_EXTRAIEEE \
- static const union luai_Cast ieeeendian = {-(33.0 + 6755399441055744.0)};
-#define LUA_IEEEENDIANLOC (ieeeendian.l_p[1] == 33)
-#else
-#define LUA_IEEEENDIANLOC LUA_IEEEENDIAN
-#define LUAI_EXTRAIEEE /* empty */
-#endif /* } */
-
-#define lua_number2int32(i,n,t) \
- { LUAI_EXTRAIEEE \
- volatile union luai_Cast u; u.l_d = (n) + 6755399441055744.0; \
- (i) = (t)u.l_p[LUA_IEEEENDIANLOC]; }
-
-#define luai_hashnum(i,n) \
- { volatile union luai_Cast u; u.l_d = (n) + 1.0; /* avoid -0 */ \
- (i) = u.l_p[0]; (i) += u.l_p[1]; } /* add double bits for his hash */
-
-#define lua_number2int(i,n) lua_number2int32(i, n, int)
-#define lua_number2unsigned(i,n) lua_number2int32(i, n, lua_Unsigned)
-
-/* the trick can be expanded to lua_Integer when it is a 32-bit value */
-#if defined(LUA_IEEELL)
-#define lua_number2integer(i,n) lua_number2int32(i, n, lua_Integer)
-#endif
-
-#endif /* } */
-
-
-/* the following definitions always work, but may be slow */
-
-#if !defined(lua_number2int)
-#define lua_number2int(i,n) ((i)=(int)(n))
-#endif
-
-#if !defined(lua_number2integer)
-#define lua_number2integer(i,n) ((i)=(lua_Integer)(n))
-#endif
-
-#if !defined(lua_number2unsigned) /* { */
-/* the following definition assures proper modulo behavior */
-#if defined(LUA_NUMBER_DOUBLE) || defined(LUA_NUMBER_FLOAT)
-#include <math.h>
-#define SUPUNSIGNED ((lua_Number)(~(lua_Unsigned)0) + 1)
-#define lua_number2unsigned(i,n) \
- ((i)=(lua_Unsigned)((n) - floor((n)/SUPUNSIGNED)*SUPUNSIGNED))
-#else
-#define lua_number2unsigned(i,n) ((i)=(lua_Unsigned)(n))
-#endif
-#endif /* } */
-
-
-#if !defined(lua_unsigned2number)
-/* on several machines, coercion from unsigned to double is slow,
- so it may be worth to avoid */
-#define lua_unsigned2number(u) \
- (((u) <= (lua_Unsigned)INT_MAX) ? (lua_Number)(int)(u) : (lua_Number)(u))
-#endif
-
-
-
-#if defined(ltable_c) && !defined(luai_hashnum)
-
-#include <float.h>
-#include <math.h>
-
-#define luai_hashnum(i,n) { int e; \
- n = l_mathop(frexp)(n, &e) * (lua_Number)(INT_MAX - DBL_MAX_EXP); \
- lua_number2int(i, n); i += e; }
-
-#endif
-
/*
diff --git a/src/lmathlib.c b/src/lmathlib.c
index a49f1fd2..f26b05ca 100644
--- a/src/lmathlib.c
+++ b/src/lmathlib.c
@@ -1,5 +1,5 @@
/*
-** $Id: lmathlib.c,v 1.83 2013/03/07 18:21:32 roberto Exp $
+** $Id: lmathlib.c,v 1.90 2013/07/03 17:23:19 roberto Exp $
** Standard mathematical library
** See Copyright Notice in lua.h
*/
@@ -22,7 +22,6 @@
#define RADIANS_PER_DEGREE ((lua_Number)(PI/180.0))
-
static int math_abs (lua_State *L) {
lua_pushnumber(L, l_mathop(fabs)(luaL_checknumber(L, 1)));
return 1;
@@ -89,20 +88,40 @@ static int math_floor (lua_State *L) {
return 1;
}
+static int math_ifloor (lua_State *L) {
+ int valid;
+ lua_Integer n = lua_tointegerx(L, 1, &valid);
+ if (valid)
+ lua_pushinteger(L, n);
+ else {
+ luaL_checktype(L, 1, LUA_TNUMBER); /* error if not a number */
+ lua_pushnil(L); /* number with invalid integer value */
+ }
+ return 1;
+}
+
static int math_fmod (lua_State *L) {
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 ip;
- lua_Number fp = l_mathop(modf)(luaL_checknumber(L, 1), &ip);
+ 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);
- lua_pushnumber(L, fp);
+ /* fractionary part (test handles inf/-inf) */
+ lua_pushnumber(L, (n == ip) ? 0.0 : (n - ip));
return 2;
}
+
static int math_sqrt (lua_State *L) {
lua_pushnumber(L, l_mathop(sqrt)(luaL_checknumber(L, 1)));
return 1;
@@ -199,26 +218,28 @@ 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;
switch (lua_gettop(L)) { /* check number of arguments */
case 0: { /* no arguments */
lua_pushnumber(L, r); /* Number between 0 and 1 */
- break;
+ return 1;
}
case 1: { /* only upper limit */
- lua_Number u = luaL_checknumber(L, 1);
- luaL_argcheck(L, (lua_Number)1.0 <= u, 1, "interval is empty");
- lua_pushnumber(L, l_mathop(floor)(r*u) + (lua_Number)(1.0)); /* [1, u] */
+ low = 1;
+ up = luaL_checkinteger(L, 1);
break;
}
case 2: { /* lower and upper limits */
- lua_Number l = luaL_checknumber(L, 1);
- lua_Number u = luaL_checknumber(L, 2);
- luaL_argcheck(L, l <= u, 2, "interval is empty");
- lua_pushnumber(L, l_mathop(floor)(r*(u-l+1)) + l); /* [l, u] */
+ low = luaL_checkinteger(L, 1);
+ up = luaL_checkinteger(L, 2);
break;
}
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);
return 1;
}
@@ -230,6 +251,13 @@ static int math_randomseed (lua_State *L) {
}
+static int math_isfloat (lua_State *L) {
+ luaL_checkany(L, 1);
+ lua_pushboolean(L, (lua_type(L, 1) == LUA_TNUMBER && !lua_isinteger(L, 1)));
+ return 1;
+}
+
+
static const luaL_Reg mathlib[] = {
{"abs", math_abs},
{"acos", math_acos},
@@ -242,8 +270,10 @@ static const luaL_Reg mathlib[] = {
{"deg", math_deg},
{"exp", math_exp},
{"floor", math_floor},
+ {"ifloor", math_ifloor},
{"fmod", math_fmod},
{"frexp", math_frexp},
+ {"isfloat", math_isfloat},
{"ldexp", math_ldexp},
#if defined(LUA_COMPAT_LOG10)
{"log10", math_log10},
diff --git a/src/lobject.c b/src/lobject.c
index c152785a..edb0efeb 100644
--- a/src/lobject.c
+++ b/src/lobject.c
@@ -1,5 +1,5 @@
/*
-** $Id: lobject.c,v 2.58 2013/02/20 14:08:56 roberto Exp $
+** $Id: lobject.c,v 2.67 2013/06/25 18:58:32 roberto Exp $
** Some generic functions over Lua objects
** See Copyright Notice in lua.h
*/
@@ -70,7 +70,21 @@ int luaO_ceillog2 (unsigned int x) {
}
-lua_Number luaO_arith (int op, lua_Number v1, lua_Number v2) {
+static lua_Integer intarith (lua_State *L, int op, lua_Integer v1,
+ lua_Integer v2) {
+ switch (op) {
+ case LUA_OPADD: return intop(+, v1, v2);
+ 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(v1, v2);
+ case LUA_OPUNM: return -v1;
+ default: lua_assert(0); return 0;
+ }
+}
+
+
+static lua_Number numarith (int op, lua_Number v1, lua_Number v2) {
switch (op) {
case LUA_OPADD: return luai_numadd(NULL, v1, v2);
case LUA_OPSUB: return luai_numsub(NULL, v1, v2);
@@ -84,17 +98,41 @@ lua_Number luaO_arith (int op, lua_Number v1, lua_Number v2) {
}
+void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2,
+ TValue *res) {
+ if (op == LUA_OPIDIV) { /* operates only on integers */
+ lua_Integer i1; lua_Integer i2;
+ if (tointeger(p1, &i1) && tointeger(p2, &i2)) {
+ setivalue(res, luaV_div(L, i1, i2));
+ return;
+ }
+ /* else go to the end */
+ }
+ else { /* other operations */
+ lua_Number n1; lua_Number n2;
+ if (ttisinteger(p1) && ttisinteger(p2) && op != LUA_OPDIV &&
+ (op != LUA_OPPOW || ivalue(p2) >= 0)) {
+ setivalue(res, intarith(L, op, ivalue(p1), ivalue(p2)));
+ return;
+ }
+ else if (tonumber(p1, &n1) && tonumber(p2, &n2)) {
+ setnvalue(res, numarith(op, n1, n2));
+ return;
+ }
+ /* else go to the end */
+ }
+ /* could not perform raw operation; try metmethod */
+ lua_assert(L != NULL); /* cannot fail when folding (compile time) */
+ luaT_trybinTM(L, p1, p2, res, cast(TMS, op - LUA_OPADD + TM_ADD));
+}
+
+
int luaO_hexavalue (int c) {
if (lisdigit(c)) return c - '0';
else return ltolower(c) - 'a' + 10;
}
-#if !defined(lua_strx2number)
-
-#include <math.h>
-
-
static int isneg (const char **s) {
if (**s == '-') { (*s)++; return 1; }
else if (**s == '+') (*s)++;
@@ -102,52 +140,81 @@ static int isneg (const char **s) {
}
-static lua_Number readhexa (const char **s, lua_Number r, int *count) {
- for (; lisxdigit(cast_uchar(**s)); (*s)++) { /* read integer part */
- r = (r * cast_num(16.0)) + cast_num(luaO_hexavalue(cast_uchar(**s)));
- (*count)++;
- }
- return r;
-}
+/*
+** lua_strx2number converts an hexadecimal numeric string to a number.
+** In C99, 'strtod' does both conversions. C89, however, has no function
+** to convert floating hexadecimal strings to numbers. For these
+** systems, you can leave 'lua_strx2number' undefined and Lua will
+** provide its own implementation.
+*/
+#if defined(LUA_USE_STRTODHEX)
+#define lua_strx2number(s,p) lua_str2number(s,p)
+#endif
+
+
+#if !defined(lua_strx2number)
+
+#include <math.h>
+/* maximum number of significant digits to read (to avoid overflows
+ even with single floats) */
+#define MAXSIGDIG 30
+
/*
** convert an hexadecimal numeric string to a number, following
** C99 specification for 'strtod'
*/
static lua_Number lua_strx2number (const char *s, char **endptr) {
- lua_Number r = 0.0;
- int e = 0, i = 0;
+ lua_Number r = 0.0; /* result (accumulator) */
+ int sigdig = 0; /* number of significant digits */
+ int nosigdig = 0; /* number of non-significant digits */
+ int e = 0; /* exponent correction */
int neg = 0; /* 1 if number is negative */
+ int dot = 0; /* true after seen a dot */
*endptr = cast(char *, s); /* nothing is valid yet */
while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */
neg = isneg(&s); /* check signal */
if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */
return 0.0; /* invalid format (no '0x') */
- s += 2; /* skip '0x' */
- r = readhexa(&s, r, &i); /* read integer part */
- if (*s == '.') {
- s++; /* skip dot */
- r = readhexa(&s, r, &e); /* read fractional part */
+ for (s += 2; ; s++) { /* skip '0x' and read numeral */
+ if (*s == '.') {
+ if (dot) break; /* second dot? stop loop */
+ else dot = 1;
+ }
+ else if (lisxdigit(cast_uchar(*s))) {
+ if (sigdig == 0 && *s == '0') { /* non-significant zero? */
+ nosigdig++;
+ if (dot) e--; /* zero after dot? correct exponent */
+ }
+ else {
+ if (++sigdig <= MAXSIGDIG) { /* can read it without overflow? */
+ r = (r * cast_num(16.0)) + luaO_hexavalue(cast_uchar(*s));
+ if (dot) e--; /* decimal digit */
+ }
+ else /* too many digits; ignore */
+ if (!dot) e++; /* still count it for exponent */
+ }
+ }
+ else break; /* neither a dot nor a digit */
}
- if (i == 0 && e == 0)
- return 0.0; /* invalid format (no digit) */
- e *= -4; /* each fractional digit divides value by 2^-4 */
+ if (nosigdig + sigdig == 0) /* no digits? */
+ return 0.0; /* invalid format */
*endptr = cast(char *, s); /* valid up to here */
+ e *= 4; /* each digit multiplies/divides value by 2^4 */
if (*s == 'p' || *s == 'P') { /* exponent part? */
- int exp1 = 0;
- int neg1;
+ int exp1 = 0; /* exponent value */
+ int neg1; /* exponent signal */
s++; /* skip 'p' */
neg1 = isneg(&s); /* signal */
if (!lisdigit(cast_uchar(*s)))
- goto ret; /* must have at least one digit */
+ return 0.0; /* invalid; must have at least one digit */
while (lisdigit(cast_uchar(*s))) /* read exponent */
exp1 = exp1 * 10 + *(s++) - '0';
if (neg1) exp1 = -exp1;
e += exp1;
+ *endptr = cast(char *, s); /* valid up to here */
}
- *endptr = cast(char *, s); /* valid up to here */
- ret:
if (neg) r = -r;
return l_mathop(ldexp)(r, e);
}
@@ -169,6 +236,36 @@ int luaO_str2d (const char *s, size_t len, lua_Number *result) {
}
+int luaO_str2int (const char *s, size_t len, lua_Integer *result) {
+ const char *ends = s + len;
+ lua_Unsigned a = 0;
+ int empty = 1;
+ int neg;
+ while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */
+ neg = isneg(&s);
+ if (s[0] == '0' &&
+ (s[1] == 'x' || s[1] == 'X')) { /* hexa? */
+ s += 2; /* skip '0x' */
+ for (; lisxdigit(cast_uchar(*s)); s++) {
+ a = a * 16 + luaO_hexavalue(cast_uchar(*s));
+ empty = 0;
+ }
+ }
+ else { /* decimal */
+ for (; lisdigit(cast_uchar(*s)); s++) {
+ a = a * 10 + luaO_hexavalue(cast_uchar(*s));
+ empty = 0;
+ }
+ }
+ while (lisspace(cast_uchar(*s))) s++; /* skip trailing spaces */
+ if (empty || s != ends) return 0; /* something wrong in the numeral */
+ else {
+ if (neg) *result = -cast(lua_Integer, a);
+ else *result = cast(lua_Integer, a);
+ return 1;
+ }
+}
+
static void pushstr (lua_State *L, const char *str, size_t l) {
setsvalue2s(L, L->top++, luaS_newlstr(L, str, l));
@@ -197,7 +294,11 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
break;
}
case 'd': {
- setnvalue(L->top++, cast_num(va_arg(argp, int)));
+ setivalue(L->top++, cast_int(va_arg(argp, int)));
+ break;
+ }
+ case 'I': {
+ setivalue(L->top++, cast_integer(va_arg(argp, lua_Integer)));
break;
}
case 'f': {
diff --git a/src/lobject.h b/src/lobject.h
index dd23b914..55b4e240 100644
--- a/src/lobject.h
+++ b/src/lobject.h
@@ -1,5 +1,5 @@
/*
-** $Id: lobject.h,v 2.71 2012/09/11 18:21:44 roberto Exp $
+** $Id: lobject.h,v 2.78 2013/05/14 15:59:04 roberto Exp $
** Type definitions for Lua objects
** See Copyright Notice in lua.h
*/
@@ -57,6 +57,11 @@
#define LUA_TLNGSTR (LUA_TSTRING | (1 << 4)) /* long strings */
+/* Variant tags for numbers */
+#define LUA_TNUMFLT (LUA_TNUMBER | (0 << 4)) /* float numbers */
+#define LUA_TNUMINT (LUA_TNUMBER | (1 << 4)) /* integer numbers */
+
+
/* Bit mark for collectable types */
#define BIT_ISCOLLECTABLE (1 << 6)
@@ -92,8 +97,6 @@ typedef struct GCheader {
typedef union Value Value;
-#define numfield lua_Number n; /* numbers */
-
/*
@@ -111,7 +114,6 @@ typedef struct lua_TValue TValue;
#define val_(o) ((o)->value_)
-#define num_(o) (val_(o).n)
/* raw type tag of a TValue */
@@ -124,13 +126,15 @@ typedef struct lua_TValue TValue;
#define ttype(o) (rttype(o) & 0x3F)
/* type tag of a TValue with no variants (bits 0-3) */
-#define ttypenv(o) (novariant(rttype(o)))
+#define ttnov(o) (novariant(rttype(o)))
/* Macros to test type */
#define checktag(o,t) (rttype(o) == (t))
-#define checktype(o,t) (ttypenv(o) == (t))
-#define ttisnumber(o) checktag((o), LUA_TNUMBER)
+#define checktype(o,t) (ttnov(o) == (t))
+#define ttisnumber(o) checktype((o), LUA_TNUMBER)
+#define ttisfloat(o) checktag((o), LUA_TNUMFLT)
+#define ttisinteger(o) checktag((o), LUA_TNUMINT)
#define ttisnil(o) checktag((o), LUA_TNIL)
#define ttisboolean(o) checktag((o), LUA_TBOOLEAN)
#define ttislightuserdata(o) checktag((o), LUA_TLIGHTUSERDATA)
@@ -147,10 +151,10 @@ typedef struct lua_TValue TValue;
#define ttisthread(o) checktag((o), ctb(LUA_TTHREAD))
#define ttisdeadkey(o) checktag((o), LUA_TDEADKEY)
-#define ttisequal(o1,o2) (rttype(o1) == rttype(o2))
/* Macros to access values */
-#define nvalue(o) check_exp(ttisnumber(o), num_(o))
+#define ivalue(o) check_exp(ttisinteger(o), val_(o).i)
+#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)
@@ -185,7 +189,10 @@ typedef struct lua_TValue TValue;
#define settt_(o,t) ((o)->tt_=(t))
#define setnvalue(obj,x) \
- { TValue *io=(obj); num_(io)=(x); settt_(io, LUA_TNUMBER); }
+ { TValue *io=(obj); val_(io).n=(x); settt_(io, LUA_TNUMFLT); }
+
+#define setivalue(obj,x) \
+ { TValue *io=(obj); val_(io).i=(x); settt_(io, LUA_TNUMINT); }
#define setnilvalue(obj) settt_(obj, LUA_TNIL)
@@ -267,115 +274,6 @@ typedef struct lua_TValue TValue;
#define luai_checknum(L,o,c) { /* empty */ }
-/*
-** {======================================================
-** NaN Trick
-** =======================================================
-*/
-#if defined(LUA_NANTRICK)
-
-/*
-** numbers are represented in the 'd_' field. All other values have the
-** value (NNMARK | tag) in 'tt__'. A number with such pattern would be
-** a "signaled NaN", which is never generated by regular operations by
-** the CPU (nor by 'strtod')
-*/
-
-/* allows for external implementation for part of the trick */
-#if !defined(NNMARK) /* { */
-
-
-#if !defined(LUA_IEEEENDIAN)
-#error option 'LUA_NANTRICK' needs 'LUA_IEEEENDIAN'
-#endif
-
-
-#define NNMARK 0x7FF7A500
-#define NNMASK 0x7FFFFF00
-
-#undef TValuefields
-#undef NILCONSTANT
-
-#if (LUA_IEEEENDIAN == 0) /* { */
-
-/* little endian */
-#define TValuefields \
- union { struct { Value v__; int tt__; } i; double d__; } u
-#define NILCONSTANT {{{NULL}, tag2tt(LUA_TNIL)}}
-/* field-access macros */
-#define v_(o) ((o)->u.i.v__)
-#define d_(o) ((o)->u.d__)
-#define tt_(o) ((o)->u.i.tt__)
-
-#else /* }{ */
-
-/* big endian */
-#define TValuefields \
- union { struct { int tt__; Value v__; } i; double d__; } u
-#define NILCONSTANT {{tag2tt(LUA_TNIL), {NULL}}}
-/* field-access macros */
-#define v_(o) ((o)->u.i.v__)
-#define d_(o) ((o)->u.d__)
-#define tt_(o) ((o)->u.i.tt__)
-
-#endif /* } */
-
-#endif /* } */
-
-
-/* correspondence with standard representation */
-#undef val_
-#define val_(o) v_(o)
-#undef num_
-#define num_(o) d_(o)
-
-
-#undef numfield
-#define numfield /* no such field; numbers are the entire struct */
-
-/* basic check to distinguish numbers from non-numbers */
-#undef ttisnumber
-#define ttisnumber(o) ((tt_(o) & NNMASK) != NNMARK)
-
-#define tag2tt(t) (NNMARK | (t))
-
-#undef rttype
-#define rttype(o) (ttisnumber(o) ? LUA_TNUMBER : tt_(o) & 0xff)
-
-#undef settt_
-#define settt_(o,t) (tt_(o) = tag2tt(t))
-
-#undef setnvalue
-#define setnvalue(obj,x) \
- { TValue *io_=(obj); num_(io_)=(x); lua_assert(ttisnumber(io_)); }
-
-#undef setobj
-#define setobj(L,obj1,obj2) \
- { const TValue *o2_=(obj2); TValue *o1_=(obj1); \
- o1_->u = o2_->u; \
- checkliveness(G(L),o1_); }
-
-
-/*
-** these redefinitions are not mandatory, but these forms are more efficient
-*/
-
-#undef checktag
-#undef checktype
-#define checktag(o,t) (tt_(o) == tag2tt(t))
-#define checktype(o,t) (ctb(tt_(o) | VARBITS) == ctb(tag2tt(t) | VARBITS))
-
-#undef ttisequal
-#define ttisequal(o1,o2) \
- (ttisnumber(o1) ? ttisnumber(o2) : (tt_(o1) == tt_(o2)))
-
-
-#undef luai_checknum
-#define luai_checknum(L,o,c) { if (!ttisnumber(o)) c; }
-
-#endif
-/* }====================================================== */
-
/*
@@ -390,7 +288,8 @@ union Value {
void *p; /* light userdata */
int b; /* booleans */
lua_CFunction f; /* light C functions */
- numfield /* numbers */
+ lua_Integer i; /* integer numbers */
+ lua_Number n; /* float numbers */
};
@@ -594,8 +493,10 @@ LUAI_DDEC const TValue luaO_nilobject_;
LUAI_FUNC int luaO_int2fb (unsigned int x);
LUAI_FUNC int luaO_fb2int (int x);
LUAI_FUNC int luaO_ceillog2 (unsigned int x);
-LUAI_FUNC lua_Number luaO_arith (int op, lua_Number v1, lua_Number v2);
+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 int luaO_hexavalue (int c);
LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt,
va_list argp);
diff --git a/src/lopcodes.c b/src/lopcodes.c
index ef736927..0bd7a3e8 100644
--- a/src/lopcodes.c
+++ b/src/lopcodes.c
@@ -1,5 +1,5 @@
/*
-** $Id: lopcodes.c,v 1.49 2012/05/14 13:34:18 roberto Exp $
+** $Id: lopcodes.c,v 1.50 2013/04/26 13:07:53 roberto Exp $
** Opcodes for Lua virtual machine
** See Copyright Notice in lua.h
*/
@@ -32,6 +32,7 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = {
"SUB",
"MUL",
"DIV",
+ "IDIV",
"MOD",
"POW",
"UNM",
@@ -80,6 +81,7 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */
,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */
,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_IDIV */
,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */
,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */
,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */
diff --git a/src/lopcodes.h b/src/lopcodes.h
index 07d2b3f3..6c27b27a 100644
--- a/src/lopcodes.h
+++ b/src/lopcodes.h
@@ -1,5 +1,5 @@
/*
-** $Id: lopcodes.h,v 1.142 2011/07/15 12:50:29 roberto Exp $
+** $Id: lopcodes.h,v 1.143 2013/04/26 13:07:53 roberto Exp $
** Opcodes for Lua virtual machine
** See Copyright Notice in lua.h
*/
@@ -188,6 +188,7 @@ OP_ADD,/* A B C R(A) := RK(B) + RK(C) */
OP_SUB,/* A B C R(A) := RK(B) - RK(C) */
OP_MUL,/* A B C R(A) := RK(B) * RK(C) */
OP_DIV,/* A B C R(A) := RK(B) / RK(C) */
+OP_IDIV,/* A B C R(A) := RK(B) // RK(C) */
OP_MOD,/* A B C R(A) := RK(B) % RK(C) */
OP_POW,/* A B C R(A) := RK(B) ^ RK(C) */
OP_UNM,/* A B R(A) := -R(B) */
diff --git a/src/loslib.c b/src/loslib.c
index 5170fd0d..6d59bc39 100644
--- a/src/loslib.c
+++ b/src/loslib.c
@@ -1,5 +1,5 @@
/*
-** $Id: loslib.c,v 1.40 2012/10/19 15:54:02 roberto Exp $
+** $Id: loslib.c,v 1.41 2013/05/14 15:57:11 roberto Exp $
** Standard Operating System library
** See Copyright Notice in lua.h
*/
@@ -194,7 +194,7 @@ static const char *checkoption (lua_State *L, const char *conv, char *buff) {
static int os_date (lua_State *L) {
const char *s = luaL_optstring(L, 1, "%c");
- time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL));
+ time_t t = luaL_opt(L, (time_t)luaL_checkinteger, 2, time(NULL));
struct tm tmr, *stm;
if (*s == '!') { /* UTC? */
stm = l_gmtime(&t, &tmr);
@@ -258,14 +258,14 @@ static int os_time (lua_State *L) {
if (t == (time_t)(-1))
lua_pushnil(L);
else
- lua_pushnumber(L, (lua_Number)t);
+ lua_pushinteger(L, t);
return 1;
}
static int os_difftime (lua_State *L) {
- lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)),
- (time_t)(luaL_optnumber(L, 2, 0))));
+ lua_pushnumber(L, difftime((time_t)(luaL_checkinteger(L, 1)),
+ (time_t)(luaL_optinteger(L, 2, 0))));
return 1;
}
diff --git a/src/lparser.c b/src/lparser.c
index d8f5b4ff..e8a6b8ef 100644
--- a/src/lparser.c
+++ b/src/lparser.c
@@ -1,5 +1,5 @@
/*
-** $Id: lparser.c,v 2.130 2013/02/06 13:37:39 roberto Exp $
+** $Id: lparser.c,v 2.133 2013/04/26 13:07:53 roberto Exp $
** Lua Parser
** See Copyright Notice in lua.h
*/
@@ -935,14 +935,19 @@ static void suffixedexp (LexState *ls, expdesc *v) {
static void simpleexp (LexState *ls, expdesc *v) {
- /* simpleexp -> NUMBER | STRING | NIL | TRUE | FALSE | ... |
+ /* simpleexp -> FLT | INT | STRING | NIL | TRUE | FALSE | ... |
constructor | FUNCTION body | suffixedexp */
switch (ls->t.token) {
- case TK_NUMBER: {
- init_exp(v, VKNUM, 0);
+ case TK_FLT: {
+ init_exp(v, VKFLT, 0);
v->u.nval = ls->t.seminfo.r;
break;
}
+ case TK_INT: {
+ init_exp(v, VKINT, 0);
+ v->u.ival = ls->t.seminfo.i;
+ break;
+ }
case TK_STRING: {
codestring(ls, v, ls->t.seminfo.ts);
break;
@@ -1000,6 +1005,7 @@ static BinOpr getbinopr (int op) {
case '-': return OPR_SUB;
case '*': return OPR_MUL;
case '/': return OPR_DIV;
+ case TK_IDIV: return OPR_IDIV;
case '%': return OPR_MOD;
case '^': return OPR_POW;
case TK_CONCAT: return OPR_CONCAT;
@@ -1020,7 +1026,8 @@ static const struct {
lu_byte left; /* left priority for each binary operator */
lu_byte right; /* right priority */
} priority[] = { /* ORDER OPR */
- {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, /* `+' `-' `*' `/' `%' */
+ {6, 6}, {6, 6}, /* '+' '-' */
+ {7, 7}, {7, 7}, {7, 7}, {7, 7}, /* '*' '/' '//' '%' */
{10, 9}, {5, 4}, /* ^, .. (right associative) */
{3, 3}, {3, 3}, {3, 3}, /* ==, <, <= */
{3, 3}, {3, 3}, {3, 3}, /* ~=, >, >= */
@@ -1321,7 +1328,7 @@ static void fornum (LexState *ls, TString *varname, int line) {
if (testnext(ls, ','))
exp1(ls); /* optional step */
else { /* default step = 1 */
- luaK_codek(fs, fs->freereg, luaK_numberK(fs, 1));
+ luaK_codek(fs, fs->freereg, luaK_intK(fs, 1));
luaK_reserveregs(fs, 1);
}
forbody(ls, base, line, 1, 1);
diff --git a/src/lparser.h b/src/lparser.h
index 301167d4..147d3367 100644
--- a/src/lparser.h
+++ b/src/lparser.h
@@ -1,5 +1,5 @@
/*
-** $Id: lparser.h,v 1.70 2012/05/08 13:53:33 roberto Exp $
+** $Id: lparser.h,v 1.71 2013/04/16 18:46:28 roberto Exp $
** Lua Parser
** See Copyright Notice in lua.h
*/
@@ -22,7 +22,8 @@ typedef enum {
VTRUE,
VFALSE,
VK, /* info = index of constant in `k' */
- VKNUM, /* nval = numerical value */
+ VKFLT, /* nval = numerical float value */
+ VKINT, /* nval = numerical integer value */
VNONRELOC, /* info = result register */
VLOCAL, /* info = local register */
VUPVAL, /* info = index of upvalue in 'upvalues' */
@@ -46,7 +47,8 @@ typedef struct expdesc {
lu_byte vt; /* whether 't' is register (VLOCAL) or upvalue (VUPVAL) */
} ind;
int info; /* for generic use */
- lua_Number nval; /* for VKNUM */
+ lua_Number nval; /* for VKFLT */
+ lua_Integer ival; /* for VKINT */
} u;
int t; /* patch list of `exit when true' */
int f; /* patch list of `exit when false' */
diff --git a/src/lstring.c b/src/lstring.c
index 8b5af0b2..d9781365 100644
--- a/src/lstring.c
+++ b/src/lstring.c
@@ -1,5 +1,5 @@
/*
-** $Id: lstring.c,v 2.26 2013/01/08 13:50:10 roberto Exp $
+** $Id: lstring.c,v 2.27 2013/06/19 14:27:00 roberto Exp $
** String table (keeps all strings handled by Lua)
** See Copyright Notice in lua.h
*/
@@ -157,7 +157,7 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
if (l <= LUAI_MAXSHORTLEN) /* short string? */
return internshrstr(L, str, l);
else {
- if (l + 1 > (MAX_SIZET - sizeof(TString))/sizeof(char))
+ if (l + 1 > (MAX_SIZE - sizeof(TString))/sizeof(char))
luaM_toobig(L);
return createstrobj(L, str, l, LUA_TLNGSTR, G(L)->seed, NULL);
}
@@ -174,7 +174,7 @@ TString *luaS_new (lua_State *L, const char *str) {
Udata *luaS_newudata (lua_State *L, size_t s, Table *e) {
Udata *u;
- if (s > MAX_SIZET - sizeof(Udata))
+ if (s > MAX_SIZE - sizeof(Udata))
luaM_toobig(L);
u = &luaC_newobj(L, LUA_TUSERDATA, sizeof(Udata) + s, NULL, 0)->u;
u->uv.len = s;
diff --git a/src/lstrlib.c b/src/lstrlib.c
index fcc61c9a..28acab83 100644
--- a/src/lstrlib.c
+++ b/src/lstrlib.c
@@ -1,11 +1,12 @@
/*
-** $Id: lstrlib.c,v 1.178 2012/08/14 18:12:34 roberto Exp $
+** $Id: lstrlib.c,v 1.182 2013/06/20 15:06:51 roberto Exp $
** Standard library for string operations and pattern-matching
** See Copyright Notice in lua.h
*/
#include <ctype.h>
+#include <limits.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
@@ -43,20 +44,20 @@ static int str_len (lua_State *L) {
/* translate a relative string position: negative means back from end */
-static size_t posrelat (ptrdiff_t pos, size_t len) {
- if (pos >= 0) return (size_t)pos;
+static lua_Integer posrelat (lua_Integer pos, size_t len) {
+ if (pos >= 0) return pos;
else if (0u - (size_t)pos > len) return 0;
- else return len - ((size_t)-pos) + 1;
+ else return (lua_Integer)len + pos + 1;
}
static int str_sub (lua_State *L) {
size_t l;
const char *s = luaL_checklstring(L, 1, &l);
- size_t start = posrelat(luaL_checkinteger(L, 2), l);
- size_t end = posrelat(luaL_optinteger(L, 3, -1), l);
+ lua_Integer start = posrelat(luaL_checkinteger(L, 2), l);
+ lua_Integer end = posrelat(luaL_optinteger(L, 3, -1), l);
if (start < 1) start = 1;
- if (end > l) end = l;
+ if (end > (lua_Integer)l) end = l;
if (start <= end)
lua_pushlstring(L, s + start - 1, end - start + 1);
else lua_pushliteral(L, "");
@@ -102,13 +103,17 @@ static int str_upper (lua_State *L) {
}
-/* reasonable limit to avoid arithmetic overflow */
-#define MAXSIZE ((~(size_t)0) >> 1)
+/* reasonable limit to avoid arithmetic overflow and strings too big */
+#if INT_MAX / 2 <= 0x10000000
+#define MAXSIZE ((size_t)(INT_MAX / 2))
+#else
+#define MAXSIZE ((size_t)0x10000000)
+#endif
static int str_rep (lua_State *L) {
size_t l, lsep;
const char *s = luaL_checklstring(L, 1, &l);
- int n = luaL_checkint(L, 2);
+ lua_Integer n = luaL_checkinteger(L, 2);
const char *sep = luaL_optlstring(L, 3, "", &lsep);
if (n <= 0) lua_pushliteral(L, "");
else if (l + lsep < l || l + lsep >= MAXSIZE / n) /* may overflow? */
@@ -133,14 +138,14 @@ static int str_rep (lua_State *L) {
static int str_byte (lua_State *L) {
size_t l;
const char *s = luaL_checklstring(L, 1, &l);
- size_t posi = posrelat(luaL_optinteger(L, 2, 1), l);
- size_t pose = posrelat(luaL_optinteger(L, 3, posi), l);
+ lua_Integer posi = posrelat(luaL_optinteger(L, 2, 1), l);
+ lua_Integer pose = posrelat(luaL_optinteger(L, 3, posi), l);
int n, i;
if (posi < 1) posi = 1;
- if (pose > l) pose = l;
+ if (pose > (lua_Integer)l) pose = l;
if (posi > pose) return 0; /* empty interval; return no values */
n = (int)(pose - posi + 1);
- if (posi + n <= pose) /* (size_t -> int) overflow? */
+ if (posi + n <= pose) /* arithmetic overflow? */
return luaL_error(L, "string slice too long");
luaL_checkstack(L, n, "string slice too long");
for (i=0; i<n; i++)
@@ -155,7 +160,7 @@ static int str_char (lua_State *L) {
luaL_Buffer b;
char *p = luaL_buffinitsize(L, &b, n);
for (i=1; i<=n; i++) {
- int c = luaL_checkint(L, i);
+ lua_Integer c = luaL_checkinteger(L, i);
luaL_argcheck(L, uchar(c) == c, i, "value out of range");
p[i - 1] = uchar(c);
}
@@ -164,9 +169,9 @@ static int str_char (lua_State *L) {
}
-static int writer (lua_State *L, const void* b, size_t size, void* B) {
+static int writer (lua_State *L, const void *b, size_t size, void *B) {
(void)L;
- luaL_addlstring((luaL_Buffer*) B, (const char *)b, size);
+ luaL_addlstring((luaL_Buffer *) B, (const char *)b, size);
return 0;
}
@@ -578,9 +583,9 @@ static int str_find_aux (lua_State *L, int find) {
size_t ls, lp;
const char *s = luaL_checklstring(L, 1, &ls);
const char *p = luaL_checklstring(L, 2, &lp);
- size_t init = posrelat(luaL_optinteger(L, 3, 1), ls);
+ lua_Integer init = posrelat(luaL_optinteger(L, 3, 1), ls);
if (init < 1) init = 1;
- else if (init > ls + 1) { /* start after string's end? */
+ else if (init > (lua_Integer)ls + 1) { /* start after string's end? */
lua_pushnil(L); /* cannot find anything */
return 1;
}
@@ -786,48 +791,17 @@ static int str_gsub (lua_State *L) {
** =======================================================
*/
-/*
-** LUA_INTFRMLEN is the length modifier for integer conversions in
-** 'string.format'; LUA_INTFRM_T is the integer type corresponding to
-** the previous length
-*/
-#if !defined(LUA_INTFRMLEN) /* { */
-#if defined(LUA_USE_LONGLONG)
-
-#define LUA_INTFRMLEN "ll"
-#define LUA_INTFRM_T long long
-
-#else
-
-#define LUA_INTFRMLEN "l"
-#define LUA_INTFRM_T long
-
-#endif
-#endif /* } */
-
-
-/*
-** LUA_FLTFRMLEN is the length modifier for float conversions in
-** 'string.format'; LUA_FLTFRM_T is the float type corresponding to
-** the previous length
-*/
-#if !defined(LUA_FLTFRMLEN)
-
-#define LUA_FLTFRMLEN ""
-#define LUA_FLTFRM_T double
-
-#endif
-
-
/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */
#define MAX_ITEM 512
+
/* valid flags in a format specification */
#define FLAGS "-+ #0"
+
/*
-** maximum size of each format specification (such as '%-099.99d')
-** (+10 accounts for %99.99x plus margin of error)
+** maximum size of each format specification (such as "%-099.99d")
+** (+2 for length modifiers; +10 accounts for %99.99x plus margin of error)
*/
-#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10)
+#define MAX_FORMAT (sizeof(FLAGS) + 2 + 10)
static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
@@ -914,24 +888,11 @@ static int str_format (lua_State *L) {
nb = sprintf(buff, form, luaL_checkint(L, arg));
break;
}
- case 'd': case 'i': {
- lua_Number n = luaL_checknumber(L, arg);
- LUA_INTFRM_T ni = (LUA_INTFRM_T)n;
- lua_Number diff = n - (lua_Number)ni;
- luaL_argcheck(L, -1 < diff && diff < 1, arg,
- "not a number in proper range");
- addlenmod(form, LUA_INTFRMLEN);
- nb = sprintf(buff, form, ni);
- break;
- }
+ case 'd': case 'i':
case 'o': case 'u': case 'x': case 'X': {
- lua_Number n = luaL_checknumber(L, arg);
- unsigned LUA_INTFRM_T ni = (unsigned LUA_INTFRM_T)n;
- lua_Number diff = n - (lua_Number)ni;
- luaL_argcheck(L, -1 < diff && diff < 1, arg,
- "not a non-negative number in proper range");
- addlenmod(form, LUA_INTFRMLEN);
- nb = sprintf(buff, form, ni);
+ lua_Integer n = luaL_checkinteger(L, arg);
+ addlenmod(form, LUA_INTEGER_FRMLEN);
+ nb = sprintf(buff, form, n);
break;
}
case 'e': case 'E': case 'f':
@@ -939,8 +900,8 @@ static int str_format (lua_State *L) {
case 'a': case 'A':
#endif
case 'g': case 'G': {
- addlenmod(form, LUA_FLTFRMLEN);
- nb = sprintf(buff, form, (LUA_FLTFRM_T)luaL_checknumber(L, arg));
+ addlenmod(form, LUA_NUMBER_FRMLEN);
+ nb = sprintf(buff, form, luaL_checknumber(L, arg));
break;
}
case 'q': {
diff --git a/src/ltable.c b/src/ltable.c
index 420391fc..4b39a8de 100644
--- a/src/ltable.c
+++ b/src/ltable.c
@@ -1,5 +1,5 @@
/*
-** $Id: ltable.c,v 2.72 2012/09/11 19:37:16 roberto Exp $
+** $Id: ltable.c,v 2.78 2013/06/20 15:02:49 roberto Exp $
** Lua tables (hash)
** See Copyright Notice in lua.h
*/
@@ -18,6 +18,8 @@
** Hence even when the load factor reaches 100%, performance remains good.
*/
+#include <float.h>
+#include <math.h>
#include <string.h>
#define ltable_c
@@ -52,6 +54,7 @@
#define hashstr(t,str) hashpow2(t, (str)->tsv.hash)
#define hashboolean(t,p) hashpow2(t, p)
+#define hashint(t,i) hashpow2(t, i)
/*
@@ -64,6 +67,12 @@
#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)
@@ -75,11 +84,12 @@ static const Node dummynode_ = {
/*
-** hash for lua_Numbers
+** hash for floating-point numbers
*/
-static Node *hashnum (const Table *t, lua_Number n) {
+static Node *hashfloat (const Table *t, lua_Number n) {
int i;
- luai_hashnum(i, n);
+ n = l_mathop(frexp)(n, &i) * cast_num(INT_MAX - DBL_MAX_EXP);
+ i += cast_int(n);
if (i < 0) {
if (cast(unsigned int, i) == 0u - i) /* use unsigned to avoid overflows */
i = 0; /* handle INT_MIN */
@@ -96,8 +106,12 @@ static Node *hashnum (const Table *t, lua_Number n) {
*/
static Node *mainposition (const Table *t, const TValue *key) {
switch (ttype(key)) {
- case LUA_TNUMBER:
- return hashnum(t, nvalue(key));
+ case LUA_TNUMINT:
+ return hashint(t, ivalue(key));
+ case LUA_TNUMFLT:
+ return hashfloat(t, fltvalue(key));
+ case LUA_TSHRSTR:
+ return hashstr(t, rawtsvalue(key));
case LUA_TLNGSTR: {
TString *s = rawtsvalue(key);
if (s->tsv.extra == 0) { /* no hash? */
@@ -106,8 +120,6 @@ static Node *mainposition (const Table *t, const TValue *key) {
}
return hashstr(t, rawtsvalue(key));
}
- case LUA_TSHRSTR:
- return hashstr(t, rawtsvalue(key));
case LUA_TBOOLEAN:
return hashboolean(t, bvalue(key));
case LUA_TLIGHTUSERDATA:
@@ -125,12 +137,10 @@ static Node *mainposition (const Table *t, const TValue *key) {
** the array part of the table, -1 otherwise.
*/
static int arrayindex (const TValue *key) {
- if (ttisnumber(key)) {
- lua_Number n = nvalue(key);
- int k;
- lua_number2int(k, n);
- if (luai_numeq(cast_num(k), n))
- return k;
+ if (ttisinteger(key)) {
+ lua_Integer k = ivalue(key);
+ if (0 < k && k <= MAXASIZE) /* is `key' an appropriate array index? */
+ return cast_int(k);
}
return -1; /* `key' did not match some condition */
}
@@ -170,7 +180,7 @@ int luaH_next (lua_State *L, Table *t, StkId key) {
int i = findindex(L, t, key); /* find original element */
for (i++; i < t->sizearray; i++) { /* try first array part */
if (!ttisnil(&t->array[i])) { /* a non-nil value? */
- setnvalue(key, cast_num(i+1));
+ setivalue(key, i + 1);
setobj2s(L, key+1, &t->array[i]);
return 1;
}
@@ -217,7 +227,7 @@ static int computesizes (int nums[], int *narray) {
static int countint (const TValue *key, int *nums) {
int k = arrayindex(key);
- if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */
+ if (k > 0) { /* is `key' an appropriate array index? */
nums[luaO_ceillog2(k)]++; /* count as such */
return 1;
}
@@ -404,9 +414,18 @@ static Node *getfreepos (Table *t) {
*/
TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
Node *mp;
+ TValue aux;
if (ttisnil(key)) luaG_runerror(L, "table index is nil");
- else if (ttisnumber(key) && luai_numisnan(L, nvalue(key)))
- luaG_runerror(L, "table index is NaN");
+ else if (ttisfloat(key)) {
+ lua_Number n = fltvalue(key);
+ lua_Integer k;
+ if (luai_numisnan(L, n))
+ luaG_runerror(L, "table index is NaN");
+ if (numisinteger(n, &k)) { /* index is int? */
+ setivalue(&aux, k);
+ key = &aux; /* insert it as an integer */
+ }
+ }
mp = mainposition(t, key);
if (!ttisnil(gval(mp)) || isdummy(mp)) { /* main position is taken? */
Node *othern;
@@ -443,15 +462,14 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
/*
** search function for integers
*/
-const TValue *luaH_getint (Table *t, int key) {
+const TValue *luaH_getint (Table *t, lua_Integer key) {
/* (1 <= key && key <= t->sizearray) */
- if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray))
- return &t->array[key-1];
+ if (cast_unsigned(key - 1) < cast_unsigned(t->sizearray))
+ return &t->array[key - 1];
else {
- lua_Number nk = cast_num(key);
- Node *n = hashnum(t, nk);
+ Node *n = hashint(t, key);
do { /* check whether `key' is somewhere in the chain */
- if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk))
+ if (ttisinteger(gkey(n)) && ivalue(gkey(n)) == key)
return gval(n); /* that's it */
else n = gnext(n);
} while (n);
@@ -481,12 +499,11 @@ const TValue *luaH_getstr (Table *t, TString *key) {
const TValue *luaH_get (Table *t, const TValue *key) {
switch (ttype(key)) {
case LUA_TSHRSTR: return luaH_getstr(t, rawtsvalue(key));
+ case LUA_TNUMINT: return luaH_getint(t, ivalue(key));
case LUA_TNIL: return luaO_nilobject;
- case LUA_TNUMBER: {
- int k;
- lua_Number n = nvalue(key);
- lua_number2int(k, n);
- if (luai_numeq(cast_num(k), n)) /* index is int? */
+ case LUA_TNUMFLT: {
+ lua_Integer k;
+ if (numisinteger(fltvalue(key), &k)) /* index is int? */
return luaH_getint(t, k); /* use specialized version */
/* else go through */
}
@@ -515,14 +532,14 @@ TValue *luaH_set (lua_State *L, Table *t, const TValue *key) {
}
-void luaH_setint (lua_State *L, Table *t, int key, TValue *value) {
+void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value) {
const TValue *p = luaH_getint(t, key);
TValue *cell;
if (p != luaO_nilobject)
cell = cast(TValue *, p);
else {
TValue k;
- setnvalue(&k, cast_num(key));
+ setivalue(&k, key);
cell = luaH_newkey(L, t, &k);
}
setobj2t(L, cell, value);
@@ -535,13 +552,13 @@ static int unbound_search (Table *t, unsigned int j) {
/* find `i' and `j' such that i is present and j is not */
while (!ttisnil(luaH_getint(t, j))) {
i = j;
- j *= 2;
- if (j > cast(unsigned int, MAX_INT)) { /* overflow? */
+ if (j > cast(unsigned int, MAX_INT)/2) { /* overflow? */
/* table was built with bad purposes: resort to linear search */
i = 1;
while (!ttisnil(luaH_getint(t, i))) i++;
return i - 1;
}
+ j *= 2;
}
/* now do a binary search between them */
while (j - i > 1) {
diff --git a/src/ltable.h b/src/ltable.h
index 2f6f5c2d..5a65b52e 100644
--- a/src/ltable.h
+++ b/src/ltable.h
@@ -1,5 +1,5 @@
/*
-** $Id: ltable.h,v 2.16 2011/08/17 20:26:47 roberto Exp $
+** $Id: ltable.h,v 2.17 2013/04/26 15:39:25 roberto Exp $
** Lua tables (hash)
** See Copyright Notice in lua.h
*/
@@ -18,8 +18,9 @@
#define invalidateTMcache(t) ((t)->flags = 0)
-LUAI_FUNC const TValue *luaH_getint (Table *t, int key);
-LUAI_FUNC void luaH_setint (lua_State *L, Table *t, int key, TValue *value);
+LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key);
+LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key,
+ TValue *value);
LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key);
LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key);
LUAI_FUNC TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key);
diff --git a/src/ltm.c b/src/ltm.c
index e70006dd..3d1126a1 100644
--- a/src/ltm.c
+++ b/src/ltm.c
@@ -1,5 +1,5 @@
/*
-** $Id: ltm.c,v 2.14 2011/06/02 19:31:40 roberto Exp $
+** $Id: ltm.c,v 2.20 2013/05/06 17:19:11 roberto Exp $
** Tag methods
** See Copyright Notice in lua.h
*/
@@ -12,11 +12,14 @@
#include "lua.h"
+#include "ldebug.h"
+#include "ldo.h"
#include "lobject.h"
#include "lstate.h"
#include "lstring.h"
#include "ltable.h"
#include "ltm.h"
+#include "lvm.h"
static const char udatatypename[] = "userdata";
@@ -33,7 +36,7 @@ void luaT_init (lua_State *L) {
static const char *const luaT_eventname[] = { /* ORDER TM */
"__index", "__newindex",
"__gc", "__mode", "__len", "__eq",
- "__add", "__sub", "__mul", "__div", "__mod",
+ "__add", "__sub", "__mul", "__div", "__idiv", "__mod",
"__pow", "__unm", "__lt", "__le",
"__concat", "__call"
};
@@ -62,7 +65,7 @@ const TValue *luaT_gettm (Table *events, TMS event, TString *ename) {
const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) {
Table *mt;
- switch (ttypenv(o)) {
+ switch (ttnov(o)) {
case LUA_TTABLE:
mt = hvalue(o)->metatable;
break;
@@ -70,8 +73,71 @@ const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) {
mt = uvalue(o)->metatable;
break;
default:
- mt = G(L)->mt[ttypenv(o)];
+ mt = G(L)->mt[ttnov(o)];
}
return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject);
}
+
+void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1,
+ const TValue *p2, TValue *p3, int hasres) {
+ ptrdiff_t result = savestack(L, p3);
+ setobj2s(L, L->top++, f); /* push function */
+ setobj2s(L, L->top++, p1); /* 1st argument */
+ setobj2s(L, L->top++, p2); /* 2nd argument */
+ if (!hasres) /* no result? 'p3' is third argument */
+ setobj2s(L, L->top++, p3); /* 3rd argument */
+ /* metamethod may yield only when called from Lua code */
+ luaD_call(L, L->top - (4 - hasres), hasres, isLua(L->ci));
+ if (hasres) { /* if has result, move it to its place */
+ p3 = restorestack(L, result);
+ setobjs2s(L, p3, --L->top);
+ }
+}
+
+
+int luaT_callbinTM (lua_State *L, const TValue *p1, const TValue *p2,
+ StkId res, TMS event) {
+ const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */
+ if (ttisnil(tm))
+ tm = luaT_gettmbyobj(L, p2, event); /* try second operand */
+ if (ttisnil(tm)) return 0;
+ luaT_callTM(L, tm, p1, p2, res, 1);
+ return 1;
+}
+
+
+void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2,
+ StkId res, TMS event) {
+ if (!luaT_callbinTM(L, p1, p2, res, event)) {
+ if (event == TM_CONCAT)
+ luaG_concaterror(L, p1, p2);
+ else if (event == TM_IDIV && ttisnumber(p1) && ttisnumber(p2))
+ luaG_tointerror(L, p1, p2);
+ else
+ luaG_aritherror(L, p1, 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))
+ return -1; /* no metamethod */
+ else
+ return !l_isfalse(L->top);
+}
+
diff --git a/src/ltm.h b/src/ltm.h
index 89bdc19a..206823ef 100644
--- a/src/ltm.h
+++ b/src/ltm.h
@@ -1,5 +1,5 @@
/*
-** $Id: ltm.h,v 2.11 2011/02/28 17:32:10 roberto Exp $
+** $Id: ltm.h,v 2.16 2013/04/29 16:56:50 roberto Exp $
** Tag methods
** See Copyright Notice in lua.h
*/
@@ -26,6 +26,7 @@ typedef enum {
TM_SUB,
TM_MUL,
TM_DIV,
+ TM_IDIV,
TM_MOD,
TM_POW,
TM_UNM,
@@ -44,7 +45,7 @@ typedef enum {
#define fasttm(l,et,e) gfasttm(G(l), et, e)
#define ttypename(x) luaT_typenames_[(x) + 1]
-#define objtypename(x) ttypename(ttypenv(x))
+#define objtypename(x) ttypename(ttnov(x))
LUAI_DDEC const char *const luaT_typenames_[LUA_TOTALTAGS];
@@ -54,4 +55,16 @@ LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o,
TMS event);
LUAI_FUNC void luaT_init (lua_State *L);
+LUAI_FUNC void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1,
+ const TValue *p2, TValue *p3, int hasres);
+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);
+
+
+
#endif
diff --git a/src/lua.h b/src/lua.h
index eb0482b8..4fef6fee 100644
--- a/src/lua.h
+++ b/src/lua.h
@@ -1,5 +1,5 @@
/*
-** $Id: lua.h,v 1.285 2013/03/15 13:04:22 roberto Exp $
+** $Id: lua.h,v 1.292 2013/07/05 14:29:51 roberto Exp $
** Lua - A Scripting Language
** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
** See Copyright Notice at the end of this file
@@ -17,9 +17,9 @@
#define LUA_VERSION_MAJOR "5"
-#define LUA_VERSION_MINOR "2"
-#define LUA_VERSION_NUM 502
-#define LUA_VERSION_RELEASE "2"
+#define LUA_VERSION_MINOR "3"
+#define LUA_VERSION_NUM 503
+#define LUA_VERSION_RELEASE "0 (work1)"
#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE
@@ -61,7 +61,7 @@ typedef int (*lua_CFunction) (lua_State *L);
*/
typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz);
-typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud);
+typedef int (*lua_Writer) (lua_State *L, const void *p, size_t sz, void *ud);
/*
@@ -161,6 +161,7 @@ LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n);
LUA_API int (lua_isnumber) (lua_State *L, int idx);
LUA_API int (lua_isstring) (lua_State *L, int idx);
LUA_API int (lua_iscfunction) (lua_State *L, int idx);
+LUA_API int (lua_isinteger) (lua_State *L, int idx);
LUA_API int (lua_isuserdata) (lua_State *L, int idx);
LUA_API int (lua_type) (lua_State *L, int idx);
LUA_API const char *(lua_typename) (lua_State *L, int tp);
@@ -185,9 +186,10 @@ LUA_API const void *(lua_topointer) (lua_State *L, int idx);
#define LUA_OPSUB 1
#define LUA_OPMUL 2
#define LUA_OPDIV 3
-#define LUA_OPMOD 4
-#define LUA_OPPOW 5
-#define LUA_OPUNM 6
+#define LUA_OPIDIV 4
+#define LUA_OPMOD 5
+#define LUA_OPPOW 6
+#define LUA_OPUNM 7
LUA_API void (lua_arith) (lua_State *L, int op);
@@ -224,7 +226,7 @@ LUA_API void (lua_getglobal) (lua_State *L, const char *var);
LUA_API void (lua_gettable) (lua_State *L, int idx);
LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k);
LUA_API void (lua_rawget) (lua_State *L, int idx);
-LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n);
+LUA_API void (lua_rawgeti) (lua_State *L, int idx, lua_Integer n);
LUA_API void (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);
@@ -239,7 +241,7 @@ LUA_API void (lua_setglobal) (lua_State *L, const char *var);
LUA_API void (lua_settable) (lua_State *L, int idx);
LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k);
LUA_API void (lua_rawset) (lua_State *L, int idx);
-LUA_API void (lua_rawseti) (lua_State *L, int idx, int n);
+LUA_API void (lua_rawseti) (lua_State *L, int idx, lua_Integer n);
LUA_API void (lua_rawsetp) (lua_State *L, int idx, const void *p);
LUA_API int (lua_setmetatable) (lua_State *L, int objindex);
LUA_API void (lua_setuservalue) (lua_State *L, int idx);
@@ -305,6 +307,8 @@ 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 lua_Alloc (lua_getallocf) (lua_State *L, void **ud);
LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud);
diff --git a/src/luac.c b/src/luac.c
index 5081836d..43c3d0d6 100644
--- a/src/luac.c
+++ b/src/luac.c
@@ -202,8 +202,10 @@ int main(int argc, char* argv[])
return EXIT_SUCCESS;
}
+#define nvalue(x) 0
+#define ttypenv(x) ttnov(x)
/*
-** $Id: print.c,v 1.68 2011/09/30 10:21:20 lhf Exp $
+** $Id: print.c,v 1.69 2013/07/04 01:03:46 lhf Exp $
** print bytecodes
** See Copyright Notice in lua.h
*/
@@ -251,7 +253,7 @@ static void PrintString(const TString* ts)
static void PrintConstant(const Proto* f, int i)
{
const TValue* o=&f->k[i];
- switch (ttype(o))
+ switch (ttypenv(o))
{
case LUA_TNIL:
printf("nil");
diff --git a/src/luaconf.h b/src/luaconf.h
index df802c95..71d02561 100644
--- a/src/luaconf.h
+++ b/src/luaconf.h
@@ -1,5 +1,5 @@
/*
-** $Id: luaconf.h,v 1.176 2013/03/16 21:10:18 roberto Exp $
+** $Id: luaconf.h,v 1.185 2013/06/25 19:04:40 roberto Exp $
** Configuration file for Lua
** See Copyright Notice in lua.h
*/
@@ -376,64 +376,112 @@
/*
** {==================================================================
-@@ LUA_NUMBER is the type of numbers in Lua.
-** CHANGE the following definitions only if you want to build Lua
-** with a number type different from double. You may also need to
-** change lua_number2int & lua_number2integer.
+** The following 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.
** ===================================================================
*/
-#define LUA_NUMBER_DOUBLE
-#define LUA_NUMBER double
+/*
+@@ LUA_INTSIZE defines size for Lua integer: 1=int, 2=long, 3=long long
+@@ LUA_FLOATSIZE defines size for Lua float: 1=float, 2=double, 3=long double
+** Default is long long + double
+*/
+#define LUA_INTSIZE 3
+#define LUA_FLOATSIZE 2
+
/*
+@@ LUA_NUMBER is the floating-point type used by Lua.
+**
@@ LUAI_UACNUMBER is the result of an 'usual argument conversion'
-@* over a 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 floats to a string.
+**
+@@ l_mathop allows the addition of an 'l' or 'f' to all math operations
+**
+@@ lua_str2number converts a decimal numeric string to a number.
*/
+
+#if LUA_FLOATSIZE == 1 /* { single float */
+
+#define LUA_NUMBER float
+
#define LUAI_UACNUMBER double
+#define LUA_NUMBER_FRMLEN ""
+#define LUA_NUMBER_SCAN "%f"
+#define LUA_NUMBER_FMT "%.7g"
-/*
-@@ LUA_NUMBER_SCAN is the format for reading numbers.
-@@ LUA_NUMBER_FMT is the format for writing numbers.
-@@ lua_number2str converts a number to a string.
-@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion.
-*/
+#define l_mathop(op) op##f
+
+#define lua_str2number(s,p) strtof((s), (p))
+
+
+#elif LUA_FLOATSIZE == 3 /* }{ long double */
+
+#define LUA_NUMBER long double
+
+#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
+
+#define lua_str2number(s,p) strtold((s), (p))
+
+#else /* }{ default: double */
+
+#define LUA_NUMBER double
+
+#define LUAI_UACNUMBER double
+
+#define LUA_NUMBER_FRMLEN ""
#define LUA_NUMBER_SCAN "%lf"
#define LUA_NUMBER_FMT "%.14g"
-#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n))
-#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */
+#define l_mathop(op) op
-/*
-@@ l_mathop allows the addition of an 'l' or 'f' to all math operations
-*/
-#define l_mathop(x) (x)
+#define lua_str2number(s,p) strtod((s), (p))
+#endif /* } */
-/*
-@@ lua_str2number converts a decimal numeric string to a number.
-@@ lua_strx2number converts an hexadecimal numeric string to a number.
-** In C99, 'strtod' does both conversions. C89, however, has no function
-** to convert floating hexadecimal strings to numbers. For these
-** systems, you can leave 'lua_strx2number' undefined and Lua will
-** provide its own implementation.
-*/
-#define lua_str2number(s,p) strtod((s), (p))
-#if defined(LUA_USE_STRTODHEX)
-#define lua_strx2number(s,p) strtod((s), (p))
+#if defined(LUA_ANSI)
+/* C89 does not support 'opf' variants for math functions */
+#undef l_mathop
+#define l_mathop(op) (lua_Number)op
+#endif
+
+
+#if defined(LUA_ANSI) || defined(_WIN32)
+/* C89 and Windows do not support 'strtof'... */
+#undef lua_str2number
+#define lua_str2number(s,p) ((lua_Number)strtod((s), (p)))
#endif
+#define l_floor(x) (l_mathop(floor)(x))
+
+#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n))
+
+
/*
@@ The luai_num* macros define the primitive operations over 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) ((a) - l_mathop(floor)((a)/(b))*(b))
+#define luai_nummod(L,a,b) ((a) - l_floor((a)/(b))*(b))
#define luai_numpow(L,a,b) (l_mathop(pow)(a,b))
#endif
@@ -453,85 +501,39 @@
/*
-@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger.
-** CHANGE that if ptrdiff_t is not adequate on your machine. (On most
-** machines, ptrdiff_t gives a good choice between int or long.)
-*/
-#define LUA_INTEGER ptrdiff_t
-
-/*
-@@ LUA_UNSIGNED is the integral type used by lua_pushunsigned/lua_tounsigned.
-** It must have at least 32 bits.
-*/
-#define LUA_UNSIGNED unsigned LUA_INT32
-
-
-
-/*
-** Some tricks with doubles
-*/
-
-#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) /* { */
-/*
-** The next definitions activate some tricks to speed up the
-** conversion from doubles to integer types, mainly to LUA_UNSIGNED.
+@@ LUA_INTEGER is the integer type used by Lua.
**
-@@ LUA_MSASMTRICK uses Microsoft assembler to avoid clashes with a
-** DirectX idiosyncrasy.
+@@ LUA_UNSIGNED is the unsigned version of LUA_INTEGER.
**
-@@ LUA_IEEE754TRICK uses a trick that should work on any machine
-** using IEEE754 with a 32-bit integer type.
-**
-@@ LUA_IEEELL extends the trick to LUA_INTEGER; should only be
-** defined when LUA_INTEGER is a 32-bit integer.
-**
-@@ LUA_IEEEENDIAN is the endianness of doubles in your machine
-** (0 for little endian, 1 for big endian); if not defined, Lua will
-** check it dynamically for LUA_IEEE754TRICK (but not for LUA_NANTRICK).
-**
-@@ LUA_NANTRICK controls the use of a trick to pack all types into
-** a single double value, using NaN values to represent non-number
-** values. The trick only works on 32-bit machines (ints and pointers
-** are 32-bit values) with numbers represented as IEEE 754-2008 doubles
-** with conventional endianess (12345678 or 87654321), in CPUs that do
-** not produce signaling NaN values (all NaNs are quiet).
+@@ 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_integer2str converts an integer to a string.
*/
-/* Microsoft compiler on a Pentium (32 bit) ? */
-#if defined(LUA_WIN) && defined(_MSC_VER) && defined(_M_IX86) /* { */
-
-#define LUA_MSASMTRICK
-#define LUA_IEEEENDIAN 0
-#define LUA_NANTRICK
+#if LUA_INTSIZE == 1 /* { int */
+#define LUA_INTEGER int
+#define LUA_INTEGER_FRMLEN ""
-/* pentium 32 bits? */
-#elif defined(__i386__) || defined(__i386) || defined(__X86__) /* }{ */
+#elif LUA_INTSIZE == 2 /* }{ long */
-#define LUA_IEEE754TRICK
-#define LUA_IEEELL
-#define LUA_IEEEENDIAN 0
-#define LUA_NANTRICK
+#define LUA_INTEGER long
+#define LUA_INTEGER_FRMLEN "l"
-/* pentium 64 bits? */
-#elif defined(__x86_64) /* }{ */
+#else /* }{ default: long long */
-#define LUA_IEEE754TRICK
-#define LUA_IEEEENDIAN 0
+#define LUA_INTEGER long long
+#define LUA_INTEGER_FRMLEN "ll"
-#elif defined(__POWERPC__) || defined(__ppc__) /* }{ */
+#endif /* } */
-#define LUA_IEEE754TRICK
-#define LUA_IEEEENDIAN 1
-#else /* }{ */
+#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))
-/* assume IEEE754 and a 32-bit integer type */
-#define LUA_IEEE754TRICK
-
-#endif /* } */
-
-#endif /* } */
+#define LUA_UNSIGNED unsigned LUA_INTEGER
/* }================================================================== */
@@ -547,5 +549,7 @@
+
+
#endif
diff --git a/src/lundump.c b/src/lundump.c
index 54de011a..38b04e42 100644
--- a/src/lundump.c
+++ b/src/lundump.c
@@ -1,5 +1,5 @@
/*
-** $Id: lundump.c,v 2.22 2012/05/08 13:53:33 roberto Exp $
+** $Id: lundump.c,v 2.23 2013/04/26 18:48:35 roberto Exp $
** load precompiled Lua chunks
** See Copyright Notice in lua.h
*/
@@ -69,6 +69,13 @@ static lua_Number LoadNumber(LoadState* S)
return x;
}
+static lua_Integer LoadInteger(LoadState* S)
+{
+ lua_Integer x;
+ LoadVar(S,x);
+ return x;
+}
+
static TString* LoadString(LoadState* S)
{
size_t size;
@@ -112,10 +119,13 @@ static void LoadConstants(LoadState* S, Proto* f)
case LUA_TBOOLEAN:
setbvalue(o,LoadChar(S));
break;
- case LUA_TNUMBER:
+ case LUA_TNUMFLT:
setnvalue(o,LoadNumber(S));
break;
- case LUA_TSTRING:
+ case LUA_TNUMINT:
+ setivalue(o,LoadInteger(S));
+ break;
+ case LUA_TSHRSTR: case LUA_TLNGSTR:
setsvalue2n(S->L,o,LoadString(S));
break;
default: lua_assert(0);
diff --git a/src/lvm.c b/src/lvm.c
index 657d5c45..0a41482c 100644
--- a/src/lvm.c
+++ b/src/lvm.c
@@ -1,5 +1,5 @@
/*
-** $Id: lvm.c,v 2.155 2013/03/16 21:10:18 roberto Exp $
+** $Id: lvm.c,v 2.175 2013/06/20 15:02:49 roberto Exp $
** Lua virtual machine
** See Copyright Notice in lua.h
*/
@@ -32,15 +32,18 @@
#define MAXTAGLOOP 100
-const TValue *luaV_tonumber (const TValue *obj, TValue *n) {
- lua_Number num;
- if (ttisnumber(obj)) return obj;
- if (ttisstring(obj) && luaO_str2d(svalue(obj), tsvalue(obj)->len, &num)) {
- setnvalue(n, num);
- return n;
+/* maximum length of the conversion of a number to a string */
+#define MAXNUMBER2STR 50
+
+
+int luaV_tonumber_ (const TValue *obj, lua_Number *n) {
+ lua_assert(!ttisfloat(obj));
+ if (ttisinteger(obj)) {
+ *n = cast_num(ivalue(obj));
+ return 1;
}
else
- return NULL;
+ return (ttisstring(obj) && luaO_str2d(svalue(obj), tsvalue(obj)->len, n));
}
@@ -48,62 +51,51 @@ int luaV_tostring (lua_State *L, StkId obj) {
if (!ttisnumber(obj))
return 0;
else {
- char s[LUAI_MAXNUMBER2STR];
- lua_Number n = nvalue(obj);
- int l = lua_number2str(s, n);
- setsvalue2s(L, obj, luaS_newlstr(L, s, l));
+ char buff[MAXNUMBER2STR];
+ size_t len;
+ if (ttisinteger(obj))
+ len = lua_integer2str(buff, ivalue(obj));
+ else {
+ len = lua_number2str(buff, fltvalue(obj));
+ if (strspn(buff, "-0123456789") == len) { /* look like an integer? */
+ buff[len++] = '.'; /* add a '.0' */
+ buff[len++] = '0';
+ buff[len] = '\0';
+ }
+ }
+ setsvalue2s(L, obj, luaS_newlstr(L, buff, len));
return 1;
}
}
-static void traceexec (lua_State *L) {
- CallInfo *ci = L->ci;
- lu_byte mask = L->hookmask;
- int counthook = ((mask & LUA_MASKCOUNT) && L->hookcount == 0);
- if (counthook)
- resethookcount(L); /* reset count */
- if (ci->callstatus & CIST_HOOKYIELD) { /* called hook last time? */
- ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */
- return; /* do not call hook again (VM yielded, so it did not move) */
- }
- if (counthook)
- luaD_hook(L, LUA_HOOKCOUNT, -1); /* call count hook */
- if (mask & LUA_MASKLINE) {
- Proto *p = ci_func(ci)->p;
- int npc = pcRel(ci->u.l.savedpc, p);
- int newline = getfuncline(p, npc);
- if (npc == 0 || /* call linehook when enter a new function, */
- ci->u.l.savedpc <= L->oldpc || /* when jump back (loop), or when */
- newline != getfuncline(p, pcRel(L->oldpc, p))) /* enter a new line */
- luaD_hook(L, LUA_HOOKLINE, newline); /* call line hook */
- }
- L->oldpc = ci->u.l.savedpc;
- if (L->status == LUA_YIELD) { /* did hook yield? */
- if (counthook)
- L->hookcount = 1; /* undo decrement to zero */
- ci->u.l.savedpc--; /* undo increment (resume will increment it again) */
- ci->callstatus |= CIST_HOOKYIELD; /* mark that it yielded */
- ci->func = L->top - 1; /* protect stack below results */
- luaD_throw(L, LUA_YIELD);
+/*
+** 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 is called only when 'n' has an integer value.
+*/
+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;
}
+ return 0; /* number is outside integer limits */
}
-static void callTM (lua_State *L, const TValue *f, const TValue *p1,
- const TValue *p2, TValue *p3, int hasres) {
- ptrdiff_t result = savestack(L, p3);
- setobj2s(L, L->top++, f); /* push function */
- setobj2s(L, L->top++, p1); /* 1st argument */
- setobj2s(L, L->top++, p2); /* 2nd argument */
- if (!hasres) /* no result? 'p3' is third argument */
- setobj2s(L, L->top++, p3); /* 3rd argument */
- /* metamethod may yield only when called from Lua code */
- luaD_call(L, L->top - (4 - hasres), hasres, isLua(L->ci));
- if (hasres) { /* if has result, move it to its place */
- p3 = restorestack(L, result);
- setobjs2s(L, p3, --L->top);
+/*
+** try to convert a non-integer value to an integer
+*/
+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;
}
@@ -124,7 +116,7 @@ void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {
else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX)))
luaG_typeerror(L, t, "index");
if (ttisfunction(tm)) {
- callTM(L, tm, t, key, val, 1);
+ luaT_callTM(L, tm, t, key, val, 1);
return;
}
t = tm; /* else repeat with 'tm' */
@@ -163,7 +155,7 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
luaG_typeerror(L, t, "index");
/* there is a metamethod */
if (ttisfunction(tm)) {
- callTM(L, tm, t, key, val, 0);
+ luaT_callTM(L, tm, t, key, val, 0);
return;
}
t = tm; /* else repeat with 'tm' */
@@ -172,40 +164,6 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
}
-static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2,
- StkId res, TMS event) {
- const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */
- if (ttisnil(tm))
- tm = luaT_gettmbyobj(L, p2, event); /* try second operand */
- if (ttisnil(tm)) return 0;
- callTM(L, tm, p1, p2, res, 1);
- return 1;
-}
-
-
-static const TValue *get_equalTM (lua_State *L, Table *mt1, Table *mt2,
- TMS event) {
- const TValue *tm1 = fasttm(L, mt1, event);
- const TValue *tm2;
- if (tm1 == NULL) return NULL; /* no metamethod */
- if (mt1 == mt2) return tm1; /* same metatables => same metamethods */
- tm2 = fasttm(L, mt2, event);
- if (tm2 == NULL) return NULL; /* no metamethod */
- if (luaV_rawequalobj(tm1, tm2)) /* same metamethods? */
- return tm1;
- return NULL;
-}
-
-
-static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2,
- TMS event) {
- if (!call_binTM(L, p1, p2, L->top, event))
- return -1; /* no metamethod */
- else
- return !l_isfalse(L->top);
-}
-
-
static int l_strcmp (const TString *ls, const TString *rs) {
const char *l = getstr(ls);
size_t ll = ls->tsv.len;
@@ -230,11 +188,14 @@ static int l_strcmp (const TString *ls, const TString *rs) {
int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
int res;
- if (ttisnumber(l) && ttisnumber(r))
- return luai_numlt(L, nvalue(l), nvalue(r));
+ lua_Number nl, nr;
+ if (ttisinteger(l) && ttisinteger(r))
+ return (ivalue(l) < ivalue(r));
+ else if (tonumber(l, &nl) && tonumber(r, &nr))
+ return luai_numlt(L, nl, nr);
else if (ttisstring(l) && ttisstring(r))
return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0;
- else if ((res = call_orderTM(L, l, r, TM_LT)) < 0)
+ else if ((res = luaT_callorderTM(L, l, r, TM_LT)) < 0)
luaG_ordererror(L, l, r);
return res;
}
@@ -242,13 +203,16 @@ int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) {
int res;
- if (ttisnumber(l) && ttisnumber(r))
- return luai_numle(L, nvalue(l), nvalue(r));
+ lua_Number nl, nr;
+ if (ttisinteger(l) && ttisinteger(r))
+ return (ivalue(l) <= ivalue(r));
+ else if (tonumber(l, &nl) && tonumber(r, &nr))
+ return luai_numle(L, nl, nr);
else if (ttisstring(l) && ttisstring(r))
return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0;
- else if ((res = call_orderTM(L, l, r, TM_LE)) >= 0) /* first try `le' */
+ else if ((res = luaT_callorderTM(L, l, r, TM_LE)) >= 0) /* first try `le' */
return res;
- else if ((res = call_orderTM(L, r, l, TM_LT)) < 0) /* else try `lt' */
+ else if ((res = luaT_callorderTM(L, r, l, TM_LT)) < 0) /* else try `lt' */
luaG_ordererror(L, l, r);
return !res;
}
@@ -257,12 +221,23 @@ int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) {
/*
** equality of Lua values. L == NULL means raw equality (no metamethods)
*/
-int luaV_equalobj_ (lua_State *L, const TValue *t1, const TValue *t2) {
+int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) {
const TValue *tm;
- lua_assert(ttisequal(t1, t2));
+ if (ttype(t1) != ttype(t2)) {
+ 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_assert(ttisnumber(t1) && ttisnumber(t2));
+ (void)tonumber(t1, &n1); (void)tonumber(t2, &n2);
+ return luai_numeq(n1, n2);
+ }
+ }
+ /* values have same type and same variant */
switch (ttype(t1)) {
case LUA_TNIL: return 1;
- case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2));
+ case LUA_TNUMINT: return (ivalue(t1) == ivalue(t2));
+ case LUA_TNUMFLT: return luai_numeq(fltvalue(t1), fltvalue(t2));
case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */
case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);
case LUA_TLCF: return fvalue(t1) == fvalue(t2);
@@ -271,21 +246,20 @@ 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 = get_equalTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, TM_EQ);
+ tm = luaT_getequalTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable);
break; /* will try TM */
}
case LUA_TTABLE: {
if (hvalue(t1) == hvalue(t2)) return 1;
else if (L == NULL) return 0;
- tm = get_equalTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ);
+ tm = luaT_getequalTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable);
break; /* will try TM */
}
default:
- lua_assert(iscollectable(t1));
return gcvalue(t1) == gcvalue(t2);
}
if (tm == NULL) return 0; /* no TM? */
- callTM(L, tm, t1, t2, L->top, 1); /* call TM */
+ luaT_callTM(L, tm, t1, t2, L->top, 1); /* call TM */
return !l_isfalse(L->top);
}
@@ -295,10 +269,8 @@ void luaV_concat (lua_State *L, int total) {
do {
StkId top = L->top;
int n = 2; /* number of elements handled in this pass (at least 2) */
- if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) {
- if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT))
- luaG_concaterror(L, top-2, top-1);
- }
+ if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1))
+ luaT_trybinTM(L, top-2, top-1, top-2, TM_CONCAT);
else if (tsvalue(top-1)->len == 0) /* second operand is empty? */
(void)tostring(L, top - 2); /* result is first operand */
else if (ttisstring(top-2) && tsvalue(top-2)->len == 0) {
@@ -312,7 +284,7 @@ void luaV_concat (lua_State *L, int total) {
/* collect total length */
for (i = 1; i < total && tostring(L, top-i-1); i++) {
size_t l = tsvalue(top-i-1)->len;
- if (l >= (MAX_SIZET/sizeof(char)) - tl)
+ if (l >= (MAX_SIZE/sizeof(char)) - tl)
luaG_runerror(L, "string length overflow");
tl += l;
}
@@ -334,16 +306,16 @@ void luaV_concat (lua_State *L, int total) {
void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) {
const TValue *tm;
- switch (ttypenv(rb)) {
+ switch (ttnov(rb)) {
case LUA_TTABLE: {
Table *h = hvalue(rb);
tm = fasttm(L, h->metatable, TM_LEN);
if (tm) break; /* metamethod? break switch to call it */
- setnvalue(ra, cast_num(luaH_getn(h))); /* else primitive len */
+ setivalue(ra, luaH_getn(h)); /* else primitive len */
return;
}
case LUA_TSTRING: {
- setnvalue(ra, cast_num(tsvalue(rb)->len));
+ setivalue(ra, tsvalue(rb)->len);
return;
}
default: { /* try metamethod */
@@ -353,21 +325,54 @@ void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) {
break;
}
}
- callTM(L, tm, rb, rb, ra, 1);
+ luaT_callTM(L, tm, rb, rb, ra, 1);
+}
+
+
+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)
+ luaG_runerror(L, "attempt to divide by zero");
+ else /* -1 */
+ return -x; /* avoid overflow with 0x80000... */
+ }
+ else {
+ lua_Integer d = x / y; /* perform division */
+ if ((x ^ y) >= 0 || x % y == 0) /* same signal or no rest? */
+ return d;
+ else
+ return d - 1; /* correct 'div' for negative case */
+ }
+}
+
+
+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)
+ luaG_runerror(L, "attempt to perform 'n%%0'");
+ else /* -1 */
+ return 0; /* avoid overflow with 0x80000... */
+ }
+ else {
+ lua_Integer r = x % y;
+ if (r == 0 || (x ^ y) >= 0)
+ return r;
+ else
+ return r + y; /* correct 'mod' for negative case */
+ }
}
-void luaV_arith (lua_State *L, StkId ra, const TValue *rb,
- const TValue *rc, TMS op) {
- TValue tempb, tempc;
- const TValue *b, *c;
- if ((b = luaV_tonumber(rb, &tempb)) != NULL &&
- (c = luaV_tonumber(rc, &tempc)) != NULL) {
- lua_Number res = luaO_arith(op - TM_ADD + LUA_OPADD, nvalue(b), nvalue(c));
- setnvalue(ra, res);
+lua_Integer luaV_pow (lua_Integer x, lua_Integer y) {
+ lua_Integer r = 1;
+ lua_assert(y >= 0);
+ if (y == 0) return r;
+ for (; y > 1; y >>= 1) {
+ if (y & 1) r = intop(*, r, x);
+ x = intop(*, x, x);
}
- else if (!call_binTM(L, rb, rc, ra, op))
- luaG_aritherror(L, rb, rc);
+ r = intop(*, r, x);
+ return r;
}
@@ -426,7 +431,7 @@ void luaV_finishOp (lua_State *L) {
Instruction inst = *(ci->u.l.savedpc - 1); /* interrupted instruction */
OpCode op = GET_OPCODE(inst);
switch (op) { /* finish its execution */
- case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV:
+ case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: case OP_IDIV:
case OP_MOD: case OP_POW: case OP_UNM: case OP_LEN:
case OP_GETTABUP: case OP_GETTABLE: case OP_SELF: {
setobjs2s(L, base + GETARG_A(inst), --L->top);
@@ -446,7 +451,7 @@ void luaV_finishOp (lua_State *L) {
break;
}
case OP_CONCAT: {
- StkId top = L->top - 1; /* top when 'call_binTM' was called */
+ StkId top = L->top - 1; /* top when 'luaT_trybinTM' was called */
int b = GETARG_B(inst); /* first element to concatenate */
int total = cast_int(top - 1 - (base + b)); /* yet to concatenate */
setobj2s(L, top - 2, top); /* put TM result in proper position */
@@ -517,16 +522,6 @@ void luaV_finishOp (lua_State *L) {
luai_threadyield(L); )
-#define arith_op(op,tm) { \
- TValue *rb = RKB(i); \
- TValue *rc = RKC(i); \
- if (ttisnumber(rb) && ttisnumber(rc)) { \
- lua_Number nb = nvalue(rb), nc = nvalue(rc); \
- setnvalue(ra, op(L, nb, nc)); \
- } \
- else { Protect(luaV_arith(L, ra, rb, rc, tm)); } }
-
-
#define vmdispatch(o) switch(o)
#define vmcase(l,b) case l: {b} break;
#define vmcasenb(l,b) case l: {b} /* nb = no break */
@@ -547,7 +542,7 @@ void luaV_execute (lua_State *L) {
StkId ra;
if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
(--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
- Protect(traceexec(L));
+ Protect(luaG_traceexec(L));
}
/* WARNING: several calls may realloc the stack and invalidate `ra' */
ra = RA(i);
@@ -614,32 +609,103 @@ void luaV_execute (lua_State *L) {
setobjs2s(L, ra+1, rb);
Protect(luaV_gettable(L, rb, RKC(i), ra));
)
- vmcase(OP_ADD,
- arith_op(luai_numadd, TM_ADD);
+ vmcase(OP_ADD,
+ 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, intop(+, ib, ic));
+ }
+ else if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
+ setnvalue(ra, luai_numadd(L, nb, nc));
+ }
+ else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_ADD)); }
)
vmcase(OP_SUB,
- arith_op(luai_numsub, TM_SUB);
+ 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, intop(-, ib, ic));
+ }
+ else if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
+ setnvalue(ra, luai_numsub(L, nb, nc));
+ }
+ else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SUB)); }
)
vmcase(OP_MUL,
- arith_op(luai_nummul, TM_MUL);
+ 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, intop(*, ib, ic));
+ }
+ else if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
+ setnvalue(ra, luai_nummul(L, nb, nc));
+ }
+ else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_MUL)); }
)
- vmcase(OP_DIV,
- arith_op(luai_numdiv, TM_DIV);
+ vmcase(OP_DIV, /* float division (always with floats) */
+ TValue *rb = RKB(i);
+ TValue *rc = RKC(i);
+ lua_Number nb; lua_Number nc;
+ if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
+ setnvalue(ra, luai_numdiv(L, nb, nc));
+ }
+ else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_DIV)); }
+ )
+ vmcase(OP_IDIV, /* integer division */
+ TValue *rb = RKB(i);
+ TValue *rc = RKC(i);
+ lua_Integer ib; lua_Integer ic;
+ if (tointeger(rb, &ib) && tointeger(rc, &ic)) {
+ setivalue(ra, luaV_div(L, ib, ic));
+ }
+ else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_IDIV)); }
)
vmcase(OP_MOD,
- arith_op(luai_nummod, TM_MOD);
+ 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_mod(L, ib, ic));
+ }
+ else if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
+ setnvalue(ra, luai_nummod(L, nb, nc));
+ }
+ else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_MOD)); }
)
vmcase(OP_POW,
- arith_op(luai_numpow, TM_POW);
+ TValue *rb = RKB(i);
+ TValue *rc = RKC(i);
+ lua_Number nb; lua_Number nc;
+ lua_Integer ic;
+ if (ttisinteger(rb) && ttisinteger(rc) &&
+ (ic = ivalue(rc)) >= 0) {
+ lua_Integer ib = ivalue(rb);
+ setivalue(ra, luaV_pow(ib, ic));
+ }
+ else if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
+ setnvalue(ra, luai_numpow(L, nb, nc));
+ }
+ else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_POW)); }
)
vmcase(OP_UNM,
TValue *rb = RB(i);
- if (ttisnumber(rb)) {
- lua_Number nb = nvalue(rb);
+ lua_Number nb;
+ if (ttisinteger(rb)) {
+ lua_Integer ib = ivalue(rb);
+ setivalue(ra, -ib);
+ }
+ else if (tonumber(rb, &nb)) {
setnvalue(ra, luai_numunm(L, nb));
}
else {
- Protect(luaV_arith(L, ra, rb, rb, TM_UNM));
+ Protect(luaT_trybinTM(L, rb, rb, ra, TM_UNM));
}
)
vmcase(OP_NOT,
@@ -669,7 +735,7 @@ void luaV_execute (lua_State *L) {
TValue *rb = RKB(i);
TValue *rc = RKC(i);
Protect(
- if (cast_int(equalobj(L, rb, rc)) != GETARG_A(i))
+ if (cast_int(luaV_equalobj(L, rb, rc)) != GETARG_A(i))
ci->u.l.savedpc++;
else
donextjump(ci);
@@ -765,27 +831,47 @@ void luaV_execute (lua_State *L) {
}
)
vmcase(OP_FORLOOP,
- lua_Number step = nvalue(ra+2);
- lua_Number idx = luai_numadd(L, nvalue(ra), step); /* increment index */
- lua_Number limit = nvalue(ra+1);
- if (luai_numlt(L, 0, step) ? luai_numle(L, idx, limit)
- : luai_numle(L, limit, idx)) {
- ci->u.l.savedpc += GETARG_sBx(i); /* jump back */
- setnvalue(ra, idx); /* update internal index... */
- setnvalue(ra+3, idx); /* ...and external index */
+ if (ttisinteger(ra)) { /* integer count? */
+ lua_Integer step = ivalue(ra + 2);
+ lua_Integer idx = ivalue(ra) + step; /* increment index */
+ lua_Integer limit = ivalue(ra + 1);
+ if ((0 < step) ? (idx <= limit) : (limit <= idx)) {
+ ci->u.l.savedpc += GETARG_sBx(i); /* jump back */
+ setivalue(ra, idx); /* update internal index... */
+ setivalue(ra + 3, idx); /* ...and external index */
+ }
+ }
+ else { /* floating count */
+ lua_Number step = fltvalue(ra + 2);
+ lua_Number idx = luai_numadd(L, fltvalue(ra), step); /* inc. index */
+ lua_Number limit = fltvalue(ra + 1);
+ if (luai_numlt(L, 0, step) ? luai_numle(L, idx, limit)
+ : luai_numle(L, limit, idx)) {
+ ci->u.l.savedpc += GETARG_sBx(i); /* jump back */
+ setnvalue(ra, idx); /* update internal index... */
+ setnvalue(ra + 3, idx); /* ...and external index */
+ }
}
)
vmcase(OP_FORPREP,
- const TValue *init = ra;
- const TValue *plimit = ra+1;
- const TValue *pstep = ra+2;
- if (!tonumber(init, ra))
- luaG_runerror(L, LUA_QL("for") " initial value must be a number");
- else if (!tonumber(plimit, ra+1))
- luaG_runerror(L, LUA_QL("for") " limit must be a number");
- else if (!tonumber(pstep, ra+2))
- luaG_runerror(L, LUA_QL("for") " step must be a number");
- setnvalue(ra, luai_numsub(L, nvalue(ra), nvalue(pstep)));
+ TValue *init = ra;
+ TValue *plimit = ra + 1;
+ TValue *pstep = ra + 2;
+ if (ttisinteger(ra) && ttisinteger(ra + 1) && ttisinteger(ra + 2)) {
+ setivalue(ra, ivalue(ra) - ivalue(pstep));
+ }
+ else { /* try with 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);
+ if (!tonumber(pstep, &nstep))
+ luaG_runerror(L, LUA_QL("for") " step must be a number");
+ setnvalue(pstep, nstep);
+ if (!tonumber(init, &ninit))
+ luaG_runerror(L, LUA_QL("for") " initial value must be a number");
+ setnvalue(ra, luai_numsub(L, ninit, nstep));
+ }
ci->u.l.savedpc += GETARG_sBx(i);
)
vmcasenb(OP_TFORCALL,
diff --git a/src/lvm.h b/src/lvm.h
index 07e25f9c..4f2651d3 100644
--- a/src/lvm.h
+++ b/src/lvm.h
@@ -1,5 +1,5 @@
/*
-** $Id: lvm.h,v 2.18 2013/01/08 14:06:55 roberto Exp $
+** $Id: lvm.h,v 2.23 2013/05/02 12:31:26 roberto Exp $
** Lua virtual machine
** See Copyright Notice in lua.h
*/
@@ -15,20 +15,24 @@
#define tostring(L,o) (ttisstring(o) || (luaV_tostring(L, o)))
-#define tonumber(o,n) (ttisnumber(o) || (((o) = luaV_tonumber(o,n)) != NULL))
+#define tonumber(o,n) \
+ (ttisfloat(o) ? (*(n) = fltvalue(o), 1) : luaV_tonumber_(o,n))
-#define equalobj(L,o1,o2) (ttisequal(o1, o2) && luaV_equalobj_(L, o1, o2))
+#define tointeger(o,i) \
+ (ttisinteger(o) ? (*(i) = ivalue(o), 1) : luaV_tointeger_(o,i))
-#define luaV_rawequalobj(o1,o2) equalobj(NULL,o1,o2)
+#define intop(op,v1,v2) \
+ cast_integer(cast_unsigned(v1) op cast_unsigned(v2))
-
-/* not to called directly */
-LUAI_FUNC int luaV_equalobj_ (lua_State *L, const TValue *t1, const TValue *t2);
+#define luaV_rawequalobj(t1,t2) luaV_equalobj(NULL,t1,t2)
+LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2);
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 const TValue *luaV_tonumber (const TValue *obj, TValue *n);
+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);
@@ -37,8 +41,9 @@ LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key,
LUAI_FUNC void luaV_finishOp (lua_State *L);
LUAI_FUNC void luaV_execute (lua_State *L);
LUAI_FUNC void luaV_concat (lua_State *L, int total);
-LUAI_FUNC void luaV_arith (lua_State *L, StkId ra, const TValue *rb,
- const TValue *rc, TMS op);
+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_Integer x, lua_Integer y);
LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb);
#endif
diff --git a/src/lzio.h b/src/lzio.h
index 08682301..aec0bc12 100644
--- a/src/lzio.h
+++ b/src/lzio.h
@@ -1,5 +1,5 @@
/*
-** $Id: lzio.h,v 1.26 2011/07/15 12:48:03 roberto Exp $
+** $Id: lzio.h,v 1.27 2013/06/07 14:51:10 roberto Exp $
** Buffered streams
** See Copyright Notice in lua.h
*/
@@ -45,7 +45,7 @@ typedef struct Mbuffer {
LUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n);
LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader,
void *data);
-LUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */
+LUAI_FUNC size_t luaZ_read (ZIO* z, void *b, size_t n); /* read next n bytes */
@@ -55,7 +55,7 @@ struct Zio {
size_t n; /* bytes still unread */
const char *p; /* current position in buffer */
lua_Reader reader; /* reader function */
- void* data; /* additional data */
+ void *data; /* additional data */
lua_State *L; /* Lua state (for reader) */
};