diff options
-rw-r--r-- | README | 2 | ||||
-rw-r--r-- | doc/contents.html | 20 | ||||
-rw-r--r-- | doc/lua.css | 7 | ||||
-rw-r--r-- | doc/manual.html | 416 | ||||
-rw-r--r-- | doc/readme.html | 34 | ||||
-rw-r--r-- | src/Makefile | 2 | ||||
-rw-r--r-- | src/lapi.c | 214 | ||||
-rw-r--r-- | src/lapi.h | 6 | ||||
-rw-r--r-- | src/lauxlib.c | 50 | ||||
-rw-r--r-- | src/lauxlib.h | 21 | ||||
-rw-r--r-- | src/lbaselib.c | 79 | ||||
-rw-r--r-- | src/ldebug.c | 17 | ||||
-rw-r--r-- | src/ldo.c | 9 | ||||
-rw-r--r-- | src/ldump.c | 6 | ||||
-rw-r--r-- | src/lgc.c | 102 | ||||
-rw-r--r-- | src/lgc.h | 26 | ||||
-rw-r--r-- | src/liolib.c | 20 | ||||
-rw-r--r-- | src/llex.c | 8 | ||||
-rw-r--r-- | src/llimits.h | 32 | ||||
-rw-r--r-- | src/lmathlib.c | 61 | ||||
-rw-r--r-- | src/lmem.c | 10 | ||||
-rw-r--r-- | src/loadlib.c | 149 | ||||
-rw-r--r-- | src/lobject.c | 43 | ||||
-rw-r--r-- | src/lobject.h | 107 | ||||
-rw-r--r-- | src/lparser.c | 2 | ||||
-rw-r--r-- | src/lstate.c | 12 | ||||
-rw-r--r-- | src/lstate.h | 66 | ||||
-rw-r--r-- | src/lstring.c | 52 | ||||
-rw-r--r-- | src/lstring.h | 12 | ||||
-rw-r--r-- | src/lstrlib.c | 21 | ||||
-rw-r--r-- | src/ltable.c | 29 | ||||
-rw-r--r-- | src/ltable.h | 9 | ||||
-rw-r--r-- | src/ltablib.c | 183 | ||||
-rw-r--r-- | src/ltm.c | 2 | ||||
-rw-r--r-- | src/lua.c | 30 | ||||
-rw-r--r-- | src/lua.h | 88 | ||||
-rw-r--r-- | src/luac.c | 6 | ||||
-rw-r--r-- | src/luaconf.h | 43 | ||||
-rw-r--r-- | src/lutf8lib.c | 4 | ||||
-rw-r--r-- | src/lvm.c | 77 | ||||
-rw-r--r-- | src/lvm.h | 17 |
41 files changed, 1212 insertions, 882 deletions
@@ -1,5 +1,5 @@ -This is Lua 5.3.0 (work3), released on 19 Jul 2014. +This is Lua 5.3.0 (alpha), released on 31 Jul 2014. For installation instructions, license details, and further information about Lua, see doc/readme.html. diff --git a/doc/contents.html b/doc/contents.html index af3142b5..b7a00e30 100644 --- a/doc/contents.html +++ b/doc/contents.html @@ -22,7 +22,7 @@ Lua 5.3 Reference Manual <P> <IMG SRC="alert.png" ALIGN="absbottom"> -<EM>All details may change in the final version.</EM> +<EM>Some details may change in the final version.</EM> <P> The reference manual is the official definition of the Lua language. @@ -37,7 +37,7 @@ For a complete introduction to Lua programming, see the book <A HREF="#index">index</A> <HR> <SMALL> -Copyright © 2011–2014 Lua.org, PUC-Rio. +Copyright © 2014 Lua.org, PUC-Rio. Freely available under the terms of the <A HREF="http://www.lua.org/license.html">Lua license</A>. </SMALL> @@ -229,7 +229,6 @@ Freely available under the terms of the <TD> <H3> </H3> <P> -<A HREF="manual.html#pdf-math">math</A><BR> <A HREF="manual.html#pdf-math.abs">math.abs</A><BR> <A HREF="manual.html#pdf-math.acos">math.acos</A><BR> <A HREF="manual.html#pdf-math.asin">math.asin</A><BR> @@ -240,7 +239,6 @@ Freely available under the terms of the <A HREF="manual.html#pdf-math.floor">math.floor</A><BR> <A HREF="manual.html#pdf-math.fmod">math.fmod</A><BR> <A HREF="manual.html#pdf-math.huge">math.huge</A><BR> -<A HREF="manual.html#pdf-math.ifloor">math.ifloor</A><BR> <A HREF="manual.html#pdf-math.log">math.log</A><BR> <A HREF="manual.html#pdf-math.max">math.max</A><BR> <A HREF="manual.html#pdf-math.maxinteger">math.maxinteger</A><BR> @@ -254,7 +252,9 @@ Freely available under the terms of the <A HREF="manual.html#pdf-math.sin">math.sin</A><BR> <A HREF="manual.html#pdf-math.sqrt">math.sqrt</A><BR> <A HREF="manual.html#pdf-math.tan">math.tan</A><BR> +<A HREF="manual.html#pdf-math.tointeger">math.tointeger</A><BR> <A HREF="manual.html#pdf-math.type">math.type</A><BR> +<A HREF="manual.html#pdf-math.ult">math.ult</A><BR> <P> <A HREF="manual.html#pdf-os.clock">os.clock</A><BR> @@ -301,6 +301,7 @@ Freely available under the terms of the <P> <A HREF="manual.html#pdf-table.concat">table.concat</A><BR> +<A HREF="manual.html#pdf-table.copy">table.copy</A><BR> <A HREF="manual.html#pdf-table.insert">table.insert</A><BR> <A HREF="manual.html#pdf-table.pack">table.pack</A><BR> <A HREF="manual.html#pdf-table.remove">table.remove</A><BR> @@ -321,6 +322,7 @@ Freely available under the terms of the <P> <A HREF="manual.html#lua_Alloc">lua_Alloc</A><BR> <A HREF="manual.html#lua_CFunction">lua_CFunction</A><BR> +<A HREF="manual.html#lua_Ctx">lua_Ctx</A><BR> <A HREF="manual.html#lua_Debug">lua_Debug</A><BR> <A HREF="manual.html#lua_Hook">lua_Hook</A><BR> <A HREF="manual.html#lua_Integer">lua_Integer</A><BR> @@ -347,6 +349,7 @@ Freely available under the terms of the <A HREF="manual.html#lua_error">lua_error</A><BR> <A HREF="manual.html#lua_gc">lua_gc</A><BR> <A HREF="manual.html#lua_getallocf">lua_getallocf</A><BR> +<A HREF="manual.html#lua_getextraspace">lua_getextraspace</A><BR> <A HREF="manual.html#lua_getfield">lua_getfield</A><BR> <A HREF="manual.html#lua_getglobal">lua_getglobal</A><BR> <A HREF="manual.html#lua_gethook">lua_gethook</A><BR> @@ -399,7 +402,6 @@ Freely available under the terms of the <A HREF="manual.html#lua_pushnumber">lua_pushnumber</A><BR> <A HREF="manual.html#lua_pushstring">lua_pushstring</A><BR> <A HREF="manual.html#lua_pushthread">lua_pushthread</A><BR> -<A HREF="manual.html#lua_pushunsigned">lua_pushunsigned</A><BR> <A HREF="manual.html#lua_pushvalue">lua_pushvalue</A><BR> <A HREF="manual.html#lua_pushvfstring">lua_pushvfstring</A><BR> <A HREF="manual.html#lua_rawequal">lua_rawequal</A><BR> @@ -437,8 +439,6 @@ Freely available under the terms of the <A HREF="manual.html#lua_topointer">lua_topointer</A><BR> <A HREF="manual.html#lua_tostring">lua_tostring</A><BR> <A HREF="manual.html#lua_tothread">lua_tothread</A><BR> -<A HREF="manual.html#lua_tounsigned">lua_tounsigned</A><BR> -<A HREF="manual.html#lua_tounsignedx">lua_tounsignedx</A><BR> <A HREF="manual.html#lua_touserdata">lua_touserdata</A><BR> <A HREF="manual.html#lua_type">lua_type</A><BR> <A HREF="manual.html#lua_typename">lua_typename</A><BR> @@ -480,7 +480,6 @@ Freely available under the terms of the <A HREF="manual.html#luaL_checkstring">luaL_checkstring</A><BR> <A HREF="manual.html#luaL_checktype">luaL_checktype</A><BR> <A HREF="manual.html#luaL_checkudata">luaL_checkudata</A><BR> -<A HREF="manual.html#luaL_checkunsigned">luaL_checkunsigned</A><BR> <A HREF="manual.html#luaL_checkversion">luaL_checkversion</A><BR> <A HREF="manual.html#luaL_dofile">luaL_dofile</A><BR> <A HREF="manual.html#luaL_dostring">luaL_dostring</A><BR> @@ -508,7 +507,6 @@ Freely available under the terms of the <A HREF="manual.html#luaL_optlstring">luaL_optlstring</A><BR> <A HREF="manual.html#luaL_optnumber">luaL_optnumber</A><BR> <A HREF="manual.html#luaL_optstring">luaL_optstring</A><BR> -<A HREF="manual.html#luaL_optunsigned">luaL_optunsigned</A><BR> <A HREF="manual.html#luaL_prepbuffer">luaL_prepbuffer</A><BR> <A HREF="manual.html#luaL_prepbuffsize">luaL_prepbuffsize</A><BR> <A HREF="manual.html#luaL_pushresult">luaL_pushresult</A><BR> @@ -531,10 +529,10 @@ Freely available under the terms of the <HR> <SMALL CLASS="footer"> Last update: -Thu Jun 19 17:09:46 BRT 2014 +Thu Jul 31 14:04:18 BRT 2014 </SMALL> <!-- -Last change: updated for Lua 5.3.0 (work3) +Last change: updated for Lua 5.3.0 (alpha) --> </BODY> diff --git a/doc/lua.css b/doc/lua.css index 3d2443ac..98f0fcda 100644 --- a/doc/lua.css +++ b/doc/lua.css @@ -59,6 +59,10 @@ a:link:active, a:visited:active { color: #FF0000 ; } +h1 a img { + vertical-align: text-bottom ; +} + hr { border: 0 ; height: 1px ; @@ -88,9 +92,8 @@ input[type=text] { border-radius: 2em ; -moz-border-radius: 2em ; background-image: url('images/search.png') ; - background-repeat: no-repeat; + background-repeat: no-repeat ; background-position: 4px center ; padding-left: 20px ; height: 2em ; } - diff --git a/doc/manual.html b/doc/manual.html index de2dc5f6..186597b5 100644 --- a/doc/manual.html +++ b/doc/manual.html @@ -18,13 +18,13 @@ Lua 5.3 Reference Manual <P> <IMG SRC="alert.png" ALIGN="absbottom"> -<EM>All details may change in the final version.</EM> +<EM>Some details may change in the final version.</EM> <P> by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes <p> <small> -Copyright © 2011–2014 Lua.org, PUC-Rio. +Copyright © 2014 Lua.org, PUC-Rio. Freely available under the terms of the <a href="http://www.lua.org/license.html">Lua license</a>. </small> @@ -38,7 +38,7 @@ Freely available under the terms of the <!-- ====================================================================== --> <p> -<!-- $Id: manual.of,v 1.121 2014/06/18 19:12:23 roberto Exp $ --> +<!-- $Id: manual.of,v 1.125 2014/07/31 13:58:08 roberto Exp $ --> @@ -125,7 +125,7 @@ it usually represents the absence of a useful value. Both <b>nil</b> and <b>false</b> make a condition false; any other value makes it true. <em>Number</em> represents both -integral numbers and real (floating-point) numbers. +integer numbers and real (floating-point) numbers. <em>String</em> represents immutable sequences of bytes. Lua is 8-bit clean: @@ -146,7 +146,7 @@ Standard Lua uses 64-bit integers and double-precision (64-bit) floats, but you can also compile Lua so that it uses 32-bit integers and/or single-precision (32-bit) floats. The option with 32 bits both for integers and floats -(what is called <em>Small Lua</em>) is particularly attractive +(called <em>Small Lua</em>) is particularly attractive for small machines. @@ -159,7 +159,7 @@ functions written in C <p> The type <em>userdata</em> is provided to allow arbitrary C data to be stored in Lua variables. -A userdata value is a pointer to a block of raw memory. +A userdata value represents a block of raw memory. There are two kinds of userdata: full userdata, where the block of memory is managed by Lua, and light userdata, where the block of memory is managed by the host. @@ -178,7 +178,7 @@ The type <em>thread</em> represents independent threads of execution and it is used to implement coroutines (see <a href="#2.6">§2.6</a>). Do not confuse Lua threads with operating-system threads. Lua supports coroutines on all systems, -even those that do not support threads. +even those that do not support threads natively. <p> @@ -324,7 +324,9 @@ is never updated by Lua. <p> Because Lua is an embedded extension language, all Lua actions start from C code in the host program -calling a function from the Lua library (see <a href="#lua_pcall"><code>lua_pcall</code></a>). +calling a function from the Lua library. +(when you use Lua standalone, +the <code>lua</code> application is the host program.) Whenever an error occurs during the compilation or execution of a Lua chunk, control returns to the host, @@ -1891,9 +1893,9 @@ that rounds the quotient towards minus infinite (floor). In case of overflows in integer arithmetic, all operations <em>wrap around</em>, according to the usual rules of two-complement arithmetic. -(In other words, they return the correct result modulo <em>2<sup>64</sup></em>.) - - +(In other words, +they return the unique representable integer +that is equal modulo <em>2<sup>64</sup></em> to the mathematical result.) @@ -1921,7 +1923,7 @@ Both right and left shifts fill the vacant bits with zeros. Negative displacements shift to the other direction; displacements with absolute values equal to or higher than the number of bits in an integer -result in zero (all bits are shifted out). +result in zero (as all bits are shifted out). @@ -1952,16 +1954,17 @@ 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. +the conversion gets the nearest higher or +the nearest 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 -(that is, it is in the range of integer representation), -that is the result. +checks whether the float has an exact representation as an integer +(that is, the float has an integral value and +it is in the range of integer representation). +If it does, that representation is the result. Otherwise, the conversion fails. @@ -2005,7 +2008,7 @@ Otherwise, the values of the operands are compared. Strings are compared in the obvious way. Numbers follow the usual rule for binary operations: if both operands are integers, -the are compared as integers; +they are compared as integers; otherwise, they are converted to floats and compared as such. @@ -2028,7 +2031,7 @@ by using the "eq" metamethod (see <a href="#2.4">§2.4</a>). <p> -Equality comparisons never convert strings to numbers +Equality comparisons do not 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 @@ -2190,7 +2193,7 @@ with key <code>exp1</code> and value <code>exp2</code>. A field of the form <code>name = exp</code> is equivalent to <code>["name"] = exp</code>. Finally, fields of the form <code>exp</code> are equivalent to -<code>[i] = exp</code>, where <code>i</code> are consecutive numerical integers, +<code>[i] = exp</code>, where <code>i</code> are consecutive integers starting with 1. Fields in the other formats do not affect this counting. For example, @@ -2861,7 +2864,7 @@ the Lua code being ran by <a href="#lua_pcall"><code>lua_pcall</code></a> to yie First, we can rewrite our function like here: <pre> - int k (lua_State *L, int status, int ctx) { + int k (lua_State *L, int status, lua_Ctx ctx) { ... /* code 2 */ } @@ -2905,6 +2908,12 @@ the status is always <a href="#pdf-LUA_YIELD"><code>LUA_YIELD</code></a> when Lu (For these two functions, Lua will not call the continuation in case of errors, because they do not handle errors.) +Similarly, when using <a href="#lua_callk"><code>lua_callk</code></a>, +you should call the continuation function +with <a href="#pdf-LUA_OK"><code>LUA_OK</code></a> as the status. +(For <a href="#lua_yieldk"><code>lua_yieldk</code></a>, there is not much point in calling +directly the continuation function, +because <a href="#lua_yieldk"><code>lua_yieldk</code></a> usually does not return.) <p> @@ -3159,7 +3168,7 @@ This is considered good programming practice. <hr><h3><a name="lua_callk"><code>lua_callk</code></a></h3><p> <span class="apii">[-(nargs + 1), +nresults, <em>e</em>]</span> -<pre>void lua_callk (lua_State *L, int nargs, int nresults, int ctx, +<pre>void lua_callk (lua_State *L, int nargs, int nresults, lua_Ctx ctx, lua_KFunction k);</pre> <p> @@ -3307,7 +3316,7 @@ Concatenation is performed following the usual semantics of Lua <pre>void lua_copy (lua_State *L, int fromidx, int toidx);</pre> <p> -Moves the element at index <code>fromidx</code> +Copies the element at index <code>fromidx</code> into the valid index <code>toidx</code> without shifting any element (therefore replacing the value at that position). @@ -3335,6 +3344,21 @@ Otherwise you can use the function <a href="#lua_newtable"><code>lua_newtable</c +<hr><h3><a name="lua_Ctx"><code>lua_Ctx</code></a></h3> +<pre>typedef ... lua_Ctx;</pre> + +<p> +The type for continuation-function contexts. +It must be a numerical type. +This type is defined as <code>intptr_t</code> +when <code>intptr_t</code> is available, +so that it can store pointers too. +Otherwise, it is defined as <code>ptrdiff_t</code>. + + + + + <hr><h3><a name="lua_dump"><code>lua_dump</code></a></h3><p> <span class="apii">[-0, +0, <em>e</em>]</span> <pre>int lua_dump (lua_State *L, @@ -3485,6 +3509,31 @@ Returns the type of the pushed value. +<hr><h3><a name="lua_getextraspace"><code>lua_getextraspace</code></a></h3><p> +<span class="apii">[-0, +0, –]</span> +<pre>void *lua_getextraspace (lua_State *L);</pre> + +<p> +Returns a pointer to a raw memory area associated with the +given Lua state. +The application can use this area for any purpose; +Lua does not use it for anything. + + +<p> +Each new thread has this area initialized with a copy +of the area of the main thread. + + +<p> +By default, this area has the size of a pointer to void, +but you can recompile Lua with a different size for this area. +(See <code>LUA_EXTRASPACE</code> in <code>luaconf.h</code>.) + + + + + <hr><h3><a name="lua_getglobal"><code>lua_getglobal</code></a></h3><p> <span class="apii">[-0, +1, <em>e</em>]</span> <pre>int lua_getglobal (lua_State *L, const char *name);</pre> @@ -3502,8 +3551,9 @@ Returns the type of that value. <pre>int lua_getmetatable (lua_State *L, int index);</pre> <p> -Pushes onto the stack the metatable of the value at the given index. -If the value does not have a metatable, +If the value at the given index has a metatable, +the function pushes that metatable onto the stack and returns 1. +Otherwise, the function returns 0 and pushes nothing on the stack. @@ -3588,9 +3638,9 @@ The type of integers in Lua. <p> By default this type is <code>long long</code> (usually a 64-bit two-complement integer), -but that can be changed in <code>luaconf.h</code> -to <code>long</code> or <code>int</code> -(usually a 32-bit two-complement integer). +but that can be changed to <code>long</code> or <code>int</code>, +usually a 32-bit two-complement integer. +(See <code>LUA_INT</code> in <code>luaconf.h</code>.) <p> @@ -3775,7 +3825,7 @@ and 0 otherwise. <hr><h3><a name="lua_KFunction"><code>lua_KFunction</code></a></h3> -<pre>typedef int (*lua_KFunction) (lua_State *L, int status, int ctx);</pre> +<pre>typedef int (*lua_KFunction) (lua_State *L, int status, lua_Ctx ctx);</pre> <p> Type for continuation functions (see <a href="#4.7">§4.7</a>). @@ -3988,7 +4038,8 @@ The type of floats in Lua. <p> By default this type is double, -but that can be changed in <code>luaconf.h</code> to a single float. +but that can be changed to a single float. +(See <code>LUA_REAL</code> in <code>luaconf.h</code>.) @@ -4096,7 +4147,7 @@ error while running a <code>__gc</code> metamethod. int nargs, int nresults, int errfunc, - int ctx, + lua_Ctx ctx, lua_KFunction k);</pre> <p> @@ -4366,17 +4417,6 @@ Returns 1 if this thread is the main thread of its state. -<hr><h3><a name="lua_pushunsigned"><code>lua_pushunsigned</code></a></h3><p> -<span class="apii">[-0, +1, –]</span> -<pre>void lua_pushunsigned (lua_State *L, lua_Unsigned n);</pre> - -<p> -Pushes an integer with value <code>n</code> onto the stack. - - - - - <hr><h3><a name="lua_pushvalue"><code>lua_pushvalue</code></a></h3><p> <span class="apii">[-0, +1, –]</span> <pre>void lua_pushvalue (lua_State *L, int index);</pre> @@ -4916,9 +4956,12 @@ to a string inside the Lua state. This string always has a zero ('<code>\0</code>') after its last character (as in C), but can contain other zeros in its body. + + +<p> Because Lua has garbage collection, there is no guarantee that the pointer returned by <code>lua_tolstring</code> -will be valid after the corresponding value is removed from the stack. +will be valid after the corresponding Lua value is removed from the stack. @@ -5001,48 +5044,6 @@ otherwise, the function returns <code>NULL</code>. -<hr><h3><a name="lua_tounsigned"><code>lua_tounsigned</code></a></h3><p> -<span class="apii">[-0, +0, –]</span> -<pre>lua_Unsigned lua_tounsigned (lua_State *L, int index);</pre> - -<p> -Equivalent to <a href="#lua_tounsignedx"><code>lua_tounsignedx</code></a> with <code>isnum</code> equal to <code>NULL</code>. - - - - - -<hr><h3><a name="lua_tounsignedx"><code>lua_tounsignedx</code></a></h3><p> -<span class="apii">[-0, +0, –]</span> -<pre>lua_Unsigned lua_tounsignedx (lua_State *L, int index, int *isnum);</pre> - -<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 an integer, -or a float, -or a string convertible to a number -(see <a href="#3.4.3">§3.4.3</a>); -otherwise, <code>lua_tounsignedx</code> returns 0. - - -<p> -If the number is not an integer, -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. - - -<p> -If <code>isnum</code> is not <code>NULL</code>, -its referent is assigned a boolean value that -indicates whether the operation succeeded. - - - - - <hr><h3><a name="lua_touserdata"><code>lua_touserdata</code></a></h3><p> <span class="apii">[-0, +0, –]</span> <pre>void *lua_touserdata (lua_State *L, int index);</pre> @@ -5101,11 +5102,6 @@ which must be one the values returned by <a href="#lua_type"><code>lua_type</cod The unsigned version of <a href="#lua_Integer"><code>lua_Integer</code></a>. -<p> -Lua also defines the constant <a name="pdf-LUA_MAXUNSIGNED"><code>LUA_MAXUNSIGNED</code></a>, -with the maximum value that fits in this type. - - @@ -5178,14 +5174,14 @@ and pushes them onto the stack <code>to</code>. <hr><h3><a name="lua_yield"><code>lua_yield</code></a></h3><p> -<span class="apii">[-?, +?, –]</span> +<span class="apii">[-?, +?, <em>e</em>]</span> <pre>int lua_yield (lua_State *L, int nresults);</pre> <p> This function is equivalent to <a href="#lua_yieldk"><code>lua_yieldk</code></a>, but it has no continuation (see <a href="#4.7">§4.7</a>). Therefore, when the thread resumes, -it returns to the function that called +it continues the function that called the function calling <code>lua_yield</code>. @@ -5193,21 +5189,15 @@ the function calling <code>lua_yield</code>. <hr><h3><a name="lua_yieldk"><code>lua_yieldk</code></a></h3><p> -<span class="apii">[-?, +?, –]</span> -<pre>int lua_yieldk (lua_State *L, int nresults, int ctx, lua_KFunction k);</pre> +<span class="apii">[-?, +?, <em>e</em>]</span> +<pre>int lua_yieldk (lua_State *L, int nresults, lua_Ctx ctx, lua_KFunction k);</pre> <p> -Yields a coroutine. +Yields a coroutine (thread). <p> -This function should only be called as the -return expression of a C function, as follows: - -<pre> - return lua_yieldk (L, n, ctx, k); -</pre><p> -When a C function calls <a href="#lua_yieldk"><code>lua_yieldk</code></a> in that way, +When a C function calls <a href="#lua_yieldk"><code>lua_yieldk</code></a>, the running coroutine suspends its execution, and the call to <a href="#lua_resume"><code>lua_resume</code></a> that started this coroutine returns. The parameter <code>nresults</code> is the number of values from the stack @@ -5227,6 +5217,29 @@ the continuation function receives the value <code>ctx</code> that was passed to <a href="#lua_yieldk"><code>lua_yieldk</code></a>. +<p> +Usually, this function does not return; +when the coroutine eventually resumes, +it continues executing the continuation function. +However, there is one special case, +which is when this function is called +from inside a line hook (see <a href="#4.9">§4.9</a>). +In that case, <code>lua_yieldk</code> should be called with no continuation +(probably in the form of <a href="#lua_yield"><code>lua_yield</code></a>), +and the hook should return immediately after the call. +Lua will yield and, +when the coroutine resumes again, +it will continue the normal execution +of the (Lua) function that triggered the hook. + + +<p> +This function can raise an error if it is called from a thread +with a pending C call with no continuation function, +or it is called from a thread that is not running inside a resume +(e.g., the main thread). + + @@ -6196,18 +6209,6 @@ returns the userdata address (see <a href="#lua_touserdata"><code>lua_touserdata -<hr><h3><a name="luaL_checkunsigned"><code>luaL_checkunsigned</code></a></h3><p> -<span class="apii">[-0, +0, <em>v</em>]</span> -<pre>lua_Unsigned luaL_checkunsigned (lua_State *L, int arg);</pre> - -<p> -Checks whether the function argument <code>arg</code> is a number -and returns this number converted to a <a href="#lua_Unsigned"><code>lua_Unsigned</code></a>. - - - - - <hr><h3><a name="luaL_checkversion"><code>luaL_checkversion</code></a></h3><p> <span class="apii">[-0, +0, –]</span> <pre>void luaL_checkversion (lua_State *L);</pre> @@ -6682,23 +6683,6 @@ Otherwise, raises an error. -<hr><h3><a name="luaL_optunsigned"><code>luaL_optunsigned</code></a></h3><p> -<span class="apii">[-0, +0, <em>v</em>]</span> -<pre>lua_Unsigned luaL_optunsigned (lua_State *L, - int arg, - lua_Unsigned u);</pre> - -<p> -If the function argument <code>arg</code> is a number, -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. - - - - - <hr><h3><a name="luaL_prepbuffer"><code>luaL_prepbuffer</code></a></h3><p> <span class="apii">[-?, +?, <em>e</em>]</span> <pre>char *luaL_prepbuffer (luaL_Buffer *B);</pre> @@ -6803,18 +6787,19 @@ in which both <code>name</code> and <code>func</code> are <code>NULL</code>. lua_CFunction openf, int glb);</pre> <p> -Calls function <code>openf</code> with string <code>modname</code> as an argument +If <code>modname</code> is not already present in <a href="#pdf-package.loaded"><code>package.loaded</code></a>, +calls function <code>openf</code> with string <code>modname</code> as an argument and sets the call result in <code>package.loaded[modname]</code>, as if that function has been called through <a href="#pdf-require"><code>require</code></a>. <p> If <code>glb</code> is true, -also stores the result into global <code>modname</code>. +also stores the module into global <code>modname</code>. <p> -Leaves a copy of that result on the stack. +Leaves a copy of the module on the stack. @@ -7218,21 +7203,19 @@ Otherwise, returns the metatable of the given object. <p> -If <code>t</code> has a metamethod <code>__ipairs</code>, -calls it with <code>t</code> as argument and returns the first three -results from the call. - - -<p> -Otherwise, -returns three values: an iterator function, the table <code>t</code>, and 0, +Returns three values (an iterator function, the table <code>t</code>, and 0) so that the construction <pre> for i,v in ipairs(t) do <em>body</em> end </pre><p> -will iterate over the pairs (<code>1,t[1]</code>), (<code>2,t[2]</code>), ..., -up to the first integer key absent from the table. +will iterate over the pairs +(<code>1,t[1]</code>), (<code>2,t[2]</code>), ..., (<code>#t,t[#t]</code>). + + +<p> +The table should be a proper sequence +or have a <code>__len</code> metamethod (see <a href="#3.4.7">§3.4.7</a>). @@ -7973,9 +7956,9 @@ The name of this C function is the string "<code>luaopen_</code>" concatenated with a copy of the module name where each dot is replaced by an underscore. Moreover, if the module name has a hyphen, -its prefix up to (and including) the first hyphen is removed. -For instance, if the module name is <code>a.v1-b.c</code>, -the function name will be <code>luaopen_b_c</code>. +its sufix after (and including) the first hyphen is removed. +For instance, if the module name is <code>a.b.c-v2.1</code>, +the function name will be <code>luaopen_a_b_c</code>. <p> @@ -8138,6 +8121,8 @@ This function may not work correctly in architectures with mixed endian. + + <p> <hr><h3><a name="pdf-string.dumpint"><code>string.dumpint (n [, size [, endianness]])</code></a></h3> Returns a string with the two-complement representation of integer <code>n</code>, @@ -8165,7 +8150,7 @@ that do not use a two-complement representation for integers. <p> Looks for the first match of -<code>pattern</code> in the string <code>s</code>. +<code>pattern</code> (see <a href="#6.4.1">§6.4.1</a>) in the string <code>s</code>. If it finds a match, then <code>find</code> returns the indices of <code>s</code> where this occurrence starts and ends; otherwise, it returns <b>nil</b>. @@ -8235,7 +8220,8 @@ it is converted to one following the same rules of <a href="#pdf-tostring"><code <hr><h3><a name="pdf-string.gmatch"><code>string.gmatch (s, pattern)</code></a></h3> Returns an iterator function that, each time it is called, -returns the next captures from <code>pattern</code> over the string <code>s</code>. +returns the next captures from <code>pattern</code> (see <a href="#6.4.1">§6.4.1</a>) +over the string <code>s</code>. If <code>pattern</code> specifies no captures, then the whole match is produced in each call. @@ -8273,7 +8259,7 @@ work as an anchor, as this would prevent the iteration. <hr><h3><a name="pdf-string.gsub"><code>string.gsub (s, pattern, repl [, n])</code></a></h3> Returns a copy of <code>s</code> in which all (or the first <code>n</code>, if given) -occurrences of the <code>pattern</code> have been +occurrences of the <code>pattern</code> (see <a href="#6.4.1">§6.4.1</a>) have been replaced by a replacement string specified by <code>repl</code>, which can be a string, a table, or a function. <code>gsub</code> also returns, as its second value, @@ -8368,7 +8354,7 @@ The definition of what an uppercase letter is depends on the current locale. <p> <hr><h3><a name="pdf-string.match"><code>string.match (s, pattern [, init])</code></a></h3> Looks for the first <em>match</em> of -<code>pattern</code> in the string <code>s</code>. +<code>pattern</code> (see <a href="#6.4.1">§6.4.1</a>) in the string <code>s</code>. If it finds one, then <code>match</code> returns the captures from the pattern; otherwise it returns <b>nil</b>. @@ -8456,8 +8442,21 @@ The definition of what a lowercase letter is depends on the current locale. + + <h3>6.4.1 – <a name="6.4.1">Patterns</a></h3> +<p> +Patterns in Lua are described by regular strings, +which are interpreted as patterns by the pattern-matching functions +<a href="#pdf-string.find"><code>string.find</code></a>, +<a href="#pdf-string.gmatch"><code>string.gmatch</code></a>, +<a href="#pdf-string.gsub"><code>string.gsub</code></a>, +and <a href="#pdf-string.match"><code>string.match</code></a>. +This section describes the syntax and the meaning +(that is, what they match) of these strings. + + <h4>Character Class:</h4><p> A <em>character class</em> is used to represent a set of characters. @@ -8649,8 +8648,6 @@ string <code>"flaaap"</code>, there will be two captures: 3 and 5. - - <h2>6.5 – <a name="6.5">UTF-8 Support</a></h2> <p> @@ -8775,11 +8772,6 @@ in tables given as arguments. <p> -For performance reasons, -all table accesses (get/set) performed by these functions are raw. - - -<p> <hr><h3><a name="pdf-table.concat"><code>table.concat (list [, sep [, i [, j]]])</code></a></h3> @@ -8795,6 +8787,22 @@ If <code>i</code> is greater than <code>j</code>, returns the empty string. <p> +<hr><h3><a name="pdf-table.copy"><code>table.copy (a1, f, e, [a2,] t)</code></a></h3> + + +<p> +Copies elements from table <code>a1</code> to table <code>a2</code>. +This function performs the equivalent to the following +multiple assignment: +<code>a2[t],··· = a1[f],···,a1[e]</code>. +The default for <code>a2</code> is <code>a1</code>. +The destination range can overlap with the source range. +Index <code>f</code> must be positive. + + + + +<p> <hr><h3><a name="pdf-table.insert"><code>table.insert (list, [pos,] value)</code></a></h3> @@ -9015,18 +9023,6 @@ a value larger than 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>. -If the value does not fit in an integer, -returns <b>nil</b>. - - - - -<p> <hr><h3><a name="pdf-math.log"><code>math.log (x [, base])</code></a></h3> @@ -9172,6 +9168,18 @@ Returns the tangent of <code>x</code> (assumed to be in radians). <p> +<hr><h3><a name="pdf-math.tointeger"><code>math.tointeger (x)</code></a></h3> + + +<p> +If the value <code>x</code> is convertible to an integer, +returns that integer. +Otherwise, returns <b>nil</b>. + + + + +<p> <hr><h3><a name="pdf-math.type"><code>math.type (x)</code></a></h3> @@ -9183,6 +9191,18 @@ or <b>nil</b> if <code>x</code> is not a number. +<p> +<hr><h3><a name="pdf-math.ult"><code>math.ult (m, n)</code></a></h3> + + +<p> +Returns a boolean, +true if integer <code>m</code> is below integer <code>n</code> when +they are compared as unsigned integers. + + + + @@ -10272,8 +10292,7 @@ The options are: <li><b><code>--</code>: </b> stops handling options;</li> <li><b><code>-</code>: </b> executes <code>stdin</code> as a file and stops handling options.</li> </ul><p> -After handling its options, <code>lua</code> runs the given <em>script</em>, -passing to it the given <em>args</em> as string arguments. +After handling its options, <code>lua</code> runs the given <em>script</em>. When called without arguments, <code>lua</code> behaves as <code>lua -v -i</code> when the standard input (<code>stdin</code>) is a terminal, @@ -10283,7 +10302,7 @@ and as <code>lua -</code> otherwise. <p> When called without option <code>-E</code>, the interpreter checks for an environment variable <a name="pdf-LUA_INIT_5_3"><code>LUA_INIT_5_3</code></a> -(or <a name="pdf-LUA_INIT"><code>LUA_INIT</code></a> if it is not defined) +(or <a name="pdf-LUA_INIT"><code>LUA_INIT</code></a> if the versioned name is not defined) before running any argument. If the variable content has the format <code>@<em>filename</em></code>, then <code>lua</code> executes the file. @@ -10343,6 +10362,11 @@ For instance, the call $ lua -e "print(arg[1])" </pre><p> will print "<code>-e</code>". +If there is a script, +the script is called with parameters +<code>arg[1]</code>, ···, <code>arg[#arg]</code>. +(Like all chunks in Lua, +the script is compiled as a vararg function.) <p> @@ -10417,7 +10441,7 @@ do not imply source-code changes in a program, such as the numeric values for constants or the implementation of functions as macros. Therefore, -you should never assume that binaries are compatible between +you should not assume that binaries are compatible between different Lua versions. Always recompile clients of the Lua API when using a new version. @@ -10426,7 +10450,7 @@ using a new version. <p> Similarly, Lua versions can always change the internal representation of precompiled chunks; -precompiled chunks are never compatible between different Lua versions. +precompiled chunks are not compatible between different Lua versions. <p> @@ -10458,12 +10482,6 @@ it is not a general guideline for good programming. For good programming, use floats where you need floats and integers where you need integers.) - - -<p> -Although not formally an incompatibility, -the proper differentiation between floats and integers -have an impact on performance. </li> <li> @@ -10503,6 +10521,16 @@ while the bitwise operators in Standard Lua operate on 64-bit integers.) </li> <li> +The Table library now respects metamethods +for setting and getting elements. +</li> + +<li> +The <a href="#pdf-ipairs"><code>ipairs</code></a> iterator now respects metamethods and +its id{__ipairs} metamethod has been deprecated. +</li> + +<li> Option names in <a href="#pdf-io.read"><code>io.read</code></a> do not have a starting '<code>*</code>' anymore. For compatibility, Lua will continue to ignore this character. </li> @@ -10513,12 +10541,23 @@ The following functions were deprecated in the mathematical library: <code>frexp</code>, and <code>ldexp</code>. You can replace <code>math.pow(x,y)</code> with <code>x^y</code>; you can replace <code>math.atan2</code> with <code>math.atan</code>, -which now accepts two parameters; +which now accepts one or two parameters; you can replace <code>math.ldexp(x,exp)</code> with <code>x * 2.0^exp</code>. For the other operations, the best choice is to use an external library. </li> +<li> +The searcher for C loaders used by <a href="#pdf-require"><code>require</code></a> +changed the way it handles versioned names. +Now, the version should come after the module name +(as is usual in most other tools). +For compatibility, that searcher still tries the old format +if if cannot find an open function according to the new style. +(Lua 5.2 already worked that way, +but it did not document the change.) +</li> + </ul> @@ -10541,6 +10580,13 @@ Function <a href="#lua_dump"><code>lua_dump</code></a> has an extra parameter, < Use 0 as the value of this parameter to get the old behavior. </li> +<li> +Functions to inject/project unsigned integers +(<code>lua_pushunsigned</code>, <code>lua_tounsigned</code>, etc.) +were deprecated. +Use their signed equivalents with a type cast. +</li> + </ul> @@ -10550,7 +10596,7 @@ Use 0 as the value of this parameter to get the old behavior. <p> Here is the complete syntax of Lua in extended BNF. -(It does not describe operator precedences.) +(For operator precedences, see <a href="#3.4.8">§3.4.8</a>.) @@ -10635,10 +10681,10 @@ Here is the complete syntax of Lua in extended BNF. <HR> <SMALL CLASS="footer"> Last update: -Thu Jun 19 17:13:19 BRT 2014 +Thu Jul 31 14:02:14 BRT 2014 </SMALL> <!-- -Last change: updated for Lua 5.3.0 (work3) +Last change: revised for Lua 5.3.0 (alpha) --> </body></html> diff --git a/doc/readme.html b/doc/readme.html index 6c9ec1e1..19e0c553 100644 --- a/doc/readme.html +++ b/doc/readme.html @@ -31,12 +31,12 @@ tt, kbd, code { <HR> <H1> <A HREF="http://www.lua.org/"><IMG SRC="logo.gif" ALT="Lua" BORDER=0></A> -Welcome to Lua 5.3 (work3) +Welcome to Lua 5.3 (alpha) </H1> <P> <IMG SRC="alert.png" ALIGN="absbottom"> -<EM>All details may change in the final version.</EM> +<EM>Some details may change in the final version.</EM> <P> <A HREF="#about">about</A> @@ -114,7 +114,7 @@ Here are the details. <OL> <LI> Open a terminal window and move to -the top-level directory, which is named <TT>lua-5.3.0-work3</TT>. +the top-level directory, which is named <TT>lua-5.3.0-alpha</TT>. The <TT>Makefile</TT> there controls both the build process and the installation process. <P> <LI> @@ -275,36 +275,38 @@ lists the <LI> better support for small architectures ("Small Lua" with 32-bit numbers) <LI> bitwise operators <LI> basic utf-8 library + <LI> utf-8 escapes in literal strings -<LI> functions for packing/unpacking numbers -<LI> userdata can have any Lua value as uservalue <LI> strip option in <CODE>lua_dump</CODE>/<CODE>string.dump</CODE> </UL> Here are the other changes introduced in Lua 5.3: <H3>Language</H3> <UL> -<LI> +<LI> userdata can have any Lua value as uservalue +<LI> integer division +<LI> more flexible rules for some metamethods </UL> <H3>Libraries</H3> <UL> -<LI> +<LI> functions for packing/unpacking numbers +<LI> strip option in <CODE>string.dump</CODE> +<LI> table library respects metamethods +<LI> new function <CODE>table.copy</CODE> +<LI> new function <CODE>debug.Csize</CODE> </UL> <H3>C API</H3> <UL> -<LI> -</UL> - -<H3>Implementation</H3> -<UL> -<LI> +<LI> new functions: <CODE>lua_rotate</CODE>, <CODE>lua_isyieldable</CODE>, <CODE>lua_strtonum</CODE> +<LI> <CODE>lua_gettable</CODE> and similar functions return type of resulted value </UL> <H3>Lua standalone interpreter</H3> <UL> -<LI> Can be used as calculator; no need to prefix with '=' +<LI> can be used as calculator; no need to prefix with '=' +<LI> <CODE>arg</CODE> table available to all code </UL> <H2><A NAME="license">License</A></H2> @@ -354,10 +356,10 @@ THE SOFTWARE. <HR> <SMALL CLASS="footer"> Last update: -Wed Jun 11 22:54:18 BRT 2014 +Thu Jul 31 15:23:46 BRT 2014 </SMALL> <!-- -Last change: updated for Lua 5.3.0 (work3) +Last change: updated for Lua 5.3.0 (alpha) --> </BODY> diff --git a/src/Makefile b/src/Makefile index 4b357ce1..a30a75ef 100644 --- a/src/Makefile +++ b/src/Makefile @@ -7,7 +7,7 @@ PLAT= none CC= gcc -CFLAGS= -O2 -Wall -Wextra -DLUA_COMPAT_ALL $(SYSCFLAGS) $(MYCFLAGS) +CFLAGS= -O2 -Wall -Wextra -DLUA_COMPAT_5_2 $(SYSCFLAGS) $(MYCFLAGS) LDFLAGS= $(SYSLDFLAGS) $(MYLDFLAGS) LIBS= -lm $(SYSLIBS) $(MYLIBS) @@ -1,5 +1,5 @@ /* -** $Id: lapi.c,v 2.219 2014/06/19 18:27:20 roberto Exp $ +** $Id: lapi.c,v 2.232 2014/07/30 14:00:14 roberto Exp $ ** Lua API ** See Copyright Notice in lua.h */ @@ -44,32 +44,35 @@ const char lua_ident[] = /* test for pseudo index */ #define ispseudo(i) ((i) <= LUA_REGISTRYINDEX) +/* test for upvalue */ +#define isupvalue(i) ((i) < LUA_REGISTRYINDEX) + /* test for valid but not pseudo index */ #define isstackindex(i, o) (isvalid(o) && !ispseudo(i)) -#define api_checkvalidindex(L, o) api_check(L, isvalid(o), "invalid index") +#define api_checkvalidindex(o) api_check(isvalid(o), "invalid index") -#define api_checkstackindex(L, i, o) \ - api_check(L, isstackindex(i, o), "index not in the stack") +#define api_checkstackindex(i, o) \ + api_check(isstackindex(i, o), "index not in the stack") static TValue *index2addr (lua_State *L, int idx) { CallInfo *ci = L->ci; if (idx > 0) { TValue *o = ci->func + idx; - api_check(L, idx <= ci->top - (ci->func + 1), "unacceptable index"); + api_check(idx <= ci->top - (ci->func + 1), "unacceptable index"); if (o >= L->top) return NONVALIDVALUE; else return o; } else if (!ispseudo(idx)) { /* negative index */ - api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index"); + api_check(idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index"); return L->top + idx; } else if (idx == LUA_REGISTRYINDEX) return &G(L)->l_registry; else { /* upvalues */ idx = LUA_REGISTRYINDEX - idx; - api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large"); + api_check(idx <= MAXUPVAL + 1, "upvalue index too large"); if (ttislcf(ci->func)) /* light C function? */ return NONVALIDVALUE; /* it has no upvalues */ else { @@ -94,7 +97,7 @@ LUA_API int lua_checkstack (lua_State *L, int size) { int res; CallInfo *ci = L->ci; lua_lock(L); - api_check(L, size >= 0, "negative 'size'"); + api_check(size >= 0, "negative 'size'"); if (L->stack_last - L->top > size) /* stack large enough? */ res = 1; /* yes; check is OK */ else { /* no; need to grow stack */ @@ -116,8 +119,8 @@ LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { if (from == to) return; lua_lock(to); api_checknelems(from, n); - api_check(from, G(from) == G(to), "moving among independent states"); - api_check(from, to->ci->top - to->top >= n, "not enough elements to move"); + api_check(G(from) == G(to), "moving among independent states"); + api_check(to->ci->top - to->top >= n, "not enough elements to move"); from->top -= n; for (i = 0; i < n; i++) { setobj2s(to, to->top++, from->top + i); @@ -168,13 +171,13 @@ LUA_API void lua_settop (lua_State *L, int idx) { StkId func = L->ci->func; lua_lock(L); if (idx >= 0) { - api_check(L, idx <= L->stack_last - (func + 1), "new top too large"); + api_check(idx <= L->stack_last - (func + 1), "new top too large"); while (L->top < (func + 1) + idx) setnilvalue(L->top++); L->top = (func + 1) + idx; } else { - api_check(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top"); + api_check(-(idx+1) <= (L->top - (func + 1)), "invalid new top"); L->top += idx+1; /* `subtract' index (index is negative) */ } lua_unlock(L); @@ -183,7 +186,7 @@ LUA_API void lua_settop (lua_State *L, int idx) { /* ** Reverse the stack segment from 'from' to 'to' -** (auxiliar to 'lua_rotate') +** (auxiliary to 'lua_rotate') */ static void reverse (lua_State *L, StkId from, StkId to) { for (; from < to; from++, to--) { @@ -204,8 +207,8 @@ LUA_API void lua_rotate (lua_State *L, int idx, int n) { lua_lock(L); t = L->top - 1; /* end of stack segment being rotated */ p = index2addr(L, idx); /* start of segment */ - api_checkstackindex(L, idx, p); - api_check(L, (n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'"); + api_checkstackindex(idx, p); + api_check((n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'"); m = (n >= 0 ? t - n : p - n - 1); /* end of prefix */ reverse(L, p, m); /* reverse the prefix with length 'n' */ reverse(L, m + 1, t); /* reverse the suffix */ @@ -214,31 +217,17 @@ LUA_API void lua_rotate (lua_State *L, int idx, int n) { } -static void moveto (lua_State *L, TValue *fr, int idx) { - TValue *to = index2addr(L, idx); - api_checkvalidindex(L, to); +LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) { + TValue *fr, *to; + lua_lock(L); + fr = index2addr(L, fromidx); + to = index2addr(L, toidx); + api_checkvalidindex(to); setobj(L, to, fr); - if (idx < LUA_REGISTRYINDEX) /* function upvalue? */ + if (isupvalue(toidx)) /* function upvalue? */ luaC_barrier(L, clCvalue(L->ci->func), fr); /* LUA_REGISTRYINDEX does not need gc barrier (collector revisits it before finishing collection) */ -} - - -LUA_API void lua_replace (lua_State *L, int idx) { - lua_lock(L); - api_checknelems(L, 1); - moveto(L, L->top - 1, idx); - L->top--; - lua_unlock(L); -} - - -LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) { - TValue *fr; - lua_lock(L); - fr = index2addr(L, fromidx); - moveto(L, fr, toidx); lua_unlock(L); } @@ -265,6 +254,7 @@ LUA_API int lua_type (lua_State *L, int idx) { LUA_API const char *lua_typename (lua_State *L, int t) { UNUSED(L); + api_check(LUA_TNONE <= t && t < LUA_NUMTAGS, "invalid tag"); return ttypename(t); } @@ -289,8 +279,8 @@ LUA_API int lua_isnumber (lua_State *L, int idx) { LUA_API int lua_isstring (lua_State *L, int idx) { - int t = lua_type(L, idx); - return (t == LUA_TSTRING || t == LUA_TNUMBER); + const TValue *o = index2addr(L, idx); + return (ttisstring(o) || cvt2str(o)); } @@ -334,7 +324,7 @@ LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) { 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"); + default: api_check(0, "invalid option"); } } lua_unlock(L); @@ -372,40 +362,6 @@ LUA_API lua_Integer lua_tointegerx (lua_State *L, int idx, int *pisnum) { } -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 = l_castS2U(ivalue(o)); - isnum = 1; - break; - } - case LUA_TNUMFLT: { /* compute floor(n) % 2^(numbits in an integer) */ - const lua_Number two2n = cast_num(LUA_MAXUNSIGNED) + cast_num(1); - lua_Number n = fltvalue(o); /* get value */ - int neg = 0; - n = l_floor(n); /* get its floor */ - if (n < 0) { - neg = 1; - n = -n; /* make 'n' positive, so that 'fmod' is the same as '%' */ - } - n = l_mathop(fmod)(n, two2n); /* n = n % 2^(numbits in an integer) */ - if (luai_numisnan(n)) /* not a number? */ - break; /* not an integer, too */ - res = cast(lua_Unsigned, n); /* 'n' now must fit in an unsigned */ - if (neg) res = 0u - res; /* back to negative, if needed */ - isnum = 1; - break; - } - default: break; - } - if (pisnum) *pisnum = isnum; - return res; -} - - LUA_API int lua_toboolean (lua_State *L, int idx) { const TValue *o = index2addr(L, idx); return !l_isfalse(o); @@ -415,14 +371,14 @@ LUA_API int lua_toboolean (lua_State *L, int idx) { LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { StkId o = index2addr(L, idx); if (!ttisstring(o)) { - lua_lock(L); /* `luaV_tostring' may create a new string */ - if (!luaV_tostring(L, o)) { /* conversion failed? */ + if (!cvt2str(o)) { /* not convertible? */ if (len != NULL) *len = 0; - lua_unlock(L); return NULL; } + lua_lock(L); /* `luaO_tostring' may create a new string */ luaC_checkGC(L); o = index2addr(L, idx); /* previous call may reallocate the stack */ + luaO_tostring(L, o); lua_unlock(L); } if (len != NULL) *len = tsvalue(o)->len; @@ -453,7 +409,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 (ttnov(o)) { - case LUA_TUSERDATA: return (rawuvalue(o) + 1); + case LUA_TUSERDATA: return getudatamem(uvalue(o)); case LUA_TLIGHTUSERDATA: return pvalue(o); default: return NULL; } @@ -512,14 +468,6 @@ LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { } -LUA_API void lua_pushunsigned (lua_State *L, lua_Unsigned u) { - lua_lock(L); - setivalue(L->top, l_castU2S(u)); - api_incr_top(L); - lua_unlock(L); -} - - LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) { TString *ts; lua_lock(L); @@ -582,7 +530,7 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { else { CClosure *cl; api_checknelems(L, n); - api_check(L, n <= MAXUPVAL, "upvalue index too large"); + api_check(n <= MAXUPVAL, "upvalue index too large"); luaC_checkGC(L); cl = luaF_newCclosure(L, n); cl->f = fn; @@ -667,7 +615,7 @@ LUA_API int lua_rawget (lua_State *L, int idx) { StkId t; lua_lock(L); t = index2addr(L, idx); - api_check(L, ttistable(t), "table expected"); + api_check(ttistable(t), "table expected"); setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1)); lua_unlock(L); return ttnov(L->top - 1); @@ -678,7 +626,7 @@ LUA_API int lua_rawgeti (lua_State *L, int idx, lua_Integer n) { StkId t; lua_lock(L); t = index2addr(L, idx); - api_check(L, ttistable(t), "table expected"); + api_check(ttistable(t), "table expected"); setobj2s(L, L->top, luaH_getint(hvalue(t), n)); api_incr_top(L); lua_unlock(L); @@ -691,7 +639,7 @@ LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) { TValue k; lua_lock(L); t = index2addr(L, idx); - api_check(L, ttistable(t), "table expected"); + api_check(ttistable(t), "table expected"); setpvalue(&k, cast(void *, p)); setobj2s(L, L->top, luaH_get(hvalue(t), &k)); api_incr_top(L); @@ -746,8 +694,8 @@ LUA_API int lua_getuservalue (lua_State *L, int idx) { StkId o; lua_lock(L); o = index2addr(L, idx); - api_check(L, ttisfulluserdata(o), "full userdata expected"); - getuservalue(L, rawuvalue(o), L->top); + api_check(ttisfulluserdata(o), "full userdata expected"); + getuservalue(L, uvalue(o), L->top); api_incr_top(L); lua_unlock(L); return ttnov(L->top - 1); @@ -796,42 +744,48 @@ LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { LUA_API void lua_rawset (lua_State *L, int idx) { - StkId t; + StkId o; + Table *t; lua_lock(L); api_checknelems(L, 2); - t = index2addr(L, idx); - api_check(L, ttistable(t), "table expected"); - setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1); - invalidateTMcache(hvalue(t)); - luaC_barrierback(L, gcvalue(t), L->top-1); + o = index2addr(L, idx); + api_check(ttistable(o), "table expected"); + t = hvalue(o); + setobj2t(L, luaH_set(L, t, L->top-2), L->top-1); + invalidateTMcache(t); + luaC_barrierback(L, t, L->top-1); L->top -= 2; lua_unlock(L); } LUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) { - StkId t; + StkId o; + Table *t; lua_lock(L); api_checknelems(L, 1); - t = index2addr(L, idx); - api_check(L, ttistable(t), "table expected"); - luaH_setint(L, hvalue(t), n, L->top - 1); - luaC_barrierback(L, gcvalue(t), L->top-1); + o = index2addr(L, idx); + api_check(ttistable(o), "table expected"); + t = hvalue(o); + luaH_setint(L, t, n, L->top - 1); + luaC_barrierback(L, t, L->top-1); L->top--; lua_unlock(L); } LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) { - StkId t; + StkId o; + Table *t; TValue k; lua_lock(L); api_checknelems(L, 1); - t = index2addr(L, idx); - api_check(L, ttistable(t), "table expected"); + o = index2addr(L, idx); + api_check(ttistable(o), "table expected"); + t = hvalue(o); setpvalue(&k, cast(void *, p)); - setobj2t(L, luaH_set(L, hvalue(t), &k), L->top - 1); - luaC_barrierback(L, gcvalue(t), L->top - 1); + setobj2t(L, luaH_set(L, t, &k), L->top - 1); + luaC_barrierback(L, t, L->top - 1); L->top--; lua_unlock(L); } @@ -846,7 +800,7 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) { if (ttisnil(L->top - 1)) mt = NULL; else { - api_check(L, ttistable(L->top - 1), "table expected"); + api_check(ttistable(L->top - 1), "table expected"); mt = hvalue(L->top - 1); } switch (ttnov(obj)) { @@ -861,7 +815,7 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) { case LUA_TUSERDATA: { uvalue(obj)->metatable = mt; if (mt) { - luaC_objbarrier(L, rawuvalue(obj), mt); + luaC_objbarrier(L, uvalue(obj), mt); luaC_checkfinalizer(L, gcvalue(obj), mt); } break; @@ -882,8 +836,8 @@ LUA_API void lua_setuservalue (lua_State *L, int idx) { lua_lock(L); api_checknelems(L, 1); o = index2addr(L, idx); - api_check(L, ttisfulluserdata(o), "full userdata expected"); - setuservalue(L, rawuvalue(o), L->top - 1); + api_check(ttisfulluserdata(o), "full userdata expected"); + setuservalue(L, uvalue(o), L->top - 1); luaC_barrier(L, gcvalue(o), L->top - 1); L->top--; lua_unlock(L); @@ -896,18 +850,18 @@ LUA_API void lua_setuservalue (lua_State *L, int idx) { #define checkresults(L,na,nr) \ - api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \ + api_check((nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \ "results from function overflow current stack size") -LUA_API void lua_callk (lua_State *L, int nargs, int nresults, int ctx, +LUA_API void lua_callk (lua_State *L, int nargs, int nresults, lua_Ctx ctx, lua_KFunction k) { StkId func; lua_lock(L); - api_check(L, k == NULL || !isLua(L->ci), + api_check(k == NULL || !isLua(L->ci), "cannot use continuations inside hooks"); api_checknelems(L, nargs+1); - api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); + api_check(L->status == LUA_OK, "cannot do calls on non-normal thread"); checkresults(L, nargs, nresults); func = L->top - (nargs+1); if (k != NULL && L->nny == 0) { /* need to prepare continuation? */ @@ -940,21 +894,21 @@ static void f_call (lua_State *L, void *ud) { LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc, - int ctx, lua_KFunction k) { + lua_Ctx ctx, lua_KFunction k) { struct CallS c; int status; ptrdiff_t func; lua_lock(L); - api_check(L, k == NULL || !isLua(L->ci), + api_check(k == NULL || !isLua(L->ci), "cannot use continuations inside hooks"); api_checknelems(L, nargs+1); - api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); + api_check(L->status == LUA_OK, "cannot do calls on non-normal thread"); checkresults(L, nargs, nresults); if (errfunc == 0) func = 0; else { StkId o = index2addr(L, errfunc); - api_checkstackindex(L, errfunc, o); + api_checkstackindex(errfunc, o); func = savestack(L, o); } c.func = L->top - (nargs+1); /* function to be called */ @@ -999,7 +953,7 @@ LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, const TValue *gt = luaH_getint(reg, LUA_RIDX_GLOBALS); /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */ setobj(L, f->upvals[0]->v, gt); - luaC_barrier(L, f->upvals[0], gt); + luaC_upvalbarrier(L, f->upvals[0]); } } lua_unlock(L); @@ -1062,7 +1016,7 @@ LUA_API int lua_gc (lua_State *L, int what, int data) { case LUA_GCSTEP: { l_mem debt = 1; /* =1 to signal that it did an actual step */ int oldrunning = g->gcrunning; - g->gcrunning = 1; /* force GC to run */ + g->gcrunning = 1; /* allow GC to run */ if (data == 0) { luaE_setdebt(g, -GCSTEPSIZE); /* to do a "small" step */ luaC_step(L); @@ -1119,7 +1073,7 @@ LUA_API int lua_next (lua_State *L, int idx) { int more; lua_lock(L); t = index2addr(L, idx); - api_check(L, ttistable(t), "table expected"); + api_check(ttistable(t), "table expected"); more = luaH_next(L, hvalue(t), L->top - 1); if (more) { api_incr_top(L); @@ -1183,19 +1137,19 @@ LUA_API void *lua_newuserdata (lua_State *L, size_t size) { setuvalue(L, L->top, u); api_incr_top(L); lua_unlock(L); - return u + 1; + return getudatamem(u); } static const char *aux_upvalue (StkId fi, int n, TValue **val, - GCObject **owner, UpVal **uv) { + CClosure **owner, UpVal **uv) { switch (ttype(fi)) { case LUA_TCCL: { /* C closure */ CClosure *f = clCvalue(fi); if (!(1 <= n && n <= f->nupvalues)) return NULL; *val = &f->upvalue[n-1]; - if (owner) *owner = obj2gco(f); + if (owner) *owner = f; return ""; } case LUA_TLCL: { /* Lua closure */ @@ -1230,7 +1184,7 @@ LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { const char *name; TValue *val = NULL; /* to avoid warnings */ - GCObject *owner = NULL; + CClosure *owner = NULL; UpVal *uv = NULL; StkId fi; lua_lock(L); @@ -1251,9 +1205,9 @@ LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) { LClosure *f; StkId fi = index2addr(L, fidx); - api_check(L, ttisLclosure(fi), "Lua function expected"); + api_check(ttisLclosure(fi), "Lua function expected"); f = clLvalue(fi); - api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index"); + api_check((1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index"); if (pf) *pf = f; return &f->upvals[n - 1]; /* get its upvalue pointer */ } @@ -1267,11 +1221,11 @@ LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) { } case LUA_TCCL: { /* C closure */ CClosure *f = clCvalue(fi); - api_check(L, 1 <= n && n <= f->nupvalues, "invalid upvalue index"); + api_check(1 <= n && n <= f->nupvalues, "invalid upvalue index"); return &f->upvalue[n - 1]; } default: { - api_check(L, 0, "closure expected"); + api_check(0, "closure expected"); return NULL; } } @@ -1,5 +1,5 @@ /* -** $Id: lapi.h,v 2.7 2009/11/27 15:37:59 roberto Exp $ +** $Id: lapi.h,v 2.8 2014/07/15 21:26:50 roberto Exp $ ** Auxiliary functions from Lua API ** See Copyright Notice in lua.h */ @@ -11,13 +11,13 @@ #include "llimits.h" #include "lstate.h" -#define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top, \ +#define api_incr_top(L) {L->top++; api_check(L->top <= L->ci->top, \ "stack overflow");} #define adjustresults(L,nres) \ { if ((nres) == LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; } -#define api_checknelems(L,n) api_check(L, (n) < (L->top - L->ci->func), \ +#define api_checknelems(L,n) api_check((n) < (L->top - L->ci->func), \ "not enough elements in the stack") diff --git a/src/lauxlib.c b/src/lauxlib.c index df0e5156..abf589ae 100644 --- a/src/lauxlib.c +++ b/src/lauxlib.c @@ -1,5 +1,5 @@ /* -** $Id: lauxlib.c,v 1.263 2014/05/12 21:44:17 roberto Exp $ +** $Id: lauxlib.c,v 1.267 2014/07/19 14:37:09 roberto Exp $ ** Auxiliary functions for building Lua libraries ** See Copyright Notice in lua.h */ @@ -396,8 +396,8 @@ LUALIB_API lua_Number luaL_optnumber (lua_State *L, int arg, lua_Number def) { static void interror (lua_State *L, int arg) { - if (lua_type(L, arg) == LUA_TNUMBER) - luaL_argerror(L, arg, "float value out of integer range"); + if (lua_isnumber(L, arg)) + luaL_argerror(L, arg, "number has no integer representation"); else tag_error(L, arg, LUA_TNUMBER); } @@ -413,26 +413,11 @@ LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int arg) { } -LUALIB_API lua_Unsigned luaL_checkunsigned (lua_State *L, int arg) { - int isnum; - lua_Unsigned d = lua_tounsignedx(L, arg, &isnum); - if (!isnum) - interror(L, arg); - return d; -} - - LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int arg, lua_Integer def) { return luaL_opt(L, luaL_checkinteger, arg, def); } - -LUALIB_API lua_Unsigned luaL_optunsigned (lua_State *L, int arg, - lua_Unsigned def) { - return luaL_opt(L, luaL_checkunsigned, arg, def); -} - /* }====================================================== */ @@ -898,22 +883,26 @@ LUALIB_API int luaL_getsubtable (lua_State *L, int idx, const char *fname) { /* -** stripped-down 'require'. Calls 'openf' to open a module, -** registers the result in 'package.loaded' table and, if 'glb' -** is true, also registers the result in the global table. +** Stripped-down 'require': After checking "loaded" table, calls 'openf' +** to open a module, registers the result in 'package.loaded' table and, +** if 'glb' is true, also registers the result in the global table. ** Leaves resulting module on the top. */ LUALIB_API void luaL_requiref (lua_State *L, const char *modname, lua_CFunction openf, int glb) { - lua_pushcfunction(L, openf); - lua_pushstring(L, modname); /* argument to open function */ - lua_call(L, 1, 1); /* open module */ luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED"); - lua_pushvalue(L, -2); /* make copy of module (call result) */ - lua_setfield(L, -2, modname); /* _LOADED[modname] = module */ - lua_pop(L, 1); /* remove _LOADED table */ + lua_getfield(L, -1, modname); /* _LOADED[modname] */ + if (!lua_toboolean(L, -1)) { /* package not already loaded? */ + lua_pop(L, 1); /* remove field */ + lua_pushcfunction(L, openf); + lua_pushstring(L, modname); /* argument to open function */ + lua_call(L, 1, 1); /* call 'openf' to open module */ + lua_pushvalue(L, -1); /* make copy of module (call result) */ + lua_setfield(L, -3, modname); /* _LOADED[modname] = module */ + } + lua_remove(L, -2); /* remove _LOADED table */ if (glb) { - lua_pushvalue(L, -1); /* copy of 'mod' */ + lua_pushvalue(L, -1); /* copy of module */ lua_setglobal(L, modname); /* _G[modname] = module */ } } @@ -963,13 +952,12 @@ LUALIB_API lua_State *luaL_newstate (void) { LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver, size_t sz) { const lua_Number *v = lua_version(L); + if (sz != LUAL_NUMSIZES) /* check numeric types */ + luaL_error(L, "core and library have incompatible numeric types"); 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", ver, *v); - /* 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 3ffe3561..b5560143 100644 --- a/src/lauxlib.h +++ b/src/lauxlib.h @@ -1,5 +1,5 @@ /* -** $Id: lauxlib.h,v 1.124 2014/04/15 18:25:49 roberto Exp $ +** $Id: lauxlib.h,v 1.125 2014/06/26 17:25:11 roberto Exp $ ** Auxiliary functions for building Lua libraries ** See Copyright Notice in lua.h */ @@ -46,9 +46,6 @@ LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int arg, lua_Number def); LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int arg); LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int arg, lua_Integer def); -LUALIB_API lua_Unsigned (luaL_checkunsigned) (lua_State *L, int arg); -LUALIB_API lua_Unsigned (luaL_optunsigned) (lua_State *L, int arg, - lua_Unsigned def); LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); LUALIB_API void (luaL_checktype) (lua_State *L, int arg, int t); @@ -211,6 +208,22 @@ LUALIB_API void (luaL_openlib) (lua_State *L, const char *libname, #endif +/* +** {============================================================ +** Compatibility with deprecated unsigned conversions +** ============================================================= +*/ +#if defined(LUA_COMPAT_APIUNSIGNED) + +#define luaL_checkunsigned(L,a) ((lua_Unsigned)luaL_checkinteger(L,a)) +#define luaL_optunsigned(L,a,d) \ + ((lua_Unsigned)luaL_optinteger(L,a,(lua_Integer)(d))) + +#endif +/* }============================================================ */ + + + #endif diff --git a/src/lbaselib.c b/src/lbaselib.c index deefe6c6..de1a767f 100644 --- a/src/lbaselib.c +++ b/src/lbaselib.c @@ -1,5 +1,5 @@ /* -** $Id: lbaselib.c,v 1.289 2014/06/10 17:41:38 roberto Exp $ +** $Id: lbaselib.c,v 1.293 2014/07/24 19:33:29 roberto Exp $ ** Basic library ** See Copyright Notice in lua.h */ @@ -200,9 +200,12 @@ static int luaB_collectgarbage (lua_State *L) { } +/* +** This function has all type names as upvalues, to maximize performance. +*/ static int luaB_type (lua_State *L) { luaL_checkany(L, 1); - lua_pushstring(L, luaL_typename(L, 1)); + lua_pushvalue(L, lua_upvalueindex(lua_type(L, 1) + 1)); return 1; } @@ -241,17 +244,53 @@ static int luaB_pairs (lua_State *L) { } -static int ipairsaux (lua_State *L) { - int i = luaL_checkint(L, 2); +/* +** Traversal function for 'ipairs' for raw tables +*/ +static int ipairsaux_raw (lua_State *L) { + int i = luaL_checkint(L, 2) + 1; luaL_checktype(L, 1, LUA_TTABLE); - i++; /* next value */ lua_pushinteger(L, i); return (lua_rawgeti(L, 1, i) == LUA_TNIL) ? 1 : 2; } +/* +** Traversal function for 'ipairs' for tables with metamethods +*/ +static int ipairsaux (lua_State *L) { + int i = luaL_checkint(L, 2) + 1; + if (i > luaL_len(L, 1)) { /* larger than length? */ + lua_pushnil(L); /* end traversal */ + return 1; + } + else { + lua_pushinteger(L, i); + lua_pushinteger(L, i); /* key for indexing table */ + lua_gettable(L, 1); + return 2; + } +} + + +/* +** This function will use either 'ipairsaux' or 'ipairsaux_raw' to +** traverse a table, depending on whether the table has metamethods +** that can affect the traversal. +*/ static int luaB_ipairs (lua_State *L) { - return pairsmeta(L, "__ipairs", 1, ipairsaux); + lua_CFunction iter = + (luaL_getmetafield(L, 1, "__len") || + luaL_getmetafield(L, 1, "__index")) + ? ipairsaux : ipairsaux_raw; +#if defined(LUA_COMPAT_IPAIRS) + return pairsmeta(L, "__ipairs", 1, iter); +#else + lua_pushcfunction(L, iter); /* iteration function */ + lua_pushvalue(L, 1); /* state */ + lua_pushinteger(L, 0); /* initial value */ + return 3; +#endif } @@ -341,7 +380,7 @@ static int luaB_load (lua_State *L) { /* }====================================================== */ -static int dofilecont (lua_State *L, int d1, int d2) { +static int dofilecont (lua_State *L, int d1, lua_Ctx d2) { (void)d1; (void)d2; /* only to match 'lua_Kfunction' prototype */ return lua_gettop(L) - 1; } @@ -387,12 +426,12 @@ static int luaB_select (lua_State *L) { /* ** Continuation function for 'pcall' and 'xpcall'. Both functions -** already pushed a 'true' before doing the call, so in case of sucess +** already pushed a 'true' before doing the call, so in case of success ** 'finishpcall' only has to return everything in the stack minus ** 'extra' values (where 'extra' is exactly the number of items to be ** ignored). */ -static int finishpcall (lua_State *L, int status, int extra) { +static int finishpcall (lua_State *L, int status, lua_Ctx extra) { if (status != LUA_OK && status != LUA_YIELD) { /* error? */ lua_pushboolean(L, 0); /* first result (false) */ lua_pushvalue(L, -2); /* error message */ @@ -461,21 +500,31 @@ static const luaL_Reg base_funcs[] = { {"setmetatable", luaB_setmetatable}, {"tonumber", luaB_tonumber}, {"tostring", luaB_tostring}, - {"type", luaB_type}, {"xpcall", luaB_xpcall}, + /* placeholders */ + {"type", NULL}, + {"_G", NULL}, + {"_VERSION", NULL}, {NULL, NULL} }; LUAMOD_API int luaopen_base (lua_State *L) { - /* set global _G */ - lua_pushglobaltable(L); - lua_pushglobaltable(L); - lua_setfield(L, -2, "_G"); + int i; /* open lib into global table */ + lua_pushglobaltable(L); luaL_setfuncs(L, base_funcs, 0); + /* set global _G */ + lua_pushvalue(L, -1); + lua_setfield(L, -2, "_G"); + /* set global _VERSION */ lua_pushliteral(L, LUA_VERSION); - lua_setfield(L, -2, "_VERSION"); /* set global _VERSION */ + lua_setfield(L, -2, "_VERSION"); + /* set function 'type' with proper upvalues */ + for (i = 0; i < LUA_NUMTAGS; i++) /* push all type names as upvalues */ + lua_pushstring(L, lua_typename(L, i)); + lua_pushcclosure(L, luaB_type, LUA_NUMTAGS); + lua_setfield(L, -2, "type"); return 1; } diff --git a/src/ldebug.c b/src/ldebug.c index c1f8c3f2..3321d9f1 100644 --- a/src/ldebug.c +++ b/src/ldebug.c @@ -1,5 +1,5 @@ /* -** $Id: ldebug.c,v 2.97 2013/12/09 14:21:10 roberto Exp $ +** $Id: ldebug.c,v 2.100 2014/07/30 14:00:14 roberto Exp $ ** Debug Interface ** See Copyright Notice in lua.h */ @@ -271,7 +271,7 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { if (*what == '>') { ci = NULL; func = L->top - 1; - api_check(L, ttisfunction(func), "function expected"); + api_check(ttisfunction(func), "function expected"); what++; /* skip the '>' */ L->top--; /* pop function */ } @@ -526,26 +526,27 @@ l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) { 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(p1)); + if (ttisstring(p1) || cvt2str(p1)) p1 = p2; luaG_typeerror(L, p1, "concatenate"); } l_noret luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { lua_Number temp; - if (!tonumber(p1, &temp)) - p2 = p1; /* first operand is wrong */ + if (!tonumber(p1, &temp)) /* first operand is wrong? */ + p2 = p1; /* now second is wrong */ luaG_typeerror(L, p2, "perform arithmetic on"); } +/* +** Error when both values are convertible to numbers, but not to integers +*/ 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)); + luaG_runerror(L, "number%s has no integer representation", varinfo(L, p2)); } @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 2.123 2014/06/19 18:27:20 roberto Exp $ +** $Id: ldo.c,v 2.126 2014/07/17 13:53:37 roberto Exp $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -516,7 +516,7 @@ static l_noret resume_error (lua_State *L, const char *msg, StkId firstArg) { /* ** Do the work for 'lua_resume' in protected mode. Most of the work ** depends on the status of the coroutine: initial state, suspended -** inside a hook, or regulary suspended (optionally with a continuation +** inside a hook, or regularly suspended (optionally with a continuation ** function), plus erroneous cases: non-suspended coroutine or dead ** coroutine. */ @@ -593,7 +593,8 @@ LUA_API int lua_isyieldable (lua_State *L) { } -LUA_API int lua_yieldk (lua_State *L, int nresults, int ctx, lua_KFunction k) { +LUA_API int lua_yieldk (lua_State *L, int nresults, lua_Ctx ctx, + lua_KFunction k) { CallInfo *ci = L->ci; luai_userstateyield(L, nresults); lua_lock(L); @@ -607,7 +608,7 @@ LUA_API int lua_yieldk (lua_State *L, int nresults, int ctx, lua_KFunction k) { L->status = LUA_YIELD; ci->extra = savestack(L, ci->func); /* save current 'func' */ if (isLua(ci)) { /* inside a hook? */ - api_check(L, k == NULL, "hooks cannot continue after yielding"); + api_check(k == NULL, "hooks cannot continue after yielding"); } else { if ((ci->u.c.k = k) != NULL) /* is there a continuation? */ diff --git a/src/ldump.c b/src/ldump.c index 0be56c65..4418f3be 100644 --- a/src/ldump.c +++ b/src/ldump.c @@ -1,5 +1,5 @@ /* -** $Id: ldump.c,v 2.32 2014/06/18 18:35:43 roberto Exp $ +** $Id: ldump.c,v 2.33 2014/07/18 13:36:14 roberto Exp $ ** save precompiled Lua chunks ** See Copyright Notice in lua.h */ @@ -71,7 +71,7 @@ static void DumpString (const TString *s, DumpState *D) { if (s == NULL) DumpByte(0, D); else { - size_t size = s->tsv.len + 1; /* include trailing '\0' */ + size_t size = s->len + 1; /* include trailing '\0' */ if (size < 0xFF) DumpByte(cast_int(size), D); else { @@ -112,7 +112,7 @@ static void DumpConstants (const Proto *f, DumpState *D) { break; case LUA_TSHRSTR: case LUA_TLNGSTR: - DumpString(rawtsvalue(o), D); + DumpString(tsvalue(o), D); break; default: lua_assert(0); @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 2.183 2014/05/25 19:08:32 roberto Exp $ +** $Id: lgc.c,v 2.192 2014/07/29 16:22:24 roberto Exp $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -62,10 +62,10 @@ */ #define maskcolors (~(bitmask(BLACKBIT) | WHITEBITS)) #define makewhite(g,x) \ - (gch(x)->marked = cast_byte((gch(x)->marked & maskcolors) | luaC_white(g))) + (x->marked = cast_byte((x->marked & maskcolors) | luaC_white(g))) -#define white2gray(x) resetbits(gch(x)->marked, WHITEBITS) -#define black2gray(x) resetbit(gch(x)->marked, BLACKBIT) +#define white2gray(x) resetbits(x->marked, WHITEBITS) +#define black2gray(x) resetbit(x->marked, BLACKBIT) #define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) @@ -81,7 +81,7 @@ if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); } #define markobject(g,t) \ - { if ((t) && iswhite(obj2gco(t))) reallymarkobject(g, obj2gco(t)); } + { if ((t) && iswhite(t)) reallymarkobject(g, obj2gco(t)); } static void reallymarkobject (global_State *g, GCObject *o); @@ -112,7 +112,7 @@ static void reallymarkobject (global_State *g, GCObject *o); static void removeentry (Node *n) { lua_assert(ttisnil(gval(n))); if (valiswhite(gkey(n))) - setdeadvalue(gkey(n)); /* unused and unmarked key; remove it */ + setdeadvalue(wgkey(n)); /* unused and unmarked key; remove it */ } @@ -126,7 +126,7 @@ static void removeentry (Node *n) { static int iscleared (global_State *g, const TValue *o) { if (!iscollectable(o)) return 0; else if (ttisstring(o)) { - markobject(g, rawtsvalue(o)); /* strings are `values', so are never weak */ + markobject(g, tsvalue(o)); /* strings are `values', so are never weak */ return 0; } else return iswhite(gcvalue(o)); @@ -135,13 +135,13 @@ static int iscleared (global_State *g, const TValue *o) { /* ** barrier that moves collector forward, that is, mark the white object -** being pointed by a black object. +** being pointed by a black object. (If in sweep phase, clear the black +** object to white [sweep it] to avoid other barrier calls for this +** same object.) */ void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) { global_State *g = G(L); lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); - lua_assert(g->gcstate != GCSpause); - lua_assert(gch(o)->tt != LUA_TTABLE); /* tables use a back barrier */ if (keepinvariant(g)) /* must keep invariant? */ reallymarkobject(g, v); /* restore invariant */ else { /* sweep phase */ @@ -153,16 +153,14 @@ void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) { /* ** barrier that moves collector backward, that is, mark the black object -** pointing to a white object as gray again. (Current implementation -** only works for tables; access to 'gclist' is not uniform across -** different types.) +** pointing to a white object as gray again. */ -void luaC_barrierback_ (lua_State *L, GCObject *o) { +void luaC_barrierback_ (lua_State *L, Table *t) { global_State *g = G(L); - lua_assert(isblack(o) && !isdead(g, o) && gch(o)->tt == LUA_TTABLE); - black2gray(o); /* make object gray (again) */ - gco2t(o)->gclist = g->grayagain; - g->grayagain = o; + lua_assert(isblack(t) && !isdead(g, t)); + black2gray(t); /* make table gray (again) */ + t->gclist = g->grayagain; + g->grayagain = obj2gco(t); } @@ -185,8 +183,8 @@ void luaC_fix (lua_State *L, GCObject *o) { global_State *g = G(L); lua_assert(g->allgc == o); /* object must be 1st in 'allgc' list! */ white2gray(o); /* they will be gray forever */ - g->allgc = o->gch.next; /* remove object from 'allgc' list */ - o->gch.next = g->fixedgc; /* link it to 'fixedgc' list */ + g->allgc = o->next; /* remove object from 'allgc' list */ + o->next = g->fixedgc; /* link it to 'fixedgc' list */ g->fixedgc = o; } @@ -198,9 +196,9 @@ void luaC_fix (lua_State *L, GCObject *o) { GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { global_State *g = G(L); GCObject *o = cast(GCObject *, luaM_newobject(L, novariant(tt), sz)); - gch(o)->marked = luaC_white(g); - gch(o)->tt = tt; - gch(o)->next = g->allgc; + o->marked = luaC_white(g); + o->tt = tt; + o->next = g->allgc; g->allgc = o; return o; } @@ -225,7 +223,7 @@ GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { static void reallymarkobject (global_State *g, GCObject *o) { reentry: white2gray(o); - switch (gch(o)->tt) { + switch (o->tt) { case LUA_TSHRSTR: case LUA_TLNGSTR: { gray2black(o); @@ -237,7 +235,7 @@ static void reallymarkobject (global_State *g, GCObject *o) { markobject(g, gco2u(o)->metatable); /* mark its metatable */ gray2black(o); g->GCmemtrav += sizeudata(gco2u(o)); - getuservalue(g->mainthread, rawgco2u(o), &uvalue); + getuservalue(g->mainthread, gco2u(o), &uvalue); if (valiswhite(&uvalue)) { /* markvalue(g, &uvalue); */ o = gcvalue(&uvalue); goto reentry; @@ -288,7 +286,7 @@ static void markmt (global_State *g) { */ static void markbeingfnz (global_State *g) { GCObject *o; - for (o = g->tobefnz; o != NULL; o = gch(o)->next) + for (o = g->tobefnz; o != NULL; o = o->next) markobject(g, o); } @@ -303,8 +301,8 @@ static void remarkupvals (global_State *g) { lua_State *thread; lua_State **p = &g->twups; while ((thread = *p) != NULL) { - lua_assert(!isblack(obj2gco(thread))); /* threads are never black */ - if (isgray(obj2gco(thread)) && thread->openupval != NULL) + lua_assert(!isblack(thread)); /* threads are never black */ + if (isgray(thread) && thread->openupval != NULL) p = &thread->twups; /* keep marked thread with upvalues in the list */ else { /* thread is not marked or without upvalues */ UpVal *uv; @@ -429,7 +427,7 @@ static lu_mem traversetable (global_State *g, Table *h) { ((weakkey = strchr(svalue(mode), 'k')), (weakvalue = strchr(svalue(mode), 'v')), (weakkey || weakvalue))) { /* is really weak? */ - black2gray(obj2gco(h)); /* keep table gray */ + black2gray(h); /* keep table gray */ if (!weakkey) /* strong keys? */ traverseweakvalue(g, h); else if (!weakvalue) /* strong values? */ @@ -446,7 +444,7 @@ static lu_mem traversetable (global_State *g, Table *h) { static int traverseproto (global_State *g, Proto *f) { int i; - if (f->cache && iswhite(obj2gco(f->cache))) + if (f->cache && iswhite(f->cache)) f->cache = NULL; /* allow cache to be collected */ markobject(g, f->source); for (i = 0; i < f->sizek; i++) /* mark literals */ @@ -528,7 +526,7 @@ static void propagatemark (global_State *g) { GCObject *o = g->gray; lua_assert(isgray(o)); gray2black(o); - switch (gch(o)->tt) { + switch (o->tt) { case LUA_TTABLE: { Table *h = gco2t(o); g->gray = h->gclist; /* remove from 'gray' list */ @@ -685,7 +683,7 @@ static void freeLclosure (lua_State *L, LClosure *cl) { static void freeobj (lua_State *L, GCObject *o) { - switch (gch(o)->tt) { + switch (o->tt) { case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; case LUA_TLCL: { freeLclosure(L, gco2lcl(o)); @@ -699,7 +697,7 @@ static void freeobj (lua_State *L, GCObject *o) { case LUA_TTHREAD: luaE_freethread(L, gco2th(o)); break; case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break; case LUA_TSHRSTR: - luaS_remove(L, rawgco2ts(o)); /* remove it from hash table */ + luaS_remove(L, gco2ts(o)); /* remove it from hash table */ /* go through */ case LUA_TLNGSTR: { luaM_freemem(L, o, sizestring(gco2ts(o))); @@ -727,14 +725,14 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { int white = luaC_white(g); /* current white */ while (*p != NULL && count-- > 0) { GCObject *curr = *p; - int marked = gch(curr)->marked; + int marked = curr->marked; if (isdeadm(ow, marked)) { /* is 'curr' dead? */ - *p = gch(curr)->next; /* remove 'curr' from list */ + *p = curr->next; /* remove 'curr' from list */ freeobj(L, curr); /* erase 'curr' */ } else { /* update marks */ - gch(curr)->marked = cast_byte((marked & maskcolors) | white); - p = &gch(curr)->next; /* go to next element */ + curr->marked = cast_byte((marked & maskcolors) | white); + p = &curr->next; /* go to next element */ } } return (*p == NULL) ? NULL : p; @@ -781,10 +779,10 @@ static void checkSizes (lua_State *L, global_State *g) { static GCObject *udata2finalize (global_State *g) { GCObject *o = g->tobefnz; /* get first element */ lua_assert(tofinalize(o)); - g->tobefnz = gch(o)->next; /* remove it from 'tobefnz' list */ - gch(o)->next = g->allgc; /* return it to 'allgc' list */ + g->tobefnz = o->next; /* remove it from 'tobefnz' list */ + o->next = g->allgc; /* return it to 'allgc' list */ g->allgc = o; - resetbit(gch(o)->marked, FINALIZEDBIT); /* object is "normal" again */ + resetbit(o->marked, FINALIZEDBIT); /* object is "normal" again */ if (issweepphase(g)) makewhite(g, o); /* "sweep" object */ return o; @@ -859,7 +857,7 @@ static void callallpendingfinalizers (lua_State *L, int propagateerrors) { */ static GCObject **findlast (GCObject **p) { while (*p != NULL) - p = &gch(*p)->next; + p = &(*p)->next; return p; } @@ -875,12 +873,12 @@ static void separatetobefnz (global_State *g, int all) { while ((curr = *p) != NULL) { /* traverse all finalizable objects */ lua_assert(tofinalize(curr)); if (!(iswhite(curr) || all)) /* not being collected? */ - p = &gch(curr)->next; /* don't bother with it */ + p = &curr->next; /* don't bother with it */ else { - *p = gch(curr)->next; /* remove 'curr' from "fin" list */ - gch(curr)->next = *lastnext; /* link at the end of 'tobefnz' list */ + *p = curr->next; /* remove 'curr' from "fin" list */ + curr->next = *lastnext; /* link at the end of 'tobefnz' list */ *lastnext = curr; - lastnext = &gch(curr)->next; + lastnext = &curr->next; } } } @@ -899,15 +897,15 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { GCObject **p; if (issweepphase(g)) { makewhite(g, o); /* "sweep" object 'o' */ - if (g->sweepgc == &o->gch.next) /* shoud not remove 'sweepgc' object */ + if (g->sweepgc == &o->next) /* should not remove 'sweepgc' object */ g->sweepgc = sweeptolive(L, g->sweepgc, NULL); /* change 'sweepgc' */ } /* search for pointer pointing to 'o' */ - for (p = &g->allgc; *p != o; p = &gch(*p)->next) { /* empty */ } - *p = o->gch.next; /* remove 'o' from 'allgc' list */ - o->gch.next = g->finobj; /* link it in "fin" list */ + for (p = &g->allgc; *p != o; p = &(*p)->next) { /* empty */ } + *p = o->next; /* remove 'o' from 'allgc' list */ + o->next = g->finobj; /* link it in "fin" list */ g->finobj = o; - l_setbit(o->gch.marked, FINALIZEDBIT); /* mark it as such */ + l_setbit(o->marked, FINALIZEDBIT); /* mark it as such */ } } @@ -975,7 +973,7 @@ static l_mem atomic (lua_State *L) { l_mem work; GCObject *origweak, *origall; g->GCmemtrav = 0; /* start counting work */ - lua_assert(!iswhite(obj2gco(g->mainthread))); + lua_assert(!iswhite(g->mainthread)); g->gcstate = GCSinsideatomic; markobject(g, L); /* mark running thread */ /* registry and global metatables may be changed by API */ @@ -1066,7 +1064,7 @@ static lu_mem singlestep (lua_State *L) { return sweepstep(L, g, GCSswpend, NULL); } case GCSswpend: { /* finish sweeps */ - makewhite(g, obj2gco(g->mainthread)); /* sweep main thread */ + makewhite(g, g->mainthread); /* sweep main thread */ checkSizes(L, g); g->gcstate = GCScallfin; return 0; @@ -1,5 +1,5 @@ /* -** $Id: lgc.h,v 2.82 2014/03/19 18:51:16 roberto Exp $ +** $Id: lgc.h,v 2.85 2014/07/19 15:14:46 roberto Exp $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -84,19 +84,19 @@ #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) -#define iswhite(x) testbits((x)->gch.marked, WHITEBITS) -#define isblack(x) testbit((x)->gch.marked, BLACKBIT) +#define iswhite(x) testbits((x)->marked, WHITEBITS) +#define isblack(x) testbit((x)->marked, BLACKBIT) #define isgray(x) /* neither white nor black */ \ - (!testbits((x)->gch.marked, WHITEBITS | bitmask(BLACKBIT))) + (!testbits((x)->marked, WHITEBITS | bitmask(BLACKBIT))) -#define tofinalize(x) testbit((x)->gch.marked, FINALIZEDBIT) +#define tofinalize(x) testbit((x)->marked, FINALIZEDBIT) #define otherwhite(g) ((g)->currentwhite ^ WHITEBITS) #define isdeadm(ow,m) (!(((m) ^ WHITEBITS) & (ow))) -#define isdead(g,v) isdeadm(otherwhite(g), (v)->gch.marked) +#define isdead(g,v) isdeadm(otherwhite(g), (v)->marked) -#define changewhite(x) ((x)->gch.marked ^= WHITEBITS) -#define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) +#define changewhite(x) ((x)->marked ^= WHITEBITS) +#define gray2black(x) l_setbit((x)->marked, BLACKBIT) #define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) @@ -107,15 +107,15 @@ #define luaC_barrier(L,p,v) { \ - if (iscollectable(v) && isblack(obj2gco(p)) && iswhite(gcvalue(v))) \ + if (iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) \ luaC_barrier_(L,obj2gco(p),gcvalue(v)); } #define luaC_barrierback(L,p,v) { \ - if (iscollectable(v) && isblack(obj2gco(p)) && iswhite(gcvalue(v))) \ - luaC_barrierback_(L,obj2gco(p)); } + if (iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) \ + luaC_barrierback_(L,p); } #define luaC_objbarrier(L,p,o) { \ - if (isblack(obj2gco(p)) && iswhite(obj2gco(o))) \ + if (isblack(p) && iswhite(o)) \ luaC_barrier_(L,obj2gco(p),obj2gco(o)); } #define luaC_upvalbarrier(L,uv) \ @@ -129,7 +129,7 @@ LUAI_FUNC void luaC_runtilstate (lua_State *L, int statesmask); LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency); LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz); LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v); -LUAI_FUNC void luaC_barrierback_ (lua_State *L, GCObject *o); +LUAI_FUNC void luaC_barrierback_ (lua_State *L, Table *o); LUAI_FUNC void luaC_upvalbarrier_ (lua_State *L, UpVal *uv); LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt); LUAI_FUNC void luaC_upvdeccount (lua_State *L, UpVal *uv); diff --git a/src/liolib.c b/src/liolib.c index 5613aa1a..96cb1a31 100644 --- a/src/liolib.c +++ b/src/liolib.c @@ -1,5 +1,5 @@ /* -** $Id: liolib.c,v 2.126 2014/06/02 03:00:51 roberto Exp $ +** $Id: liolib.c,v 2.128 2014/07/29 16:01:00 roberto Exp $ ** Standard I/O (and system) library ** See Copyright Notice in lua.h */ @@ -402,11 +402,11 @@ static int test2 (RN *rn, const char *set) { /* -** Read a sequence of (hexa)digits +** Read a sequence of (hex)digits */ -static int readdigits (RN *rn, int hexa) { +static int readdigits (RN *rn, int hex) { int count = 0; - while ((hexa ? isxdigit(rn->c) : isdigit(rn->c)) && nextc(rn)) + while ((hex ? isxdigit(rn->c) : isdigit(rn->c)) && nextc(rn)) count++; return count; } @@ -426,7 +426,7 @@ static int readdigits (RN *rn, int hexa) { static int read_number (lua_State *L, FILE *f) { RN rn; int count = 0; - int hexa = 0; + int hex = 0; char decp[2] = "."; rn.f = f; rn.n = 0; decp[0] = getlocaledecpoint(); /* get decimal point from locale */ @@ -434,13 +434,13 @@ static int read_number (lua_State *L, FILE *f) { do { rn.c = l_getc(rn.f); } while (isspace(rn.c)); /* skip spaces */ test2(&rn, "-+"); /* optional signal */ if (test2(&rn, "0")) { - if (test2(&rn, "xX")) hexa = 1; /* numeral is hexadecimal */ + if (test2(&rn, "xX")) hex = 1; /* numeral is hexadecimal */ else count = 1; /* count initial '0' as a valid digit */ } - count += readdigits(&rn, hexa); /* integral part */ + count += readdigits(&rn, hex); /* integral part */ if (test2(&rn, decp)) /* decimal point? */ - count += readdigits(&rn, hexa); /* fractionary part */ - if (count > 0 && test2(&rn, (hexa ? "pP" : "eE"))) { /* exponent mark? */ + count += readdigits(&rn, hex); /* fractional part */ + if (count > 0 && test2(&rn, (hex ? "pP" : "eE"))) { /* exponent mark? */ test2(&rn, "-+"); /* exponent signal */ readdigits(&rn, 0); /* exponent digits */ } @@ -654,7 +654,7 @@ static int f_setvbuf (lua_State *L) { FILE *f = tofile(L); int op = luaL_checkoption(L, 2, NULL, modenames); lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE); - int res = setvbuf(f, NULL, mode[op], sz); + int res = setvbuf(f, NULL, mode[op], (size_t)sz); return luaL_fileresult(L, res == 0, NULL); } @@ -1,5 +1,5 @@ /* -** $Id: llex.c,v 2.78 2014/05/21 15:22:02 roberto Exp $ +** $Id: llex.c,v 2.80 2014/07/18 13:36:14 roberto Exp $ ** Lexical Analyzer ** See Copyright Notice in lua.h */ @@ -71,7 +71,7 @@ void luaX_init (lua_State *L) { for (i=0; i<NUM_RESERVED; i++) { TString *ts = luaS_new(L, luaX_tokens[i]); luaC_fix(L, obj2gco(ts)); /* reserved words are never collected */ - ts->tsv.extra = cast_byte(i+1); /* reserved word */ + ts->extra = cast_byte(i+1); /* reserved word */ } } @@ -137,7 +137,7 @@ TString *luaX_newstring (LexState *ls, const char *str, size_t l) { luaC_checkGC(L); } else { /* string already present */ - ts = rawtsvalue(keyfromval(o)); /* re-use value previously stored */ + ts = tsvalue(keyfromval(o)); /* re-use value previously stored */ } L->top--; /* remove string from stack */ return ts; @@ -565,7 +565,7 @@ static int llex (LexState *ls, SemInfo *seminfo) { luaZ_bufflen(ls->buff)); seminfo->ts = ts; if (isreserved(ts)) /* reserved word? */ - return ts->tsv.extra - 1 + FIRST_RESERVED; + return ts->extra - 1 + FIRST_RESERVED; else { return TK_NAME; } diff --git a/src/llimits.h b/src/llimits.h index b3f7774d..1f41e257 100644 --- a/src/llimits.h +++ b/src/llimits.h @@ -1,5 +1,5 @@ /* -** $Id: llimits.h,v 1.116 2014/04/15 16:32:49 roberto Exp $ +** $Id: llimits.h,v 1.120 2014/07/18 18:29:12 roberto Exp $ ** Limits, basic types, and some other `installation-dependent' definitions ** See Copyright Notice in lua.h */ @@ -28,36 +28,37 @@ typedef unsigned char lu_byte; /* maximum value for size_t */ -#define MAX_SIZET ((size_t)(~(size_t)0)-2) +#define MAX_SIZET ((size_t)(~(size_t)0)) /* 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_MAXINTEGER)-2) + : (size_t)(LUA_MAXINTEGER)) -#define MAX_LUMEM ((lu_mem)(~(lu_mem)0)-2) +#define MAX_LUMEM ((lu_mem)(~(lu_mem)0)) -#define MAX_LMEM ((l_mem) ((MAX_LUMEM >> 1) - 2)) +#define MAX_LMEM ((l_mem)(MAX_LUMEM >> 1)) -#define MAX_INT (INT_MAX-2) /* maximum value of an int (-2 for safety) */ +#define MAX_INT INT_MAX /* maximum value of an int */ /* -** conversion of pointer to integer +** conversion of pointer to integer: ** this is for hashing only; there is no problem if the integer ** cannot hold the whole pointer value */ -#define IntPoint(p) ((unsigned int)(lu_mem)(p)) +#define point2int(p) ((unsigned int)((lu_mem)(p) & UINT_MAX)) /* type to ensure maximum alignment */ -#if !defined(LUAI_USER_ALIGNMENT_T) -#define LUAI_USER_ALIGNMENT_T union { double u; void *s; long l; } +#if defined(LUAI_USER_ALIGNMENT_T) +typedef LUAI_USER_ALIGNMENT_T L_Umaxalign; +#else +typedef union { double u; void *s; lua_Integer i; long l; } L_Umaxalign; #endif -typedef LUAI_USER_ALIGNMENT_T L_Umaxalign; /* types of 'usual argument conversions' for lua_Number and lua_Integer */ @@ -79,18 +80,15 @@ typedef LUAI_UACINT l_uacInt; /* ** assertion for checking API calls */ -#if !defined(luai_apicheck) - #if defined(LUA_USE_APICHECK) #include <assert.h> -#define luai_apicheck(L,e) assert(e) +#define luai_apicheck(e) assert(e) #else -#define luai_apicheck(L,e) lua_assert(e) +#define luai_apicheck(e) lua_assert(e) #endif -#endif -#define api_check(l,e,msg) luai_apicheck(l,(e) && msg) +#define api_check(e,msg) luai_apicheck((e) && msg) #if !defined(UNUSED) diff --git a/src/lmathlib.c b/src/lmathlib.c index 145b35ab..312df517 100644 --- a/src/lmathlib.c +++ b/src/lmathlib.c @@ -1,5 +1,5 @@ /* -** $Id: lmathlib.c,v 1.103 2014/06/18 12:35:53 roberto Exp $ +** $Id: lmathlib.c,v 1.108 2014/07/28 17:35:47 roberto Exp $ ** Standard mathematical library ** See Copyright Notice in lua.h */ @@ -76,39 +76,39 @@ static int math_atan (lua_State *L) { } -static int math_ifloor (lua_State *L) { +static int math_toint (lua_State *L) { int valid; lua_Integer n = lua_tointegerx(L, 1, &valid); if (valid) - lua_pushinteger(L, n); /* floor computed by Lua */ + lua_pushinteger(L, n); else { - luaL_checktype(L, 1, LUA_TNUMBER); /* argument must be a number */ - lua_pushnil(L); /* number is not convertible to integer */ + luaL_checkany(L, 1); + lua_pushnil(L); /* value is not convertible to integer */ } return 1; } -static int math_floor (lua_State *L) { - int valid; - lua_Integer n = lua_tointegerx(L, 1, &valid); - if (valid) - lua_pushinteger(L, n); /* floor computed by Lua */ - else - lua_pushnumber(L, l_mathop(floor)(luaL_checknumber(L, 1))); - return 1; -} - - static void pushnumint (lua_State *L, lua_Number d) { lua_Integer n; - if (lua_numtointeger(d, &n)) /* fits in an integer? */ + if (lua_numtointeger(d, &n)) /* does 'd' fit in an integer? */ lua_pushinteger(L, n); /* result is integer */ else lua_pushnumber(L, d); /* result is float */ } +static int math_floor (lua_State *L) { + if (lua_isinteger(L, 1)) + lua_settop(L, 1); /* integer is its own floor */ + else { + lua_Number d = l_mathop(floor)(luaL_checknumber(L, 1)); + pushnumint(L, d); + } + return 1; +} + + static int math_ceil (lua_State *L) { if (lua_isinteger(L, 1)) lua_settop(L, 1); /* integer is its own ceil */ @@ -145,14 +145,14 @@ static int math_fmod (lua_State *L) { static int math_modf (lua_State *L) { if (lua_isinteger(L ,1)) { lua_settop(L, 1); /* number is its own integer part */ - lua_pushnumber(L, 0); /* no fractionary part */ + lua_pushnumber(L, 0); /* no fractional part */ } else { lua_Number n = luaL_checknumber(L, 1); /* integer part (rounds toward zero) */ lua_Number ip = (n < 0) ? l_mathop(ceil)(n) : l_mathop(floor)(n); pushnumint(L, ip); - /* fractionary part (test needed for inf/-inf) */ + /* fractional part (test needed for inf/-inf) */ lua_pushnumber(L, (n == ip) ? 0.0 : (n - ip)); } return 2; @@ -164,6 +164,14 @@ static int math_sqrt (lua_State *L) { return 1; } + +static int math_ult (lua_State *L) { + lua_Integer a = luaL_checkinteger(L, 1); + lua_Integer b = luaL_checkinteger(L, 2); + lua_pushboolean(L, (lua_Unsigned)a < (lua_Unsigned)b); + return 1; +} + static int math_log (lua_State *L) { lua_Number x = luaL_checknumber(L, 1); lua_Number res; @@ -257,22 +265,23 @@ static int math_random (lua_State *L) { static int math_randomseed (lua_State *L) { - l_srand((unsigned int)luaL_checkunsigned(L, 1)); + l_srand((unsigned int)(lua_Integer)luaL_checknumber(L, 1)); (void)rand(); /* discard first value to avoid undesirable correlations */ return 0; } static int math_type (lua_State *L) { - luaL_checkany(L, 1); if (lua_type(L, 1) == LUA_TNUMBER) { if (lua_isinteger(L, 1)) lua_pushliteral(L, "integer"); else lua_pushliteral(L, "float"); } - else + else { + luaL_checkany(L, 1); lua_pushnil(L); + } return 1; } @@ -339,9 +348,10 @@ static const luaL_Reg mathlib[] = { {"cos", math_cos}, {"deg", math_deg}, {"exp", math_exp}, - {"ifloor", math_ifloor}, + {"tointeger", math_toint}, {"floor", math_floor}, {"fmod", math_fmod}, + {"ult", math_ult}, {"log", math_log}, {"max", math_max}, {"min", math_min}, @@ -363,6 +373,11 @@ static const luaL_Reg mathlib[] = { {"ldexp", math_ldexp}, {"log10", math_log10}, #endif + /* placeholders */ + {"pi", NULL}, + {"huge", NULL}, + {"maxinteger", NULL}, + {"mininteger", NULL}, {NULL, NULL} }; @@ -1,5 +1,5 @@ /* -** $Id: lmem.c,v 1.84 2012/05/23 15:41:53 roberto Exp $ +** $Id: lmem.c,v 1.86 2014/07/15 21:26:50 roberto Exp $ ** Interface to Memory Manager ** See Copyright Notice in lua.h */ @@ -83,12 +83,10 @@ void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { #endif newblock = (*g->frealloc)(g->ud, block, osize, nsize); if (newblock == NULL && nsize > 0) { - api_check(L, nsize > realosize, + api_check( nsize > realosize, "realloc cannot fail when shrinking a block"); - if (g->gcrunning) { - luaC_fullgc(L, 1); /* try to free some memory... */ - newblock = (*g->frealloc)(g->ud, block, osize, nsize); /* try again */ - } + luaC_fullgc(L, 1); /* try to free some memory... */ + newblock = (*g->frealloc)(g->ud, block, osize, nsize); /* try again */ if (newblock == NULL) luaD_throw(L, LUA_ERRMEM); } diff --git a/src/loadlib.c b/src/loadlib.c index 5333311d..4894188a 100644 --- a/src/loadlib.c +++ b/src/loadlib.c @@ -1,5 +1,5 @@ /* -** $Id: loadlib.c,v 1.113 2014/03/12 20:57:40 roberto Exp $ +** $Id: loadlib.c,v 1.116 2014/07/29 16:01:00 roberto Exp $ ** Dynamic library loader for Lua ** See Copyright Notice in lua.h ** @@ -97,20 +97,33 @@ #define LIB_FAIL "open" - -/* error codes for ll_loadfunc */ -#define ERRLIB 1 -#define ERRFUNC 2 - #define setprogdir(L) ((void)0) /* ** system-dependent functions */ -static void ll_unloadlib (void *lib); -static void *ll_load (lua_State *L, const char *path, int seeglb); -static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym); + +/* +** unload library 'lib' +*/ +static void lsys_unloadlib (void *lib); + +/* +** load C library in file 'path'. If 'seeglb', load with all names in +** the library global. +** Returns the library; in case of error, returns NULL plus an +** error string in the stack. +*/ +static void *lsys_load (lua_State *L, const char *path, int seeglb); + +/* +** Try to find a function named 'sym' in library 'lib'. +** Returns the function; in case of error, returns NULL plus an +** error string in the stack. +*/ +static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym); + @@ -126,19 +139,19 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym); #include <dlfcn.h> -static void ll_unloadlib (void *lib) { +static void lsys_unloadlib (void *lib) { dlclose(lib); } -static void *ll_load (lua_State *L, const char *path, int seeglb) { +static void *lsys_load (lua_State *L, const char *path, int seeglb) { void *lib = dlopen(path, RTLD_NOW | (seeglb ? RTLD_GLOBAL : RTLD_LOCAL)); if (lib == NULL) lua_pushstring(L, dlerror()); return lib; } -static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { +static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) { lua_CFunction f = (lua_CFunction)dlsym(lib, sym); if (f == NULL) lua_pushstring(L, dlerror()); return f; @@ -190,12 +203,12 @@ static void pusherror (lua_State *L) { lua_pushfstring(L, "system error %d\n", error); } -static void ll_unloadlib (void *lib) { +static void lsys_unloadlib (void *lib) { FreeLibrary((HMODULE)lib); } -static void *ll_load (lua_State *L, const char *path, int seeglb) { +static void *lsys_load (lua_State *L, const char *path, int seeglb) { HMODULE lib = LoadLibraryExA(path, NULL, LUA_LLE_FLAGS); (void)(seeglb); /* not used: symbols are 'global' by default */ if (lib == NULL) pusherror(L); @@ -203,7 +216,7 @@ static void *ll_load (lua_State *L, const char *path, int seeglb) { } -static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { +static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) { lua_CFunction f = (lua_CFunction)GetProcAddress((HMODULE)lib, sym); if (f == NULL) pusherror(L); return f; @@ -226,19 +239,19 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { #define DLMSG "dynamic libraries not enabled; check your Lua installation" -static void ll_unloadlib (void *lib) { +static void lsys_unloadlib (void *lib) { (void)(lib); /* not used */ } -static void *ll_load (lua_State *L, const char *path, int seeglb) { +static void *lsys_load (lua_State *L, const char *path, int seeglb) { (void)(path); (void)(seeglb); /* not used */ lua_pushliteral(L, DLMSG); return NULL; } -static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { +static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) { (void)(lib); (void)(sym); /* not used */ lua_pushliteral(L, DLMSG); return NULL; @@ -248,7 +261,10 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { #endif -static void *ll_checkclib (lua_State *L, const char *path) { +/* +** return registry.CLIBS[path] +*/ +static void *checkclib (lua_State *L, const char *path) { void *plib; lua_getfield(L, LUA_REGISTRYINDEX, CLIBS); lua_getfield(L, -1, path); @@ -258,7 +274,11 @@ static void *ll_checkclib (lua_State *L, const char *path) { } -static void ll_addtoclib (lua_State *L, const char *path, void *plib) { +/* +** registry.CLIBS[path] = plib -- for queries +** registry.CLIBS[#CLIBS + 1] = plib -- also keep a list of all libraries +*/ +static void addtoclib (lua_State *L, const char *path, void *plib) { lua_getfield(L, LUA_REGISTRYINDEX, CLIBS); lua_pushlightuserdata(L, plib); lua_pushvalue(L, -1); @@ -269,33 +289,49 @@ static void ll_addtoclib (lua_State *L, const char *path, void *plib) { /* -** __gc tag method for CLIBS table: calls 'll_unloadlib' for all lib +** __gc tag method for CLIBS table: calls 'lsys_unloadlib' for all lib ** handles in list CLIBS */ static int gctm (lua_State *L) { - int n = luaL_len(L, 1); + lua_Integer n = luaL_len(L, 1); for (; n >= 1; n--) { /* for each handle, in reverse order */ lua_rawgeti(L, 1, n); /* get handle CLIBS[n] */ - ll_unloadlib(lua_touserdata(L, -1)); + lsys_unloadlib(lua_touserdata(L, -1)); lua_pop(L, 1); /* pop handle */ } return 0; } -static int ll_loadfunc (lua_State *L, const char *path, const char *sym) { - void *reg = ll_checkclib(L, path); /* check loaded C libraries */ + +/* error codes for 'lookforfunc' */ +#define ERRLIB 1 +#define ERRFUNC 2 + +/* +** Look for a C function named 'sym' in a dynamically loaded library +** 'path'. +** First, check whether the library is already loaded; if not, try +** to load it. +** Then, if 'sym' is '*', return true (as library has been loaded). +** Otherwise, look for symbol 'sym' in the library and push a +** C function with that symbol. +** Return 0 and 'true' or a function in the stack; in case of +** errors, return an error code and an error message in the stack. +*/ +static int lookforfunc (lua_State *L, const char *path, const char *sym) { + void *reg = checkclib(L, path); /* check loaded C libraries */ if (reg == NULL) { /* must load library? */ - reg = ll_load(L, path, *sym == '*'); + reg = lsys_load(L, path, *sym == '*'); /* global symbols if 'sym'=='*' */ if (reg == NULL) return ERRLIB; /* unable to load library */ - ll_addtoclib(L, path, reg); + addtoclib(L, path, reg); } if (*sym == '*') { /* loading only library (no function)? */ lua_pushboolean(L, 1); /* return 'true' */ return 0; /* no errors */ } else { - lua_CFunction f = ll_sym(L, reg, sym); + lua_CFunction f = lsys_sym(L, reg, sym); if (f == NULL) return ERRFUNC; /* unable to find function */ lua_pushcfunction(L, f); /* else create new function */ @@ -307,7 +343,7 @@ static int ll_loadfunc (lua_State *L, const char *path, const char *sym) { static int ll_loadlib (lua_State *L) { const char *path = luaL_checkstring(L, 1); const char *init = luaL_checkstring(L, 2); - int stat = ll_loadfunc(L, path, init); + int stat = lookforfunc(L, path, init); if (stat == 0) /* no errors? */ return 1; /* return the loaded function */ else { /* error; error message is on stack top */ @@ -416,21 +452,29 @@ static int searcher_Lua (lua_State *L) { } +/* +** Try to find a load function for module 'modname' at file 'filename'. +** First, change '.' to '_' in 'modname'; then, if 'modname' has +** the form X-Y (that is, it has an "ignore mark"), build a function +** name "luaopen_X" and look for it. (For compatibility, if that +** fails, it also tries "luaopen_Y".) If there is no ignore mark, +** look for a function named "luaopen_modname". +*/ static int loadfunc (lua_State *L, const char *filename, const char *modname) { - const char *funcname; + const char *openfunc; const char *mark; modname = luaL_gsub(L, modname, ".", LUA_OFSEP); mark = strchr(modname, *LUA_IGMARK); if (mark) { int stat; - funcname = lua_pushlstring(L, modname, mark - modname); - funcname = lua_pushfstring(L, LUA_POF"%s", funcname); - stat = ll_loadfunc(L, filename, funcname); + openfunc = lua_pushlstring(L, modname, mark - modname); + openfunc = lua_pushfstring(L, LUA_POF"%s", openfunc); + stat = lookforfunc(L, filename, openfunc); if (stat != ERRFUNC) return stat; modname = mark + 1; /* else go ahead and try old-style name */ } - funcname = lua_pushfstring(L, LUA_POF"%s", modname); - return ll_loadfunc(L, filename, funcname); + openfunc = lua_pushfstring(L, LUA_POF"%s", modname); + return lookforfunc(L, filename, openfunc); } @@ -655,6 +699,12 @@ static const luaL_Reg pk_funcs[] = { #if defined(LUA_COMPAT_MODULE) {"seeall", ll_seeall}, #endif + /* placeholders */ + {"preload", NULL}, + {"cpath", NULL}, + {"path", NULL}, + {"searchers", NULL}, + {"loaded", NULL}, {NULL, NULL} }; @@ -680,24 +730,31 @@ static void createsearcherstable (lua_State *L) { lua_pushcclosure(L, searchers[i], 1); lua_rawseti(L, -2, i+1); } +#if defined(LUA_COMPAT_LOADERS) + lua_pushvalue(L, -1); /* make a copy of 'searchers' table */ + lua_setfield(L, -3, "loaders"); /* put it in field `loaders' */ +#endif + lua_setfield(L, -2, "searchers"); /* put it in field 'searchers' */ } -LUAMOD_API int luaopen_package (lua_State *L) { - /* create table CLIBS to keep track of loaded C libraries */ - luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS); - lua_createtable(L, 0, 1); /* metatable for CLIBS */ +/* +** create table CLIBS to keep track of loaded C libraries, +** setting a finalizer to close all libraries when closing state. +*/ +static void createclibstable (lua_State *L) { + luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS); /* create CLIBS table */ + lua_createtable(L, 0, 1); /* create metatable for CLIBS */ lua_pushcfunction(L, gctm); lua_setfield(L, -2, "__gc"); /* set finalizer for CLIBS table */ lua_setmetatable(L, -2); - /* create `package' table */ - luaL_newlib(L, pk_funcs); +} + + +LUAMOD_API int luaopen_package (lua_State *L) { + createclibstable(L); + luaL_newlib(L, pk_funcs); /* create `package' table */ createsearcherstable(L); -#if defined(LUA_COMPAT_LOADERS) - lua_pushvalue(L, -1); /* make a copy of 'searchers' table */ - lua_setfield(L, -3, "loaders"); /* put it in field `loaders' */ -#endif - lua_setfield(L, -2, "searchers"); /* put it in field 'searchers' */ /* set field 'path' */ setpath(L, "path", LUA_PATHVARVERSION, LUA_PATH_VAR, LUA_PATH_DEFAULT); /* set field 'cpath' */ diff --git a/src/lobject.c b/src/lobject.c index 0130c1c0..2bcdbfa1 100644 --- a/src/lobject.c +++ b/src/lobject.c @@ -1,5 +1,5 @@ /* -** $Id: lobject.c,v 2.86 2014/05/12 21:44:17 roberto Exp $ +** $Id: lobject.c,v 2.88 2014/07/30 14:00:14 roberto Exp $ ** Some generic functions over Lua objects ** See Copyright Notice in lua.h */ @@ -256,7 +256,7 @@ static const char *l_str2d (const char *s, lua_Number *result) { char *endptr; if (strpbrk(s, "nN")) /* reject 'inf' and 'nan' */ return NULL; - else if (strpbrk(s, "xX")) /* hexa? */ + else if (strpbrk(s, "xX")) /* hex? */ *result = lua_strx2number(s, &endptr); else *result = lua_str2number(s, &endptr); @@ -273,7 +273,7 @@ static const char *l_str2int (const char *s, lua_Integer *result) { while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ neg = isneg(&s); if (s[0] == '0' && - (s[1] == 'x' || s[1] == 'X')) { /* hexa? */ + (s[1] == 'x' || s[1] == 'X')) { /* hex? */ s += 2; /* skip '0x' */ for (; lisxdigit(cast_uchar(*s)); s++) { a = a * 16 + luaO_hexavalue(cast_uchar(*s)); @@ -327,6 +327,32 @@ int luaO_utf8esc (char *buff, unsigned int x) { } +/* maximum length of the conversion of a number to a string */ +#define MAXNUMBER2STR 50 + + +/* +** Convert a number object to a string +*/ +void luaO_tostring (lua_State *L, StkId obj) { + char buff[MAXNUMBER2STR]; + size_t len; + lua_assert(ttisnumber(obj)); + if (ttisinteger(obj)) + len = lua_integer2str(buff, ivalue(obj)); + else { + len = lua_number2str(buff, fltvalue(obj)); +#if !defined(LUA_COMPAT_FLOATSTRING) + if (buff[strspn(buff, "-0123456789")] == '\0') { /* looks like an int? */ + buff[len++] = '.'; + buff[len++] = '0'; /* adds '.0' to result */ + } +#endif + } + setsvalue2s(L, obj, luaS_newlstr(L, buff, len)); +} + + static void pushstr (lua_State *L, const char *str, size_t l) { setsvalue2s(L, L->top++, luaS_newlstr(L, str, l)); } @@ -349,24 +375,23 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { break; } case 'c': { - char buff; - buff = cast(char, va_arg(argp, int)); + char buff = cast(char, va_arg(argp, int)); pushstr(L, &buff, 1); break; } case 'd': { - setivalue(L->top++, cast_int(va_arg(argp, int))); - luaV_tostring(L, L->top - 1); + setivalue(L->top++, va_arg(argp, int)); + luaO_tostring(L, L->top - 1); break; } case 'I': { setivalue(L->top++, cast(lua_Integer, va_arg(argp, l_uacInt))); - luaV_tostring(L, L->top - 1); + luaO_tostring(L, L->top - 1); break; } case 'f': { setfltvalue(L->top++, cast_num(va_arg(argp, l_uacNumber))); - luaV_tostring(L, L->top - 1); + luaO_tostring(L, L->top - 1); break; } case 'p': { diff --git a/src/lobject.h b/src/lobject.h index 7c512422..9972e08b 100644 --- a/src/lobject.h +++ b/src/lobject.h @@ -1,5 +1,5 @@ /* -** $Id: lobject.h,v 2.94 2014/06/19 18:39:36 roberto Exp $ +** $Id: lobject.h,v 2.101 2014/07/30 14:00:14 roberto Exp $ ** Type definitions for Lua objects ** See Copyright Notice in lua.h */ @@ -69,9 +69,9 @@ /* -** Union of all collectable objects +** Common type for all collectable objects */ -typedef union GCObject GCObject; +typedef struct GCObject GCObject; /* @@ -82,11 +82,11 @@ typedef union GCObject GCObject; /* -** Common header in struct form +** Common type has only the common header */ -typedef struct GCheader { +struct GCObject { CommonHeader; -} GCheader; +}; @@ -156,10 +156,8 @@ typedef struct lua_TValue TValue; #define fltvalue(o) check_exp(ttisfloat(o), val_(o).n) #define gcvalue(o) check_exp(iscollectable(o), val_(o).gc) #define pvalue(o) check_exp(ttislightuserdata(o), val_(o).p) -#define rawtsvalue(o) check_exp(ttisstring(o), rawgco2ts(val_(o).gc)) -#define tsvalue(o) (&rawtsvalue(o)->tsv) -#define rawuvalue(o) check_exp(ttisfulluserdata(o), rawgco2u(val_(o).gc)) -#define uvalue(o) (&rawuvalue(o)->uv) +#define tsvalue(o) check_exp(ttisstring(o), gco2ts(val_(o).gc)) +#define uvalue(o) check_exp(ttisfulluserdata(o), gco2u(val_(o).gc)) #define clvalue(o) check_exp(ttisclosure(o), gco2cl(val_(o).gc)) #define clLvalue(o) check_exp(ttisLclosure(o), gco2lcl(val_(o).gc)) #define clCvalue(o) check_exp(ttisCclosure(o), gco2ccl(val_(o).gc)) @@ -177,7 +175,7 @@ typedef struct lua_TValue TValue; /* Macros for internal tests */ -#define righttt(obj) (ttype(obj) == gcvalue(obj)->gch.tt) +#define righttt(obj) (ttype(obj) == gcvalue(obj)->tt) #define checkliveness(g,obj) \ lua_longassert(!iscollectable(obj) || \ @@ -206,11 +204,11 @@ typedef struct lua_TValue TValue; #define setgcovalue(L,obj,x) \ { TValue *io = (obj); GCObject *i_g=(x); \ - val_(io).gc = i_g; settt_(io, ctb(gch(i_g)->tt)); } + val_(io).gc = i_g; settt_(io, ctb(i_g->tt)); } #define setsvalue(L,obj,x) \ { TValue *io = (obj); TString *x_ = (x); \ - val_(io).gc = obj2gco(x_); settt_(io, ctb(x_->tsv.tt)); \ + val_(io).gc = obj2gco(x_); settt_(io, ctb(x_->tt)); \ checkliveness(G(L),io); } #define setuvalue(L,obj,x) \ @@ -243,8 +241,7 @@ typedef struct lua_TValue TValue; #define setobj(L,obj1,obj2) \ - { const TValue *io2=(obj2); TValue *io1=(obj1); \ - io1->value_ = io2->value_; io1->tt_ = io2->tt_; \ + { TValue *io1=(obj1); *io1 = *(obj2); \ (void)L; checkliveness(G(L),io1); } @@ -299,50 +296,76 @@ typedef TValue *StkId; /* index to stack elements */ /* ** Header for string value; string bytes follow the end of this structure +** (aligned according to 'UTString'; see next). */ -typedef union TString { - L_Umaxalign dummy; /* ensures maximum alignment for strings */ - struct { - CommonHeader; - lu_byte extra; /* reserved words for short strings; "has hash" for longs */ - unsigned int hash; - size_t len; /* number of characters in string */ - union TString *hnext; /* linked list for hash table */ - } tsv; +typedef struct TString { + CommonHeader; + lu_byte extra; /* reserved words for short strings; "has hash" for longs */ + unsigned int hash; + size_t len; /* number of characters in string */ + struct TString *hnext; /* linked list for hash table */ } TString; -/* get the actual string (array of bytes) from a TString */ -#define getstr(ts) cast(const char *, (ts) + 1) +/* +** Ensures that address after this type is always fully aligned. +*/ +typedef union UTString { + L_Umaxalign dummy; /* ensures maximum alignment for strings */ + TString tsv; +} UTString; + + +/* +** Get the actual string (array of bytes) from a 'TString'. +** (Access to 'extra' ensures that value is really a 'TString'.) +*/ +#define getaddrstr(ts) (cast(char *, (ts)) + sizeof(UTString)) +#define getstr(ts) \ + check_exp(sizeof((ts)->extra), cast(const char*, getaddrstr(ts))) /* get the actual string (array of bytes) from a Lua value */ -#define svalue(o) getstr(rawtsvalue(o)) +#define svalue(o) getstr(tsvalue(o)) /* ** Header for userdata; memory area follows the end of this structure +** (aligned according to 'UUdata'; see next). */ -typedef union Udata { - L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */ - struct { - CommonHeader; - lu_byte ttuv_; /* user value's tag */ - struct Table *metatable; - size_t len; /* number of bytes */ - union Value user_; /* user value */ - } uv; +typedef struct Udata { + CommonHeader; + lu_byte ttuv_; /* user value's tag */ + struct Table *metatable; + size_t len; /* number of bytes */ + union Value user_; /* user value */ } Udata; +/* +** Ensures that address after this type is always fully aligned. +*/ +typedef union UUdata { + L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */ + Udata uv; +} UUdata; + + +/* +** Get the address of memory block inside 'Udata'. +** (Access to 'ttuv_' ensures that value is really a 'Udata'.) +*/ +#define getudatamem(u) \ + check_exp(sizeof((u)->ttuv_), (cast(char*, (u)) + sizeof(UUdata))) + #define setuservalue(L,u,o) \ { const TValue *io=(o); Udata *iu = (u); \ - iu->uv.user_ = io->value_; iu->uv.ttuv_ = io->tt_; \ + iu->user_ = io->value_; iu->ttuv_ = io->tt_; \ checkliveness(G(L),io); } #define getuservalue(L,u,o) \ { TValue *io=(o); const Udata *iu = (u); \ - io->value_ = iu->uv.user_; io->tt_ = iu->uv.ttuv_; \ + io->value_ = iu->user_; io->tt_ = iu->ttuv_; \ checkliveness(G(L),io); } @@ -447,6 +470,13 @@ typedef union TKey { } TKey; +/* copy a value into a key without messing up field 'next' */ +#define setkey(L,key,obj) \ + { TKey *k_=(key); const TValue *io_=(obj); \ + k_->nk.value_ = io_->value_; k_->nk.tt_ = io_->tt_; \ + (void)L; checkliveness(G(L),io_); } + + typedef struct Node { TValue i_val; TKey i_key; @@ -497,6 +527,7 @@ LUAI_FUNC void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2, TValue *res); LUAI_FUNC size_t luaO_str2num (const char *s, TValue *o); LUAI_FUNC int luaO_hexavalue (int c); +LUAI_FUNC void luaO_tostring (lua_State *L, StkId obj); LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp); LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...); diff --git a/src/lparser.c b/src/lparser.c index 6c097d7f..1e7e244a 100644 --- a/src/lparser.c +++ b/src/lparser.c @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 2.139 2014/06/19 18:27:20 roberto Exp $ +** $Id: lparser.c,v 2.142 2014/07/21 16:02:10 roberto Exp $ ** Lua Parser ** See Copyright Notice in lua.h */ diff --git a/src/lstate.c b/src/lstate.c index 1628ad91..295fc4c7 100644 --- a/src/lstate.c +++ b/src/lstate.c @@ -1,5 +1,5 @@ /* -** $Id: lstate.c,v 2.121 2014/02/18 13:46:26 roberto Exp $ +** $Id: lstate.c,v 2.125 2014/07/24 16:17:56 roberto Exp $ ** Global State ** See Copyright Notice in lua.h */ @@ -53,9 +53,7 @@ ** thread state + extra space */ typedef struct LX { -#if defined(LUAI_EXTRASPACE) - char buff[LUAI_EXTRASPACE]; -#endif + lu_byte extra_[LUA_EXTRASPACE]; lua_State l; } LX; @@ -252,7 +250,7 @@ static void close_state (lua_State *L) { LUA_API lua_State *lua_newthread (lua_State *L) { - global_State *g = G(L); + global_State *g = G(L); lua_State *L1; lua_lock(L); luaC_checkGC(L); @@ -263,6 +261,7 @@ LUA_API lua_State *lua_newthread (lua_State *L) { /* link it on list 'allgc' */ L1->next = g->allgc; g->allgc = obj2gco(L1); + /* anchor it on L stack */ setthvalue(L, L->top, L1); api_incr_top(L); preinit_thread(L1, g); @@ -270,6 +269,9 @@ LUA_API lua_State *lua_newthread (lua_State *L) { L1->basehookcount = L->basehookcount; L1->hook = L->hook; resethookcount(L1); + /* initialize L1 extra space */ + memcpy(lua_getextraspace(L1), lua_getextraspace(g->mainthread), + LUA_EXTRASPACE); luai_userstatethread(L, L1); stack_init(L1, L); /* init stack */ lua_unlock(L); diff --git a/src/lstate.h b/src/lstate.h index add9e95b..698bea0d 100644 --- a/src/lstate.h +++ b/src/lstate.h @@ -1,5 +1,5 @@ /* -** $Id: lstate.h,v 2.107 2014/06/12 19:07:30 roberto Exp $ +** $Id: lstate.h,v 2.114 2014/07/23 17:15:43 roberto Exp $ ** Global State ** See Copyright Notice in lua.h */ @@ -60,9 +60,6 @@ typedef struct CallInfo { StkId func; /* function index in the stack */ StkId top; /* top for this function */ struct CallInfo *previous, *next; /* dynamic call link */ - ptrdiff_t extra; - short nresults; /* expected number of results from this function */ - lu_byte callstatus; union { struct { /* only for Lua functions */ StkId base; /* base for this function */ @@ -71,9 +68,12 @@ typedef struct CallInfo { struct { /* only for C functions */ lua_KFunction k; /* continuation in case of yields */ ptrdiff_t old_errfunc; - int ctx; /* context info. in case of yields */ + lua_Ctx ctx; /* context info. in case of yields */ } c; } u; + ptrdiff_t extra; + short nresults; /* expected number of results from this function */ + lu_byte callstatus; } CallInfo; @@ -149,20 +149,20 @@ struct lua_State { const Instruction *oldpc; /* last pc traced */ StkId stack_last; /* last free slot in the stack */ StkId stack; /* stack base */ - int stacksize; - unsigned short nny; /* number of non-yieldable calls in stack */ - unsigned short nCcalls; /* number of nested C calls */ - lu_byte hookmask; - lu_byte allowhook; - int basehookcount; - int hookcount; - lua_Hook hook; UpVal *openupval; /* list of open upvalues in this stack */ GCObject *gclist; struct lua_State *twups; /* list of threads with open upvalues */ struct lua_longjmp *errorJmp; /* current error recover point */ - ptrdiff_t errfunc; /* current error handling function (stack index) */ CallInfo base_ci; /* CallInfo for first level (C calling Lua) */ + lua_Hook hook; + ptrdiff_t errfunc; /* current error handling function (stack index) */ + int stacksize; + int basehookcount; + int hookcount; + unsigned short nny; /* number of non-yieldable calls in stack */ + unsigned short nCcalls; /* number of nested C calls */ + lu_byte hookmask; + lu_byte allowhook; }; @@ -170,12 +170,12 @@ struct lua_State { /* -** Union of all collectable objects +** Union of all collectable objects (only for conversions) */ -union GCObject { - GCheader gch; /* common header */ - union TString ts; - union Udata u; +union GCUnion { + GCObject gc; /* common header */ + struct TString ts; + struct Udata u; union Closure cl; struct Table h; struct Proto p; @@ -183,24 +183,24 @@ union GCObject { }; -#define gch(o) (&(o)->gch) +#define cast_u(o) cast(union GCUnion *, (o)) /* macros to convert a GCObject into a specific value */ -#define rawgco2ts(o) \ - check_exp(novariant((o)->gch.tt) == LUA_TSTRING, &((o)->ts)) -#define gco2ts(o) (&rawgco2ts(o)->tsv) -#define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u)) -#define gco2u(o) (&rawgco2u(o)->uv) -#define gco2lcl(o) check_exp((o)->gch.tt == LUA_TLCL, &((o)->cl.l)) -#define gco2ccl(o) check_exp((o)->gch.tt == LUA_TCCL, &((o)->cl.c)) +#define gco2ts(o) \ + check_exp(novariant((o)->tt) == LUA_TSTRING, &((cast_u(o))->ts)) +#define gco2u(o) check_exp((o)->tt == LUA_TUSERDATA, &((cast_u(o))->u)) +#define gco2lcl(o) check_exp((o)->tt == LUA_TLCL, &((cast_u(o))->cl.l)) +#define gco2ccl(o) check_exp((o)->tt == LUA_TCCL, &((cast_u(o))->cl.c)) #define gco2cl(o) \ - check_exp(novariant((o)->gch.tt) == LUA_TFUNCTION, &((o)->cl)) -#define gco2t(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h)) -#define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p)) -#define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th)) + check_exp(novariant((o)->tt) == LUA_TFUNCTION, &((cast_u(o))->cl)) +#define gco2t(o) check_exp((o)->tt == LUA_TTABLE, &((cast_u(o))->h)) +#define gco2p(o) check_exp((o)->tt == LUA_TPROTO, &((cast_u(o))->p)) +#define gco2th(o) check_exp((o)->tt == LUA_TTHREAD, &((cast_u(o))->th)) + -/* macro to convert any Lua object into a GCObject */ -#define obj2gco(v) (cast(GCObject *, (v))) +/* macro to convert a Lua object into a GCObject */ +#define obj2gco(v) \ + check_exp(novariant((v)->tt) < LUA_TDEADKEY, (&(cast_u(v)->gc))) /* actual number of total bytes allocated */ diff --git a/src/lstring.c b/src/lstring.c index c63111a8..df28a7f2 100644 --- a/src/lstring.c +++ b/src/lstring.c @@ -1,5 +1,5 @@ /* -** $Id: lstring.c,v 2.40 2014/06/18 22:59:29 roberto Exp $ +** $Id: lstring.c,v 2.44 2014/07/21 16:02:10 roberto Exp $ ** String table (keeps all strings handled by Lua) ** See Copyright Notice in lua.h */ @@ -34,10 +34,10 @@ ** equality for long strings */ int luaS_eqlngstr (TString *a, TString *b) { - size_t len = a->tsv.len; - lua_assert(a->tsv.tt == LUA_TLNGSTR && b->tsv.tt == LUA_TLNGSTR); + size_t len = a->len; + lua_assert(a->tt == LUA_TLNGSTR && b->tt == LUA_TLNGSTR); return (a == b) || /* same instance or... */ - ((len == b->tsv.len) && /* equal length and ... */ + ((len == b->len) && /* equal length and ... */ (memcmp(getstr(a), getstr(b), len) == 0)); /* equal contents */ } @@ -67,9 +67,9 @@ void luaS_resize (lua_State *L, int newsize) { TString *p = tb->hash[i]; tb->hash[i] = NULL; while (p) { /* for each node in the list */ - TString *hnext = p->tsv.hnext; /* save next */ - unsigned int h = lmod(p->tsv.hash, newsize); /* new position */ - p->tsv.hnext = tb->hash[h]; /* chain it */ + TString *hnext = p->hnext; /* save next */ + unsigned int h = lmod(p->hash, newsize); /* new position */ + p->hnext = tb->hash[h]; /* chain it */ tb->hash[h] = p; p = hnext; } @@ -92,24 +92,24 @@ static TString *createstrobj (lua_State *L, const char *str, size_t l, TString *ts; GCObject *o; size_t totalsize; /* total size of TString object */ - totalsize = sizeof(TString) + ((l + 1) * sizeof(char)); + totalsize = sizelstring(l); o = luaC_newobj(L, tag, totalsize); - ts = rawgco2ts(o); - ts->tsv.len = l; - ts->tsv.hash = h; - ts->tsv.extra = 0; - memcpy(ts+1, str, l*sizeof(char)); - ((char *)(ts+1))[l] = '\0'; /* ending 0 */ + ts = gco2ts(o); + ts->len = l; + ts->hash = h; + ts->extra = 0; + memcpy(getaddrstr(ts), str, l * sizeof(char)); + getaddrstr(ts)[l] = '\0'; /* ending 0 */ return ts; } void luaS_remove (lua_State *L, TString *ts) { stringtable *tb = &G(L)->strt; - TString **p = &tb->hash[lmod(ts->tsv.hash, tb->size)]; + TString **p = &tb->hash[lmod(ts->hash, tb->size)]; while (*p != ts) /* find previous element */ - p = &(*p)->tsv.hnext; - *p = (*p)->tsv.hnext; /* remove element from its list */ + p = &(*p)->hnext; + *p = (*p)->hnext; /* remove element from its list */ tb->nuse--; } @@ -122,12 +122,12 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) { global_State *g = G(L); unsigned int h = luaS_hash(str, l, g->seed); TString **list = &g->strt.hash[lmod(h, g->strt.size)]; - for (ts = *list; ts != NULL; ts = ts->tsv.hnext) { - if (l == ts->tsv.len && + for (ts = *list; ts != NULL; ts = ts->hnext) { + if (l == ts->len && (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) { /* found! */ - if (isdead(g, obj2gco(ts))) /* dead (but not collected yet)? */ - changewhite(obj2gco(ts)); /* resurrect it */ + if (isdead(g, ts)) /* dead (but not collected yet)? */ + changewhite(ts); /* resurrect it */ return ts; } } @@ -136,7 +136,7 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) { list = &g->strt.hash[lmod(h, g->strt.size)]; /* recompute with new size */ } ts = createstrobj(L, str, l, LUA_TSHRSTR, h); - ts->tsv.hnext = *list; + ts->hnext = *list; *list = ts; g->strt.nuse++; return ts; @@ -170,10 +170,10 @@ Udata *luaS_newudata (lua_State *L, size_t s) { GCObject *o; if (s > MAX_SIZE - sizeof(Udata)) luaM_toobig(L); - o = luaC_newobj(L, LUA_TUSERDATA, sizeof(Udata) + s); - u = rawgco2u(o); - u->uv.len = s; - u->uv.metatable = NULL; + o = luaC_newobj(L, LUA_TUSERDATA, sizeludata(s)); + u = gco2u(o); + u->len = s; + u->metatable = NULL; setuservalue(L, u, luaO_nilobject); return u; } diff --git a/src/lstring.h b/src/lstring.h index d5f5b249..d3f04caf 100644 --- a/src/lstring.h +++ b/src/lstring.h @@ -1,5 +1,5 @@ /* -** $Id: lstring.h,v 1.54 2014/03/19 18:51:42 roberto Exp $ +** $Id: lstring.h,v 1.56 2014/07/18 14:46:47 roberto Exp $ ** String table (keep all strings handled by Lua) ** See Copyright Notice in lua.h */ @@ -12,9 +12,11 @@ #include "lstate.h" -#define sizestring(s) (sizeof(union TString)+((s)->len+1)*sizeof(char)) +#define sizelstring(l) (sizeof(union UTString) + ((l) + 1) * sizeof(char)) +#define sizestring(s) sizelstring((s)->len) -#define sizeudata(u) (sizeof(union Udata)+(u)->len) +#define sizeludata(l) (sizeof(union UUdata) + (l)) +#define sizeudata(u) sizeludata((u)->len) #define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ (sizeof(s)/sizeof(char))-1)) @@ -23,13 +25,13 @@ /* ** test whether a string is a reserved word */ -#define isreserved(s) ((s)->tsv.tt == LUA_TSHRSTR && (s)->tsv.extra > 0) +#define isreserved(s) ((s)->tt == LUA_TSHRSTR && (s)->extra > 0) /* ** equality for short strings, which are always internalized */ -#define eqshrstr(a,b) check_exp((a)->tsv.tt == LUA_TSHRSTR, (a) == (b)) +#define eqshrstr(a,b) check_exp((a)->tt == LUA_TSHRSTR, (a) == (b)) LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, unsigned int seed); diff --git a/src/lstrlib.c b/src/lstrlib.c index 3cbd91b2..05330c80 100644 --- a/src/lstrlib.c +++ b/src/lstrlib.c @@ -1,5 +1,5 @@ /* -** $Id: lstrlib.c,v 1.198 2014/04/27 14:42:26 roberto Exp $ +** $Id: lstrlib.c,v 1.200 2014/07/30 13:59:24 roberto Exp $ ** Standard library for string operations and pattern-matching ** See Copyright Notice in lua.h */ @@ -59,7 +59,7 @@ static int str_sub (lua_State *L) { if (start < 1) start = 1; if (end > (lua_Integer)l) end = l; if (start <= end) - lua_pushlstring(L, s + start - 1, end - start + 1); + lua_pushlstring(L, s + start - 1, (size_t)(end - start + 1)); else lua_pushliteral(L, ""); return 1; } @@ -119,7 +119,7 @@ static int str_rep (lua_State *L) { else if (l + lsep < l || l + lsep > MAXSIZE / n) /* may overflow? */ return luaL_error(L, "resulting string too large"); else { - size_t totallen = n * l + (n - 1) * lsep; + size_t totallen = (size_t)n * l + (size_t)(n - 1) * lsep; luaL_Buffer b; char *p = luaL_buffinitsize(L, &b, totallen); while (n-- > 1) { /* first n-1 copies (followed by separator) */ @@ -594,7 +594,7 @@ static int str_find_aux (lua_State *L, int find) { /* explicit request or no special characters? */ if (find && (lua_toboolean(L, 4) || nospecials(p, lp))) { /* do a plain search */ - const char *s2 = lmemfind(s + init - 1, ls - init + 1, p, lp); + const char *s2 = lmemfind(s + init - 1, ls - (size_t)init + 1, p, lp); if (s2) { lua_pushinteger(L, s2 - s + 1); lua_pushinteger(L, s2 - s + lp); @@ -685,7 +685,8 @@ static int gmatch (lua_State *L) { static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, const char *e) { size_t l, i; - const char *news = lua_tolstring(ms->L, 3, &l); + lua_State *L = ms->L; + const char *news = lua_tolstring(L, 3, &l); for (i = 0; i < l; i++) { if (news[i] != L_ESC) luaL_addchar(b, news[i]); @@ -693,14 +694,16 @@ static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, i++; /* skip ESC */ if (!isdigit(uchar(news[i]))) { if (news[i] != L_ESC) - luaL_error(ms->L, "invalid use of " LUA_QL("%c") - " in replacement string", L_ESC); + luaL_error(L, "invalid use of " LUA_QL("%c") + " in replacement string", L_ESC); luaL_addchar(b, news[i]); } else if (news[i] == '0') luaL_addlstring(b, s, e - s); else { push_onecapture(ms, news[i] - '1', s, e); + luaL_tolstring(L, -1, NULL); /* if number, convert it to string */ + lua_remove(L, -2); /* remove original value */ luaL_addvalue(b); /* add capture to accumulated result */ } } @@ -744,9 +747,9 @@ static int str_gsub (lua_State *L) { const char *src = luaL_checklstring(L, 1, &srcl); const char *p = luaL_checklstring(L, 2, &lp); int tr = lua_type(L, 3); - size_t max_s = luaL_optinteger(L, 4, srcl+1); + lua_Integer max_s = luaL_optinteger(L, 4, srcl + 1); int anchor = (*p == '^'); - size_t n = 0; + lua_Integer n = 0; MatchState ms; luaL_Buffer b; luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || diff --git a/src/ltable.c b/src/ltable.c index a7675a57..6ba80e3b 100644 --- a/src/ltable.c +++ b/src/ltable.c @@ -1,5 +1,5 @@ /* -** $Id: ltable.c,v 2.90 2014/06/18 22:59:29 roberto Exp $ +** $Id: ltable.c,v 2.93 2014/07/29 16:22:24 roberto Exp $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ @@ -52,7 +52,7 @@ #define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t)))) -#define hashstr(t,str) hashpow2(t, (str)->tsv.hash) +#define hashstr(t,str) hashpow2(t, (str)->hash) #define hashboolean(t,p) hashpow2(t, p) #define hashint(t,i) hashpow2(t, i) @@ -64,7 +64,7 @@ #define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1)))) -#define hashpointer(t,p) hashmod(t, IntPoint(p)) +#define hashpointer(t,p) hashmod(t, point2int(p)) #define dummynode (&dummynode_) @@ -116,14 +116,14 @@ static Node *mainposition (const Table *t, const TValue *key) { case LUA_TNUMFLT: return hashfloat(t, fltvalue(key)); case LUA_TSHRSTR: - return hashstr(t, rawtsvalue(key)); + return hashstr(t, tsvalue(key)); case LUA_TLNGSTR: { - TString *s = rawtsvalue(key); - if (s->tsv.extra == 0) { /* no hash? */ - s->tsv.hash = luaS_hash(getstr(s), s->tsv.len, s->tsv.hash); - s->tsv.extra = 1; /* now it has its hash */ + TString *s = tsvalue(key); + if (s->extra == 0) { /* no hash? */ + s->hash = luaS_hash(getstr(s), s->len, s->hash); + s->extra = 1; /* now it has its hash */ } - return hashstr(t, rawtsvalue(key)); + return hashstr(t, tsvalue(key)); } case LUA_TBOOLEAN: return hashboolean(t, bvalue(key)); @@ -309,7 +309,7 @@ static void setnodevector (lua_State *L, Table *t, int size) { for (i=0; i<size; i++) { Node *n = gnode(t, i); gnext(n) = 0; - setnilvalue(gkey(n)); + setnilvalue(wgkey(n)); setnilvalue(gval(n)); } } @@ -466,7 +466,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { mp = f; } } - setobj2t(L, gkey(mp), key); + setkey(L, &mp->i_key, key); luaC_barrierback(L, t, key); lua_assert(ttisnil(gval(mp))); return gval(mp); @@ -501,9 +501,10 @@ const TValue *luaH_getint (Table *t, lua_Integer key) { */ const TValue *luaH_getstr (Table *t, TString *key) { Node *n = hashstr(t, key); - lua_assert(key->tsv.tt == LUA_TSHRSTR); + lua_assert(key->tt == LUA_TSHRSTR); for (;;) { /* check whether `key' is somewhere in the chain */ - if (ttisshrstring(gkey(n)) && eqshrstr(rawtsvalue(gkey(n)), key)) + const TValue *k = gkey(n); + if (ttisshrstring(k) && eqshrstr(tsvalue(k), key)) return gval(n); /* that's it */ else { int nx = gnext(n); @@ -520,7 +521,7 @@ 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_TSHRSTR: return luaH_getstr(t, tsvalue(key)); case LUA_TNUMINT: return luaH_getint(t, ivalue(key)); case LUA_TNIL: return luaO_nilobject; case LUA_TNUMFLT: { diff --git a/src/ltable.h b/src/ltable.h index 12366d4b..45ff45f2 100644 --- a/src/ltable.h +++ b/src/ltable.h @@ -1,5 +1,5 @@ /* -** $Id: ltable.h,v 2.18 2013/08/30 16:01:37 roberto Exp $ +** $Id: ltable.h,v 2.19 2014/07/29 16:22:24 roberto Exp $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ @@ -11,10 +11,15 @@ #define gnode(t,i) (&(t)->node[i]) -#define gkey(n) (&(n)->i_key.tvk) #define gval(n) (&(n)->i_val) #define gnext(n) ((n)->i_key.nk.next) + +/* 'const' to avoid wrong writings that can mess up field 'next' */ +#define gkey(n) cast(const TValue*, (&(n)->i_key.tvk)) + +#define wgkey(n) (&(n)->i_key.nk) + #define invalidateTMcache(t) ((t)->flags = 0) diff --git a/src/ltablib.c b/src/ltablib.c index ab0d21e7..bc353866 100644 --- a/src/ltablib.c +++ b/src/ltablib.c @@ -1,5 +1,5 @@ /* -** $Id: ltablib.c,v 1.70 2014/05/16 18:53:25 roberto Exp $ +** $Id: ltablib.c,v 1.73 2014/07/29 16:01:00 roberto Exp $ ** Library for Table Manipulation ** See Copyright Notice in lua.h */ @@ -17,8 +17,56 @@ #include "lualib.h" -#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_len(L, n)) +/* +** Structure with table-access functions +*/ +typedef struct { + int (*geti) (lua_State *L, int idx, lua_Integer n); + void (*seti) (lua_State *L, int idx, lua_Integer n); +} TabA; + + +/* +** equivalent to 'lua_rawgeti', but not raw +*/ +static int geti (lua_State *L, int idx, lua_Integer n) { + lua_pushinteger(L, n); + return lua_gettable(L, idx); /* assume 'idx' is not negative */ +} + + +/* +** equivalent to 'lua_rawseti', but not raw +*/ +static void seti (lua_State *L, int idx, lua_Integer n) { + lua_pushinteger(L, n); + lua_rotate(L, -2, 1); /* exchange key and value */ + lua_settable(L, idx); /* assume 'idx' is not negative */ +} + + +/* +** Check that 'arg' has a table and set access functions in 'ta' to raw +** or non-raw according to the presence of corresponding metamethods. +*/ +static void checktab (lua_State *L, int arg, TabA *ta) { + luaL_checktype(L, arg, LUA_TTABLE); + if (!lua_getmetatable(L, arg)) { /* fast track */ + ta->geti = lua_rawgeti; /* with no metatable, all is raw */ + ta->seti = lua_rawseti; + } + else { + lua_pushliteral(L, "__index"); /* 'index' metamethod */ + ta->geti = (lua_rawget(L, -2) == LUA_TNIL) ? lua_rawgeti : geti; + lua_pushliteral(L, "__newindex"); /* 'newindex' metamethod */ + ta->seti = (lua_rawget(L, -3) == LUA_TNIL) ? lua_rawseti : seti; + lua_pop(L, 3); /* pop metatable plus both metamethods */ + } +} + + +#define aux_getn(L,n,ta) (checktab(L, n, ta), luaL_len(L, n)) #if defined(LUA_COMPAT_MAXN) @@ -40,7 +88,8 @@ static int maxn (lua_State *L) { static int tinsert (lua_State *L) { - lua_Integer e = aux_getn(L, 1) + 1; /* first empty element */ + TabA ta; + lua_Integer e = aux_getn(L, 1, &ta) + 1; /* first empty element */ lua_Integer pos; /* where to insert new element */ switch (lua_gettop(L)) { case 2: { /* called with only 2 arguments */ @@ -52,8 +101,8 @@ static int tinsert (lua_State *L) { pos = luaL_checkinteger(L, 2); /* 2nd argument is the position */ luaL_argcheck(L, 1 <= pos && pos <= e, 2, "position out of bounds"); for (i = e; i > pos; i--) { /* move up elements */ - lua_rawgeti(L, 1, i-1); - lua_rawseti(L, 1, i); /* t[i] = t[i-1] */ + (*ta.geti)(L, 1, i - 1); + (*ta.seti)(L, 1, i); /* t[i] = t[i - 1] */ } break; } @@ -61,29 +110,67 @@ static int tinsert (lua_State *L) { return luaL_error(L, "wrong number of arguments to " LUA_QL("insert")); } } - lua_rawseti(L, 1, pos); /* t[pos] = v */ + (*ta.seti)(L, 1, pos); /* t[pos] = v */ return 0; } static int tremove (lua_State *L) { - lua_Integer size = aux_getn(L, 1); + TabA ta; + lua_Integer size = aux_getn(L, 1, &ta); lua_Integer pos = luaL_optinteger(L, 2, size); if (pos != size) /* validate 'pos' if given */ luaL_argcheck(L, 1 <= pos && pos <= size + 1, 1, "position out of bounds"); - lua_rawgeti(L, 1, pos); /* result = t[pos] */ + (*ta.geti)(L, 1, pos); /* result = t[pos] */ for ( ; pos < size; pos++) { - lua_rawgeti(L, 1, pos+1); - lua_rawseti(L, 1, pos); /* t[pos] = t[pos+1] */ + (*ta.geti)(L, 1, pos + 1); + (*ta.seti)(L, 1, pos); /* t[pos] = t[pos + 1] */ } lua_pushnil(L); - lua_rawseti(L, 1, pos); /* t[pos] = nil */ + (*ta.seti)(L, 1, pos); /* t[pos] = nil */ + return 1; +} + + +static int tcopy (lua_State *L) { + TabA ta; + lua_Integer f = luaL_checkinteger(L, 2); + lua_Integer e = luaL_checkinteger(L, 3); + lua_Integer t; + int tt = 4; /* destination table */ + /* the following restriction avoids several problems with overflows */ + luaL_argcheck(L, f > 0, 2, "initial position must be positive"); + if (lua_istable(L, tt)) + t = luaL_checkinteger(L, 5); + else { + tt = 1; /* destination table is equal to source */ + t = luaL_checkinteger(L, 4); + } + if (e >= f) { /* otherwise, nothing to move */ + lua_Integer n, i; + ta.geti = (!luaL_getmetafield(L, 1, "__index")) ? lua_rawgeti : geti; + ta.seti = (!luaL_getmetafield(L, tt, "__newindex")) ? lua_rawseti : seti; + n = e - f + 1; /* number of elements to move */ + if (t > f) { + for (i = n - 1; i >= 0; i--) { + (*ta.geti)(L, 1, f + i); + (*ta.seti)(L, tt, t + i); + } + } + else { + for (i = 0; i < n; i++) { + (*ta.geti)(L, 1, f + i); + (*ta.seti)(L, tt, t + i); + } + } + } + lua_pushvalue(L, tt); /* return "to table" */ return 1; } -static void addfield (lua_State *L, luaL_Buffer *b, lua_Integer i) { - lua_rawgeti(L, 1, i); +static void addfield (lua_State *L, luaL_Buffer *b, TabA *ta, lua_Integer i) { + (*ta->geti)(L, 1, i); if (!lua_isstring(L, -1)) luaL_error(L, "invalid value (%s) at index %d in table for " LUA_QL("concat"), luaL_typename(L, -1), i); @@ -92,20 +179,21 @@ static void addfield (lua_State *L, luaL_Buffer *b, lua_Integer i) { static int tconcat (lua_State *L) { + TabA ta; luaL_Buffer b; size_t lsep; lua_Integer i, last; const char *sep = luaL_optlstring(L, 2, "", &lsep); - luaL_checktype(L, 1, LUA_TTABLE); + checktab(L, 1, &ta); i = luaL_optinteger(L, 3, 1); last = luaL_opt(L, luaL_checkinteger, 4, luaL_len(L, 1)); luaL_buffinit(L, &b); for (; i < last; i++) { - addfield(L, &b, i); + addfield(L, &b, &ta, i); luaL_addlstring(&b, sep, lsep); } if (i == last) /* add last value (if interval was not empty) */ - addfield(L, &b, i); + addfield(L, &b, &ta, i); luaL_pushresult(&b); return 1; } @@ -131,20 +219,21 @@ static int pack (lua_State *L) { static int unpack (lua_State *L) { + TabA ta; lua_Integer i, e; lua_Unsigned n; - luaL_checktype(L, 1, LUA_TTABLE); + checktab(L, 1, &ta); i = luaL_optinteger(L, 2, 1); e = luaL_opt(L, luaL_checkinteger, 3, luaL_len(L, 1)); if (i > e) return 0; /* empty range */ n = (lua_Unsigned)e - i; /* number of elements minus 1 (avoid overflows) */ - if (n >= (unsigned int)INT_MAX || !lua_checkstack(L, ++n)) + if (n >= (unsigned int)INT_MAX || !lua_checkstack(L, (int)(++n))) return luaL_error(L, "too many results to unpack"); do { /* must have at least one element */ - lua_rawgeti(L, 1, i); /* push arg[i..e] */ + (*ta.geti)(L, 1, i); /* push arg[i..e] */ } while (i++ < e); - return n; + return (int)n; } /* }====================================================== */ @@ -160,9 +249,9 @@ static int unpack (lua_State *L) { */ -static void set2 (lua_State *L, int i, int j) { - lua_rawseti(L, 1, i); - lua_rawseti(L, 1, j); +static void set2 (lua_State *L, TabA *ta, int i, int j) { + (*ta->seti)(L, 1, i); + (*ta->seti)(L, 1, j); } static int sort_comp (lua_State *L, int a, int b) { @@ -180,45 +269,45 @@ static int sort_comp (lua_State *L, int a, int b) { return lua_compare(L, a, b, LUA_OPLT); } -static void auxsort (lua_State *L, int l, int u) { +static void auxsort (lua_State *L, TabA *ta, int l, int u) { while (l < u) { /* for tail recursion */ int i, j; /* sort elements a[l], a[(l+u)/2] and a[u] */ - lua_rawgeti(L, 1, l); - lua_rawgeti(L, 1, u); + (*ta->geti)(L, 1, l); + (*ta->geti)(L, 1, u); if (sort_comp(L, -1, -2)) /* a[u] < a[l]? */ - set2(L, l, u); /* swap a[l] - a[u] */ + set2(L, ta, l, u); /* swap a[l] - a[u] */ else lua_pop(L, 2); if (u-l == 1) break; /* only 2 elements */ i = (l+u)/2; - lua_rawgeti(L, 1, i); - lua_rawgeti(L, 1, l); + (*ta->geti)(L, 1, i); + (*ta->geti)(L, 1, l); if (sort_comp(L, -2, -1)) /* a[i]<a[l]? */ - set2(L, i, l); + set2(L, ta, i, l); else { lua_pop(L, 1); /* remove a[l] */ - lua_rawgeti(L, 1, u); + (*ta->geti)(L, 1, u); if (sort_comp(L, -1, -2)) /* a[u]<a[i]? */ - set2(L, i, u); + set2(L, ta, i, u); else lua_pop(L, 2); } if (u-l == 2) break; /* only 3 elements */ - lua_rawgeti(L, 1, i); /* Pivot */ + (*ta->geti)(L, 1, i); /* Pivot */ lua_pushvalue(L, -1); - lua_rawgeti(L, 1, u-1); - set2(L, i, u-1); + (*ta->geti)(L, 1, u-1); + set2(L, ta, i, u-1); /* a[l] <= P == a[u-1] <= a[u], only need to sort from l+1 to u-2 */ i = l; j = u-1; for (;;) { /* invariant: a[l..i] <= P <= a[j..u] */ /* repeat ++i until a[i] >= P */ - while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { + while ((*ta->geti)(L, 1, ++i), sort_comp(L, -1, -2)) { if (i>=u) luaL_error(L, "invalid order function for sorting"); lua_pop(L, 1); /* remove a[i] */ } /* repeat --j until a[j] <= P */ - while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) { + while ((*ta->geti)(L, 1, --j), sort_comp(L, -3, -1)) { if (j<=l) luaL_error(L, "invalid order function for sorting"); lua_pop(L, 1); /* remove a[j] */ } @@ -226,11 +315,11 @@ static void auxsort (lua_State *L, int l, int u) { lua_pop(L, 3); /* pop pivot, a[i], a[j] */ break; } - set2(L, i, j); + set2(L, ta, i, j); } - lua_rawgeti(L, 1, u-1); - lua_rawgeti(L, 1, i); - set2(L, u-1, i); /* swap pivot (a[u-1]) with a[i] */ + (*ta->geti)(L, 1, u-1); + (*ta->geti)(L, 1, i); + set2(L, ta, u-1, i); /* swap pivot (a[u-1]) with a[i] */ /* a[l..i-1] <= a[i] == P <= a[i+1..u] */ /* adjust so that smaller half is in [j..i] and larger one in [l..u] */ if (i-l < u-i) { @@ -239,17 +328,18 @@ static void auxsort (lua_State *L, int l, int u) { else { j=i+1; i=u; u=j-2; } - auxsort(L, j, i); /* call recursively the smaller one */ + auxsort(L, ta, j, i); /* call recursively the smaller one */ } /* repeat the routine for the larger one */ } static int sort (lua_State *L) { - int n = aux_getn(L, 1); - luaL_checkstack(L, 40, ""); /* assume array is smaller than 2^40 */ + TabA ta; + int n = (int)aux_getn(L, 1, &ta); + luaL_checkstack(L, 50, ""); /* assume array is smaller than 2^50 */ if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */ luaL_checktype(L, 2, LUA_TFUNCTION); - lua_settop(L, 2); /* make sure there is two arguments */ - auxsort(L, 1, n); + lua_settop(L, 2); /* make sure there are two arguments */ + auxsort(L, &ta, 1, n); return 0; } @@ -265,6 +355,7 @@ static const luaL_Reg tab_funcs[] = { {"pack", pack}, {"unpack", unpack}, {"remove", tremove}, + {"copy", tcopy}, {"sort", sort}, {NULL, NULL} }; @@ -1,5 +1,5 @@ /* -** $Id: ltm.c,v 2.27 2014/06/10 18:53:18 roberto Exp $ +** $Id: ltm.c,v 2.29 2014/07/18 13:36:14 roberto Exp $ ** Tag methods ** See Copyright Notice in lua.h */ @@ -1,5 +1,5 @@ /* -** $Id: lua.c,v 1.211 2014/06/05 20:42:06 roberto Exp $ +** $Id: lua.c,v 1.213 2014/06/30 19:48:08 roberto Exp $ ** Lua stand-alone interpreter ** See Copyright Notice in lua.h */ @@ -115,7 +115,7 @@ static void lstop (lua_State *L, lua_Debug *ar) { /* ** Function to be called at a C signal. Because a C signal cannot -** just change a Lua state (as there is no proper syncronization), +** just change a Lua state (as there is no proper synchronization), ** this function only sets a hook that, when called, will stop the ** interpreter. */ @@ -284,7 +284,7 @@ static const char *get_prompt (lua_State *L, int firstline) { /* ** Check whether 'status' signals a syntax error and the error ** message at the top of the stack ends with the above mark for -** incoplete statements. +** incomplete statements. */ static int incomplete (lua_State *L, int status) { if (status == LUA_ERRSYNTAX) { @@ -417,25 +417,31 @@ static void doREPL (lua_State *L) { /* -** Push on the stack 'n' strings from 'argv' +** Push on the stack the contents of table 'arg' from 1 to #arg */ -static void pushargs (lua_State *L, char **argv, int n) { - int i; +static int pushargs (lua_State *L) { + int i, n; + lua_getglobal(L, "arg"); + if (!lua_istable(L, -1)) + luaL_error(L, "'arg' is not a table"); + n = (int)luaL_len(L, -1); luaL_checkstack(L, n + 3, "too many arguments to script"); - for (i = 1; i < n; i++) /* skip 0 (the script name) */ - lua_pushstring(L, argv[i]); + for (i = 1; i <= n; i++) + lua_rawgeti(L, -i, i); + lua_remove(L, -i); /* remove table from the stack */ + return n; } -static int handle_script (lua_State *L, char **argv, int n) { +static int handle_script (lua_State *L, char **argv) { int status; const char *fname = argv[0]; if (strcmp(fname, "-") == 0 && strcmp(argv[-1], "--") != 0) fname = NULL; /* stdin */ status = luaL_loadfile(L, fname); if (status == LUA_OK) { - pushargs(L, argv, n); /* push arguments to script */ - status = docall(L, n - 1, LUA_MULTRET); + int n = pushargs(L); /* push arguments to script */ + status = docall(L, n, LUA_MULTRET); } return report(L, status); } @@ -570,7 +576,7 @@ static int pmain (lua_State *L) { if (!runargs(L, argv, script)) /* execute arguments -e and -l */ return 0; /* something failed */ if (script < argc && /* execute main script (if there is one) */ - handle_script(L, argv + script, argc - script) != LUA_OK) + handle_script(L, argv + script) != LUA_OK) return 0; if (args & has_i) /* -i option? */ doREPL(L); /* do read-eval-print loop */ @@ -1,5 +1,5 @@ /* -** $Id: lua.h,v 1.307 2014/06/10 17:41:38 roberto Exp $ +** $Id: lua.h,v 1.312 2014/07/31 13:44:30 roberto Exp $ ** Lua - A Scripting Language ** Lua.org, PUC-Rio, Brazil (http://www.lua.org) ** See Copyright Notice at the end of this file @@ -19,7 +19,7 @@ #define LUA_VERSION_MAJOR "5" #define LUA_VERSION_MINOR "3" #define LUA_VERSION_NUM 503 -#define LUA_VERSION_RELEASE "0 (work3)" +#define LUA_VERSION_RELEASE "0 (alpha)" #define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR #define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE @@ -53,30 +53,6 @@ typedef struct lua_State lua_State; -/* -** Type for C functions registered with Lua -*/ -typedef int (*lua_CFunction) (lua_State *L); - -/* -** Type for continuation functions -*/ -typedef int (*lua_KFunction) (lua_State *L, int status, int ctx); - - -/* -** functions that read/write blocks when loading/dumping Lua chunks -*/ -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); - - -/* -** prototype for memory-allocation functions -*/ -typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); - /* ** basic types @@ -117,6 +93,34 @@ typedef LUA_INTEGER lua_Integer; /* unsigned integer type */ typedef LUA_UNSIGNED lua_Unsigned; +/* type for continuation-function contexts */ +typedef LUA_CTXT lua_Ctx; + + +/* +** Type for C functions registered with Lua +*/ +typedef int (*lua_CFunction) (lua_State *L); + +/* +** Type for continuation functions +*/ +typedef int (*lua_KFunction) (lua_State *L, int status, lua_Ctx ctx); + + +/* +** Type for functions that read/write blocks when loading/dumping Lua chunks +*/ +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); + + +/* +** Type for memory-allocation functions +*/ +typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); + /* @@ -154,7 +158,6 @@ LUA_API int (lua_gettop) (lua_State *L); LUA_API void (lua_settop) (lua_State *L, int idx); LUA_API void (lua_pushvalue) (lua_State *L, int idx); LUA_API void (lua_rotate) (lua_State *L, int idx, int n); -LUA_API void (lua_replace) (lua_State *L, int idx); LUA_API void (lua_copy) (lua_State *L, int fromidx, int toidx); LUA_API int (lua_checkstack) (lua_State *L, int sz); @@ -175,7 +178,6 @@ LUA_API const char *(lua_typename) (lua_State *L, int tp); LUA_API lua_Number (lua_tonumberx) (lua_State *L, int idx, int *isnum); LUA_API lua_Integer (lua_tointegerx) (lua_State *L, int idx, int *isnum); -LUA_API lua_Unsigned (lua_tounsignedx) (lua_State *L, int idx, int *isnum); LUA_API int (lua_toboolean) (lua_State *L, int idx); 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); @@ -220,7 +222,6 @@ LUA_API int (lua_compare) (lua_State *L, int idx1, int idx2, int op); LUA_API void (lua_pushnil) (lua_State *L); LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); -LUA_API void (lua_pushunsigned) (lua_State *L, lua_Unsigned n); LUA_API const char *(lua_pushlstring) (lua_State *L, const char *s, size_t l); LUA_API const char *(lua_pushstring) (lua_State *L, const char *s); LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, @@ -264,12 +265,12 @@ LUA_API void (lua_setuservalue) (lua_State *L, int idx); /* ** 'load' and 'call' functions (load and run Lua code) */ -LUA_API void (lua_callk) (lua_State *L, int nargs, int nresults, int ctx, +LUA_API void (lua_callk) (lua_State *L, int nargs, int nresults, lua_Ctx ctx, lua_KFunction k); #define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL) LUA_API int (lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc, - int ctx, lua_KFunction k); + lua_Ctx ctx, lua_KFunction k); #define lua_pcall(L,n,r,f) lua_pcallk(L, (n), (r), (f), 0, NULL) LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, @@ -282,7 +283,7 @@ LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data, int strip); /* ** coroutine functions */ -LUA_API int (lua_yieldk) (lua_State *L, int nresults, int ctx, +LUA_API int (lua_yieldk) (lua_State *L, int nresults, lua_Ctx ctx, lua_KFunction k); #define lua_yield(L,n) lua_yieldk(L, (n), 0, NULL) LUA_API int (lua_resume) (lua_State *L, lua_State *from, int narg); @@ -326,14 +327,15 @@ LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); /* -** =============================================================== +** {============================================================== ** some useful macros ** =============================================================== */ +#define lua_getextraspace(L) ((void *)((char *)(L) - LUA_EXTRASPACE)) + #define lua_tonumber(L,i) lua_tonumberx(L,(i),NULL) #define lua_tointeger(L,i) lua_tointegerx(L,(i),NULL) -#define lua_tounsigned(L,i) lua_tounsignedx(L,(i),NULL) #define lua_pop(L,n) lua_settop(L, -(n)-1) @@ -365,6 +367,24 @@ LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); #define lua_remove(L,idx) (lua_rotate(L, (idx), -1), lua_pop(L, 1)) +#define lua_replace(L,idx) (lua_copy(L, -1, (idx)), lua_pop(L, 1)) + +/* }============================================================== */ + + +/* +** {============================================================== +** compatibility macros for unsigned conversions +** =============================================================== +*/ +#if defined(LUA_COMPAT_APIUNSIGNED) + +#define lua_pushunsigned(L,n) lua_pushinteger(L, (lua_Integer)(n)) +#define lua_tounsignedx(L,i,is) ((lua_Integer)lua_tointegerx(L,i,is)) +#define lua_tounsigned(L,i) lua_tounsignedx(L,(i),NULL) + +#endif +/* }============================================================== */ /* ** {====================================================================== @@ -203,7 +203,7 @@ int main(int argc, char* argv[]) } /* -** $Id: print.c,v 1.73 2014/06/12 02:41:25 lhf Exp $ +** $Id: print.c,v 1.74 2014/07/21 01:41:45 lhf Exp $ ** print bytecodes ** See Copyright Notice in lua.h */ @@ -223,7 +223,7 @@ int main(int argc, char* argv[]) static void PrintString(const TString* ts) { const char* s=getstr(ts); - size_t i,n=ts->tsv.len; + size_t i,n=ts->len; printf("%c",'"'); for (i=0; i<n; i++) { @@ -266,7 +266,7 @@ static void PrintConstant(const Proto* f, int i) printf(LUA_INTEGER_FMT,ivalue(o)); break; case LUA_TSHRSTR: case LUA_TLNGSTR: - PrintString(rawtsvalue(o)); + PrintString(tsvalue(o)); break; default: /* cannot happen */ printf("? type=%d",ttype(o)); diff --git a/src/luaconf.h b/src/luaconf.h index 2bceab1c..d3db9267 100644 --- a/src/luaconf.h +++ b/src/luaconf.h @@ -1,5 +1,5 @@ /* -** $Id: luaconf.h,v 1.207 2014/06/10 19:21:20 roberto Exp $ +** $Id: luaconf.h,v 1.212 2014/07/24 19:33:29 roberto Exp $ ** Configuration file for Lua ** See Copyright Notice in lua.h */ @@ -211,6 +211,14 @@ /* +@@ LUA_EXTRASPACE defines the size of a raw memory area associated with +** a Lua state with very fast access. +** CHANGE it if you need a different size. +*/ +#define LUA_EXTRASPACE (sizeof(void *)) + + +/* @@ LUA_QL describes how error messages quote program elements. ** CHANGE it if you want a different appearance. */ @@ -254,6 +262,22 @@ #define LUAI_MAXSHORTLEN 40 +/* +@@ LUA_CTXT is the type of the context ('ctx') for continuation functions. +@@ It must be a numerical type; Lua will use 'intptr_t' if available. +*/ +#if defined (LUA_USE_C99) +#include <stdint.h> +#if defined (INTPTR_MAX) /* even in C99 this type is optional */ +#define LUA_CTXT intptr_t +#endif +#endif + +#if !defined(LUA_CTXT) +/* default definition (the nearest thing to 'intptr_t' in C89) */ +#define LUA_CTXT ptrdiff_t +#endif + /* ** {================================================================== @@ -280,6 +304,17 @@ */ #define LUA_COMPAT_BITLIB +/* +@@ LUA_COMPAT_IPAIRS controls the effectivness of the __ipairs metamethod. +*/ +#define LUA_COMPAT_IPAIRS + +/* +@@ LUA_COMPAT_APIUNSIGNED controls the presence of macros for +** manipulating unsigned integers (lua_pushunsigned, lua_tounsigned, etc.) +*/ +#define LUA_COMPAT_APIUNSIGNED + /* @@ LUA_COMPAT_FLOATSTRING makes Lua format integral floats without a @@ -569,7 +604,6 @@ @@ LUA_INTEGER_FMT is the format for writing integers. @@ LUA_MAXINTEGER is the maximum value for a LUA_INTEGER. @@ LUA_MININTEGER is the minimum value for a LUA_INTEGER. -@@ LUA_MAXUNSIGNED is the maximum value for a LUA_UNSIGNED. @@ lua_integer2str converts an integer to a string. */ @@ -595,7 +629,6 @@ #define LUA_INTEGER int #define LUA_INTEGER_FRMLEN "" -#define LUA_MAXUNSIGNED UINT_MAX #define LUA_MAXINTEGER INT_MAX #define LUA_MININTEGER INT_MIN @@ -604,7 +637,6 @@ #define LUA_INTEGER long #define LUA_INTEGER_FRMLEN "l" -#define LUA_MAXUNSIGNED ULONG_MAX #define LUA_MAXINTEGER LONG_MAX #define LUA_MININTEGER LONG_MIN @@ -615,7 +647,6 @@ #define LUA_INTEGER __int64 #define LUA_INTEGER_FRMLEN "I64" -#define LUA_MAXUNSIGNED _UI64_MAX #define LUA_MAXINTEGER _I64_MAX #define LUA_MININTEGER _I64_MIN @@ -624,7 +655,6 @@ #define LUA_INTEGER long long #define LUA_INTEGER_FRMLEN "ll" -#define LUA_MAXUNSIGNED ULLONG_MAX #define LUA_MAXINTEGER LLONG_MAX #define LUA_MININTEGER LLONG_MIN @@ -639,7 +669,6 @@ #define LUA_INTEGER short int #define LUA_INTEGER_FRMLEN "" -#define LUA_MAXUNSIGNED ((LUA_UNSIGNED)USHRT_MAX) #define LUA_MAXINTEGER SHRT_MAX #define LUA_MININTEGER SHRT_MIN diff --git a/src/lutf8lib.c b/src/lutf8lib.c index 747c018d..1e848def 100644 --- a/src/lutf8lib.c +++ b/src/lutf8lib.c @@ -1,5 +1,5 @@ /* -** $Id: lutf8lib.c,v 1.9 2014/05/14 18:33:37 roberto Exp $ +** $Id: lutf8lib.c,v 1.10 2014/07/16 13:56:14 roberto Exp $ ** Standard library for UTF-8 manipulation ** See Copyright Notice in lua.h */ @@ -238,6 +238,8 @@ static struct luaL_Reg funcs[] = { {"char", utfchar}, {"len", utflen}, {"codes", iter_codes}, + /* placeholders */ + {"charpatt", NULL}, {NULL, NULL} }; @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.216 2014/06/19 18:27:20 roberto Exp $ +** $Id: lvm.c,v 2.222 2014/07/30 14:42:44 roberto Exp $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -33,10 +33,6 @@ #define MAXTAGLOOP 2000 -/* maximum length of the conversion of a number to a string */ -#define MAXNUMBER2STR 50 - - /* ** Similar to 'tonumber', but does not attempt to convert strings and ** ensure correct precision (no extra bits). Used in comparisons. @@ -70,7 +66,7 @@ int luaV_tonumber_ (const TValue *obj, lua_Number *n) { *n = fltvalue(obj); return 1; } - else if (ttisstring(obj) && /* string convertible to number? */ + else if (cvt2num(obj) && /* string convertible to number? */ luaO_str2num(svalue(obj), &v) == tsvalue(obj)->len + 1) { obj = &v; goto again; /* convert result from 'luaO_str2num' to a float */ @@ -80,21 +76,29 @@ int luaV_tonumber_ (const TValue *obj, lua_Number *n) { /* -** try to convert a value to an integer, rounding up if 'up' is true +** try to convert a value to an integer, rounding according to 'mode': +** mode == 0: accepts only integral values +** mode < 0: takes the floor of the number +** mode > 0: takes the ceil of the number */ -static int tointeger_aux (const TValue *obj, lua_Integer *p, int up) { +static int tointeger_aux (const TValue *obj, lua_Integer *p, int mode) { TValue v; again: if (ttisfloat(obj)) { lua_Number n = fltvalue(obj); - n = (up ? -l_floor(-n) : l_floor(n)); - return lua_numtointeger(n, p); + lua_Number f = l_floor(n); + if (n != f) { /* not an integral value? */ + if (mode == 0) return 0; /* fails if mode demands integral value */ + else if (mode > 0) /* needs ceil? */ + f += 1; /* convert floor to ceil (remember: n != f) */ + } + return lua_numtointeger(f, p); } else if (ttisinteger(obj)) { *p = ivalue(obj); return 1; } - else if (ttisstring(obj) && + else if (cvt2num(obj) && luaO_str2num(svalue(obj), &v) == tsvalue(obj)->len + 1) { obj = &v; goto again; /* convert result from 'luaO_str2num' to an integer */ @@ -104,7 +108,7 @@ static int tointeger_aux (const TValue *obj, lua_Integer *p, int up) { /* -** try to convert a non-integer value to an integer, rounding down +** try to convert a value to an integer */ int luaV_tointeger_ (const TValue *obj, lua_Integer *p) { return tointeger_aux(obj, p, 0); @@ -112,32 +116,6 @@ int luaV_tointeger_ (const TValue *obj, lua_Integer *p) { /* -** Convert a number object to a string -*/ -int luaV_tostring (lua_State *L, StkId obj) { - if (!ttisnumber(obj)) - return 0; - else { - char buff[MAXNUMBER2STR]; - size_t len; - if (ttisinteger(obj)) - len = lua_integer2str(buff, ivalue(obj)); - else { - len = lua_number2str(buff, fltvalue(obj)); -#if !defined(LUA_COMPAT_FLOATSTRING) - if (buff[strspn(buff, "-0123456789")] == '\0') { /* looks like an int? */ - buff[len++] = '.'; - buff[len++] = '0'; /* adds '.0' to result */ - } -#endif - } - setsvalue2s(L, obj, luaS_newlstr(L, buff, len)); - return 1; - } -} - - -/* ** Try to convert a 'for' limit to an integer, preserving the ** semantics of the loop. ** (The following explanation assumes a non-negative step; it is valid @@ -155,7 +133,7 @@ int luaV_tostring (lua_State *L, StkId obj) { static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step, int *stopnow) { *stopnow = 0; /* usually, let loops run */ - if (!tointeger_aux(obj, p, (step < 0))) { /* does not fit in integer? */ + if (!tointeger_aux(obj, p, (step < 0 ? 1 : -1))) { /* not fit in integer? */ lua_Number n; /* try to convert to float */ if (!tonumber(obj, &n)) /* cannot convert to float? */ return 0; /* not a number */ @@ -239,7 +217,7 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { luaT_callTM(L, tm, t, key, val, 0); return; } - t = tm; /* else repeat assginment over 'tm' */ + t = tm; /* else repeat assignment over 'tm' */ } luaG_runerror(L, "settable chain too long; possible loop"); } @@ -254,9 +232,9 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { */ static int l_strcmp (const TString *ls, const TString *rs) { const char *l = getstr(ls); - size_t ll = ls->tsv.len; + size_t ll = ls->len; const char *r = getstr(rs); - size_t lr = rs->tsv.len; + size_t lr = rs->len; for (;;) { /* for each segment */ int temp = strcoll(l, r); if (temp != 0) /* not equal? */ @@ -286,7 +264,7 @@ int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { else if (tofloat(l, &nl) && tofloat(r, &nr)) /* both are numbers? */ return luai_numlt(nl, nr); else if (ttisstring(l) && ttisstring(r)) /* both are strings? */ - return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; + return l_strcmp(tsvalue(l), tsvalue(r)) < 0; else if ((res = luaT_callorderTM(L, l, r, TM_LT)) < 0) /* no metamethod? */ luaG_ordererror(L, l, r); /* error */ return res; @@ -304,7 +282,7 @@ int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) { else if (tofloat(l, &nl) && tofloat(r, &nr)) /* both are numbers? */ return luai_numle(nl, nr); else if (ttisstring(l) && ttisstring(r)) /* both are strings? */ - return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; + return l_strcmp(tsvalue(l), tsvalue(r)) <= 0; else if ((res = luaT_callorderTM(L, l, r, TM_LE)) >= 0) /* first try `le' */ return res; else if ((res = luaT_callorderTM(L, r, l, TM_LT)) < 0) /* else try `lt' */ @@ -337,8 +315,8 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *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); - case LUA_TSHRSTR: return eqshrstr(rawtsvalue(t1), rawtsvalue(t2)); - case LUA_TLNGSTR: return luaS_eqlngstr(rawtsvalue(t1), rawtsvalue(t2)); + case LUA_TSHRSTR: return eqshrstr(tsvalue(t1), tsvalue(t2)); + case LUA_TLNGSTR: return luaS_eqlngstr(tsvalue(t1), tsvalue(t2)); case LUA_TUSERDATA: { if (uvalue(t1) == uvalue(t2)) return 1; else if (L == NULL) return 0; @@ -366,7 +344,8 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) { /* macro used by 'luaV_concat' to ensure that element at 'o' is a string */ -#define tostring(L,o) (ttisstring(o) || (luaV_tostring(L, o))) +#define tostring(L,o) \ + (ttisstring(o) || (cvt2str(o) && (luaO_tostring(L, o), 1))) /* ** Main operation for concatenation: concat 'total' values in the stack, @@ -377,7 +356,7 @@ 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 (!(ttisstring(top-2) || cvt2str(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? */ cast_void(tostring(L, top - 2)); /* result is first operand */ @@ -541,7 +520,7 @@ static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base, ncl->upvals[i]->refcount++; /* new closure is white, so we do not need a barrier here */ } - if (!isblack(obj2gco(p))) /* cache will not break GC invariant? */ + if (!isblack(p)) /* cache will not break GC invariant? */ p->cache = ncl; /* save it on cache for reuse */ } @@ -1,5 +1,5 @@ /* -** $Id: lvm.h,v 2.31 2014/05/26 17:10:22 roberto Exp $ +** $Id: lvm.h,v 2.33 2014/07/30 14:42:44 roberto Exp $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -13,6 +13,20 @@ #include "ltm.h" +#if !defined(LUA_NOCVTN2S) +#define cvt2str(o) ttisnumber(o) +#else +#define cvt2str(o) 0 /* no convertion from numbers to strings */ +#endif + + +#if !defined(LUA_NOCVTS2N) +#define cvt2num(o) ttisstring(o) +#else +#define cvt2num(o) 0 /* no convertion from strings to numbers */ +#endif + + #define tonumber(o,n) \ (ttisfloat(o) ? (*(n) = fltvalue(o), 1) : luaV_tonumber_(o,n)) @@ -29,7 +43,6 @@ LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r); LUAI_FUNC int luaV_tonumber_ (const TValue *obj, lua_Number *n); LUAI_FUNC int luaV_tointeger_ (const TValue *obj, lua_Integer *p); -LUAI_FUNC int luaV_tostring (lua_State *L, StkId obj); LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val); LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, |