Imported Upstream version 5.2.1 56/94756/1
authorDongHun Kwak <dh0128.kwak@samsung.com>
Tue, 1 Nov 2016 05:24:34 +0000 (14:24 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Tue, 1 Nov 2016 05:24:34 +0000 (14:24 +0900)
Change-Id: I5da25762cb8a8ced6e88f2c7186f0dfc4bacf4c9
Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
43 files changed:
Makefile
README
doc/contents.html
doc/lua.css
doc/manual.css
doc/manual.html
doc/readme.html
src/Makefile
src/lapi.c
src/lauxlib.c
src/lbaselib.c
src/lcorolib.c
src/ldblib.c
src/ldebug.c
src/ldo.c
src/ldump.c
src/lfunc.c
src/lfunc.h
src/lgc.c
src/lgc.h
src/llex.c
src/llimits.h
src/lmathlib.c
src/lmem.c
src/loadlib.c
src/lobject.h
src/lopcodes.c
src/loslib.c
src/lparser.c
src/lparser.h
src/lstate.c
src/lstate.h
src/lstring.c
src/lstring.h
src/lstrlib.c
src/ltable.c
src/lua.c
src/lua.h
src/luaconf.h
src/lundump.c
src/lundump.h
src/lvm.c
src/lzio.c

index ec53e1a..bd9515f 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -46,7 +46,7 @@ TO_MAN= lua.1 luac.1
 
 # Lua version and release.
 V= 5.2
-R= $V.0
+R= $V.1
 
 # Targets start here.
 all:   $(PLAT)
diff --git a/README b/README
index 9c38467..253d110 100644 (file)
--- a/README
+++ b/README
@@ -1,5 +1,5 @@
 
-This is Lua 5.2, released on 12 Dec 2011.
+This is Lua 5.2.1, released on 08 Jun 2012.
 
 For installation instructions, license details, and
 further information about Lua, see doc/readme.html.
index 5342723..9f50605 100644 (file)
@@ -33,9 +33,9 @@ For a complete introduction to Lua programming, see the book
 <A HREF="#index">index</A>
 <HR>
 <SMALL>
-Copyright &copy; 2011 Lua.org, PUC-Rio.
+Copyright &copy; 2011&ndash;2012 Lua.org, PUC-Rio.
 Freely available under the terms of the
-<A HREF="http://www.lua.org/license.html#5">Lua license</A>.
+<A HREF="http://www.lua.org/license.html">Lua license</A>.
 </SMALL>
 
 <H2><A NAME="contents">Contents</A></H2>
@@ -521,10 +521,10 @@ Freely available under the terms of the
 <HR>
 <SMALL CLASS="footer">
 Last update:
-Tue Nov 29 22:30:23 BRST 2011
+Sat May 26 08:52:25 BRT 2012
 </SMALL>
 <!--
-Last change: revised for Lua 5.2.0
+Last change: revised for Lua 5.2.1
 -->
 
 </BODY>
index 54708f8..7fafbb1 100644 (file)
@@ -3,8 +3,8 @@ body {
        background-color: #FFFFFF ;
        font-family: Helvetica, Arial, sans-serif ;
        text-align: justify ;
-       margin-right: 20px ;
-       margin-left: 20px ;
+       margin-right: 30px ;
+       margin-left: 30px ;
 }
 
 h1, h2, h3, h4 {
@@ -16,9 +16,9 @@ h1, h2, h3, h4 {
 h2 {
        padding-top: 0.4em ;
        padding-bottom: 0.4em ;
-       padding-left: 20px ;
-       padding-right: 20px ;
-       margin-left: -20px ;
+       padding-left: 30px ;
+       padding-right: 30px ;
+       margin-left: -30px ;
        background-color: #E0E0FF ;
 }
 
index ac357a8..b49b362 100644 (file)
@@ -18,7 +18,7 @@ span.apii {
 p+h1, ul+h1 {
        padding-top: 0.4em ;
        padding-bottom: 0.4em ;
-       padding-left: 20px ;
-       margin-left: -20px ;
+       padding-left: 30px ;
+       margin-left: -30px ;
        background-color: #E0E0FF ;
 }
index 360d316..4ba084d 100644 (file)
@@ -19,9 +19,9 @@ Lua 5.2 Reference Manual
 by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes
 <p>
 <small>
-Copyright &copy; 2011 Lua.org, PUC-Rio.
+Copyright &copy; 2011&ndash;2012 Lua.org, PUC-Rio.
 Freely available under the terms of the
-<a href="http://www.lua.org/license.html#5">Lua license</a>.
+<a href="http://www.lua.org/license.html">Lua license</a>.
 </small>
 <hr>
 <p>
@@ -33,7 +33,7 @@ Freely available under the terms of the
 <!-- ====================================================================== -->
 <p>
 
-<!-- $Id: manual.of,v 1.94 2011/12/12 15:26:26 roberto Exp $ -->
+<!-- $Id: manual.of,v 1.99 2012/06/08 15:30:20 roberto Exp $ -->
 
 
 
@@ -913,6 +913,14 @@ the object memory is freed only when it becomes completely inaccessible;
 its finalizer will never be called twice.
 
 
+<p>
+When you close a state (see <a href="#lua_close"><code>lua_close</code></a>),
+Lua calls the finalizers of all objects marked for collection,
+following the reverse order that they were marked.
+If any finalizer marks new objects for collection during that phase,
+these new objects will not be finalized.
+
+
 
 
 
@@ -1206,7 +1214,7 @@ results in a newline in the string.
 The escape sequence '<code>\z</code>' skips the following span
 of white-space characters,
 including line breaks;
-it is particularly useful to break and indent a long string
+it is particularly useful to break and indent a long literal string
 into multiple lines without adding the newlines and spaces
 into the string contents.
 
@@ -1234,7 +1242,7 @@ an opening long bracket of level&nbsp;1 is written as <code>[=[</code>,
 and so on.
 A <em>closing long bracket</em> is defined similarly;
 for instance, a closing long bracket of level&nbsp;4 is written as <code>]====]</code>.
-A long string starts with an opening long bracket of any level and
+A <em>long literal</em> starts with an opening long bracket of any level and
 ends at the first closing long bracket of the same level.
 It can contain any text except a closing bracket of the proper level.
 Literals in this bracketed form can run for several lines,
@@ -2820,8 +2828,7 @@ by looking only at its arguments
 The third field, <code>x</code>,
 tells whether the function may throw errors:
 '<code>-</code>' means the function never throws any error;
-'<code>m</code>' means the function may throw only memory allocation errors;
-'<code>e</code>' means the function may throw other kinds of errors;
+'<code>e</code>' means the function may throw errors;
 '<code>v</code>' means the function may throw an error on purpose.
 
 
@@ -2922,7 +2929,7 @@ it seems to be a safe assumption.)
 
 <hr><h3><a name="lua_arith"><code>lua_arith</code></a></h3><p>
 <span class="apii">[-(2|1), +1, <em>e</em>]</span>
-<pre>int lua_arith (lua_State *L, int op);</pre>
+<pre>void lua_arith (lua_State *L, int op);</pre>
 
 <p>
 Performs an arithmetic operation over the two values
@@ -3183,7 +3190,7 @@ without shifting any element
 
 
 <hr><h3><a name="lua_createtable"><code>lua_createtable</code></a></h3><p>
-<span class="apii">[-0, +1, <em>m</em>]</span>
+<span class="apii">[-0, +1, <em>e</em>]</span>
 <pre>void lua_createtable (lua_State *L, int narr, int nrec);</pre>
 
 <p>
@@ -3202,7 +3209,7 @@ Otherwise you can use the function <a href="#lua_newtable"><code>lua_newtable</c
 
 
 <hr><h3><a name="lua_dump"><code>lua_dump</code></a></h3><p>
-<span class="apii">[-0, +0, <em>m</em>]</span>
+<span class="apii">[-0, +0, <em>e</em>]</span>
 <pre>int lua_dump (lua_State *L, lua_Writer writer, void *data);</pre>
 
 <p>
@@ -3343,7 +3350,7 @@ opaque pointer passed to <a href="#lua_newstate"><code>lua_newstate</code></a>.
 
 <hr><h3><a name="lua_getctx"><code>lua_getctx</code></a></h3><p>
 <span class="apii">[-0, +0, &ndash;]</span>
-<pre>int lua_getctx  (lua_State *L, int *ctx);</pre>
+<pre>int lua_getctx (lua_State *L, int *ctx);</pre>
 
 <p>
 This function is called by a continuation function (see <a href="#4.7">&sect;4.7</a>)
@@ -3740,7 +3747,7 @@ passes to the allocator in every call.
 
 
 <hr><h3><a name="lua_newtable"><code>lua_newtable</code></a></h3><p>
-<span class="apii">[-0, +1, <em>m</em>]</span>
+<span class="apii">[-0, +1, <em>e</em>]</span>
 <pre>void lua_newtable (lua_State *L);</pre>
 
 <p>
@@ -3752,7 +3759,7 @@ It is equivalent to <code>lua_createtable(L, 0, 0)</code>.
 
 
 <hr><h3><a name="lua_newthread"><code>lua_newthread</code></a></h3><p>
-<span class="apii">[-0, +1, <em>m</em>]</span>
+<span class="apii">[-0, +1, <em>e</em>]</span>
 <pre>lua_State *lua_newthread (lua_State *L);</pre>
 
 <p>
@@ -3773,7 +3780,7 @@ like any Lua object.
 
 
 <hr><h3><a name="lua_newuserdata"><code>lua_newuserdata</code></a></h3><p>
-<span class="apii">[-0, +1, <em>m</em>]</span>
+<span class="apii">[-0, +1, <em>e</em>]</span>
 <pre>void *lua_newuserdata (lua_State *L, size_t size);</pre>
 
 <p>
@@ -3959,7 +3966,7 @@ Pushes a boolean value with value <code>b</code> onto the stack.
 
 
 <hr><h3><a name="lua_pushcclosure"><code>lua_pushcclosure</code></a></h3><p>
-<span class="apii">[-n, +1, <em>m</em>]</span>
+<span class="apii">[-n, +1, <em>e</em>]</span>
 <pre>void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n);</pre>
 
 <p>
@@ -4025,7 +4032,7 @@ Note that <code>f</code> is used twice.
 
 
 <hr><h3><a name="lua_pushfstring"><code>lua_pushfstring</code></a></h3><p>
-<span class="apii">[-0, +1, <em>m</em>]</span>
+<span class="apii">[-0, +1, <em>e</em>]</span>
 <pre>const char *lua_pushfstring (lua_State *L, const char *fmt, ...);</pre>
 
 <p>
@@ -4092,7 +4099,7 @@ light userdata with the same C&nbsp;address.
 
 
 <hr><h3><a name="lua_pushliteral"><code>lua_pushliteral</code></a></h3><p>
-<span class="apii">[-0, +1, <em>m</em>]</span>
+<span class="apii">[-0, +1, <em>e</em>]</span>
 <pre>const char *lua_pushliteral (lua_State *L, const char *s);</pre>
 
 <p>
@@ -4105,7 +4112,7 @@ It automatically provides the string length.
 
 
 <hr><h3><a name="lua_pushlstring"><code>lua_pushlstring</code></a></h3><p>
-<span class="apii">[-0, +1, <em>m</em>]</span>
+<span class="apii">[-0, +1, <em>e</em>]</span>
 <pre>const char *lua_pushlstring (lua_State *L, const char *s, size_t len);</pre>
 
 <p>
@@ -4148,7 +4155,7 @@ Pushes a number with value <code>n</code> onto the stack.
 
 
 <hr><h3><a name="lua_pushstring"><code>lua_pushstring</code></a></h3><p>
-<span class="apii">[-0, +1, <em>m</em>]</span>
+<span class="apii">[-0, +1, <em>e</em>]</span>
 <pre>const char *lua_pushstring (lua_State *L, const char *s);</pre>
 
 <p>
@@ -4195,7 +4202,7 @@ onto the stack.
 
 
 <hr><h3><a name="lua_pushvfstring"><code>lua_pushvfstring</code></a></h3><p>
-<span class="apii">[-0, +1, <em>m</em>]</span>
+<span class="apii">[-0, +1, <em>e</em>]</span>
 <pre>const char *lua_pushvfstring (lua_State *L,
                               const char *fmt,
                               va_list argp);</pre>
@@ -4282,7 +4289,7 @@ for other values, it is&nbsp;0.
 
 
 <hr><h3><a name="lua_rawset"><code>lua_rawset</code></a></h3><p>
-<span class="apii">[-2, +0, <em>m</em>]</span>
+<span class="apii">[-2, +0, <em>e</em>]</span>
 <pre>void lua_rawset (lua_State *L, int index);</pre>
 
 <p>
@@ -4294,7 +4301,7 @@ Similar to <a href="#lua_settable"><code>lua_settable</code></a>, but does a raw
 
 
 <hr><h3><a name="lua_rawseti"><code>lua_rawseti</code></a></h3><p>
-<span class="apii">[-1, +0, <em>m</em>]</span>
+<span class="apii">[-1, +0, <em>e</em>]</span>
 <pre>void lua_rawseti (lua_State *L, int index, int n);</pre>
 
 <p>
@@ -4313,7 +4320,7 @@ that is, it does not invoke metamethods.
 
 
 <hr><h3><a name="lua_rawsetp"><code>lua_rawsetp</code></a></h3><p>
-<span class="apii">[-1, +0, <em>m</em>]</span>
+<span class="apii">[-1, +0, <em>e</em>]</span>
 <pre>void lua_rawsetp (lua_State *L, int index, const void *p);</pre>
 
 <p>
@@ -4400,7 +4407,7 @@ and then pops the top element.
 
 <hr><h3><a name="lua_resume"><code>lua_resume</code></a></h3><p>
 <span class="apii">[-?, +?, &ndash;]</span>
-<pre>int lua_resume (lua_State *L, lua_State *from, int narg);</pre>
+<pre>int lua_resume (lua_State *L, lua_State *from, int nargs);</pre>
 
 <p>
 Starts and resumes a coroutine in a given thread.
@@ -4410,7 +4417,7 @@ Starts and resumes a coroutine in a given thread.
 To start a coroutine,
 you push onto the thread stack the main function plus any arguments;
 then you call <a href="#lua_resume"><code>lua_resume</code></a>,
-with <code>narg</code> being the number of arguments.
+with <code>nargs</code> being the number of arguments.
 This call returns when the coroutine suspends or finishes its execution.
 When it returns, the stack contains all values passed to <a href="#lua_yield"><code>lua_yield</code></a>,
 or all values returned by the body function.
@@ -4550,14 +4557,15 @@ the new value associated to the userdata at the given index.
 <pre>typedef struct lua_State lua_State;</pre>
 
 <p>
-An opaque structure that keeps the whole state of a Lua interpreter.
+An opaque structure that points to a thread and indirectly
+(through the thread) to the whole state of a Lua interpreter.
 The Lua library is fully reentrant:
 it has no global variables.
-All information about a state is kept in this structure.
+All information about a state is accessible through this structure.
 
 
 <p>
-A pointer to this state must be passed as the first argument to
+A pointer to this structure must be passed as the first argument to
 every function in the library, except to <a href="#lua_newstate"><code>lua_newstate</code></a>,
 which creates a Lua state from scratch.
 
@@ -4660,7 +4668,7 @@ indicates whether the operation succeeded.
 
 
 <hr><h3><a name="lua_tolstring"><code>lua_tolstring</code></a></h3><p>
-<span class="apii">[-0, +0, <em>m</em>]</span>
+<span class="apii">[-0, +0, <em>e</em>]</span>
 <pre>const char *lua_tolstring (lua_State *L, int index, size_t *len);</pre>
 
 <p>
@@ -4743,7 +4751,7 @@ Typically this function is used only for debug information.
 
 
 <hr><h3><a name="lua_tostring"><code>lua_tostring</code></a></h3><p>
-<span class="apii">[-0, +0, <em>m</em>]</span>
+<span class="apii">[-0, +0, <em>e</em>]</span>
 <pre>const char *lua_tostring (lua_State *L, int index);</pre>
 
 <p>
@@ -4848,7 +4856,7 @@ and
 
 <hr><h3><a name="lua_typename"><code>lua_typename</code></a></h3><p>
 <span class="apii">[-0, +0, &ndash;]</span>
-<pre>const char *lua_typename  (lua_State *L, int tp);</pre>
+<pre>const char *lua_typename (lua_State *L, int tp);</pre>
 
 <p>
 Returns the name of the type encoded by the value <code>tp</code>,
@@ -4932,7 +4940,7 @@ 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">[-?, +?, &ndash;]</span>
-<pre>int lua_yield  (lua_State *L, int nresults);</pre>
+<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>,
@@ -4947,7 +4955,7 @@ the function calling <code>lua_yield</code>.
 
 <hr><h3><a name="lua_yieldk"><code>lua_yieldk</code></a></h3><p>
 <span class="apii">[-?, +?, &ndash;]</span>
-<pre>int lua_yieldk  (lua_State *L, int nresults, int ctx, lua_CFunction k);</pre>
+<pre>int lua_yieldk (lua_State *L, int nresults, int ctx, lua_CFunction k);</pre>
 
 <p>
 Yields a coroutine.
@@ -5145,11 +5153,11 @@ Returns the current hook mask.
 
 
 <hr><h3><a name="lua_getinfo"><code>lua_getinfo</code></a></h3><p>
-<span class="apii">[-(0|1), +(0|1|2), <em>m</em>]</span>
+<span class="apii">[-(0|1), +(0|1|2), <em>e</em>]</span>
 <pre>int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);</pre>
 
 <p>
-Returns information about a specific function or function invocation.
+Gets information about a specific function or function invocation.
 
 
 <p>
@@ -5268,7 +5276,7 @@ the number of active local variables.
 <pre>int lua_getstack (lua_State *L, int level, lua_Debug *ar);</pre>
 
 <p>
-Get information about the interpreter runtime stack.
+Gets information about the interpreter runtime stack.
 
 
 <p>
@@ -5345,6 +5353,20 @@ Therefore, if a hook calls back Lua to execute a function or a chunk,
 this execution occurs without any calls to hooks.
 
 
+<p>
+Hook functions cannot have continuations,
+that is, they cannot call <a href="#lua_yieldk"><code>lua_yieldk</code></a>,
+<a href="#lua_pcallk"><code>lua_pcallk</code></a>, or <a href="#lua_callk"><code>lua_callk</code></a> with a non-null <code>k</code>.
+
+
+<p>
+Hook functions can yield under the following conditions:
+Only count and line events can yield
+and they cannot yield any value;
+to yield a hook function must finish its execution
+calling <a href="#lua_yield"><code>lua_yield</code></a> with <code>nresults</code> equal to zero.
+
+
 
 
 
@@ -5450,7 +5472,7 @@ when the index is greater than the number of upvalues.
 
 <p>
 Returns an unique identifier for the upvalue numbered <code>n</code>
-from the closure at index <code>fidx</code>.
+from the closure at index <code>funcindex</code>.
 Parameters <code>funcindex</code> and <code>n</code> are as in the <a href="#lua_getupvalue"><code>lua_getupvalue</code></a>
 (see <a href="#lua_getupvalue"><code>lua_getupvalue</code></a>)
 (but <code>n</code> cannot be greater than the number of upvalues).
@@ -5467,13 +5489,14 @@ will return identical ids for those upvalue indices.
 
 
 
-<hr><h3><a name="lua_upvaluejoin"><code>lua_upvaluejoin</code></a></h3>
-<pre>void lua_upvaluejoin (lua_State *L, int fidx1, int n1,
-                                    int fidx2, int n2);</pre>
+<hr><h3><a name="lua_upvaluejoin"><code>lua_upvaluejoin</code></a></h3><p>
+<span class="apii">[-0, +0, &ndash;]</span>
+<pre>void lua_upvaluejoin (lua_State *L, int funcindex1, int n1,
+                                    int funcindex2, int n2);</pre>
 
 <p>
-Make the <code>n1</code>-th upvalue of the Lua closure at index <code>fidx1</code>
-refer to the <code>n2</code>-th upvalue of the Lua closure at index <code>fidx2</code>.
+Make the <code>n1</code>-th upvalue of the Lua closure at index <code>funcindex1</code>
+refer to the <code>n2</code>-th upvalue of the Lua closure at index <code>funcindex2</code>.
 
 
 
@@ -5538,7 +5561,7 @@ in alphabetical order.
 
 
 <hr><h3><a name="luaL_addchar"><code>luaL_addchar</code></a></h3><p>
-<span class="apii">[-?, +?, <em>m</em>]</span>
+<span class="apii">[-?, +?, <em>e</em>]</span>
 <pre>void luaL_addchar (luaL_Buffer *B, char c);</pre>
 
 <p>
@@ -5550,7 +5573,7 @@ Adds the byte <code>c</code> to the buffer <code>B</code>
 
 
 <hr><h3><a name="luaL_addlstring"><code>luaL_addlstring</code></a></h3><p>
-<span class="apii">[-?, +?, <em>m</em>]</span>
+<span class="apii">[-?, +?, <em>e</em>]</span>
 <pre>void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l);</pre>
 
 <p>
@@ -5564,7 +5587,7 @@ The string can contain embedded zeros.
 
 
 <hr><h3><a name="luaL_addsize"><code>luaL_addsize</code></a></h3><p>
-<span class="apii">[-?, +?, <em>m</em>]</span>
+<span class="apii">[-?, +?, <em>e</em>]</span>
 <pre>void luaL_addsize (luaL_Buffer *B, size_t n);</pre>
 
 <p>
@@ -5577,7 +5600,7 @@ buffer area (see <a href="#luaL_prepbuffer"><code>luaL_prepbuffer</code></a>).
 
 
 <hr><h3><a name="luaL_addstring"><code>luaL_addstring</code></a></h3><p>
-<span class="apii">[-?, +?, <em>m</em>]</span>
+<span class="apii">[-?, +?, <em>e</em>]</span>
 <pre>void luaL_addstring (luaL_Buffer *B, const char *s);</pre>
 
 <p>
@@ -5591,7 +5614,7 @@ The string cannot contain embedded zeros.
 
 
 <hr><h3><a name="luaL_addvalue"><code>luaL_addvalue</code></a></h3><p>
-<span class="apii">[-1, +?, <em>m</em>]</span>
+<span class="apii">[-1, +?, <em>e</em>]</span>
 <pre>void luaL_addvalue (luaL_Buffer *B);</pre>
 
 <p>
@@ -5614,7 +5637,7 @@ which is the value to be added to the buffer.
 <span class="apii">[-0, +0, <em>v</em>]</span>
 <pre>void luaL_argcheck (lua_State *L,
                     int cond,
-                    int narg,
+                    int arg,
                     const char *extramsg);</pre>
 
 <p>
@@ -5627,7 +5650,7 @@ If not, raises an error with a standard message.
 
 <hr><h3><a name="luaL_argerror"><code>luaL_argerror</code></a></h3><p>
 <span class="apii">[-0, +0, <em>v</em>]</span>
-<pre>int luaL_argerror (lua_State *L, int narg, const char *extramsg);</pre>
+<pre>int luaL_argerror (lua_State *L, int arg, const char *extramsg);</pre>
 
 <p>
 Raises an error with a standard message
@@ -5686,7 +5709,7 @@ size <code>sz</code> with a call <code>luaL_buffinitsize(L, &amp;b, sz)</code>.<
 <li>Then copy the string into that space.</li>
 
 <li>
-Finish by calling <code>luaL_pushresult(&amp;b, sz)</code>,
+Finish by calling <code>luaL_pushresultsize(&amp;b, sz)</code>,
 where <code>sz</code> is the total size of the resulting string
 copied into that space.
 </li>
@@ -5728,7 +5751,7 @@ the buffer must be declared as a variable
 
 
 <hr><h3><a name="luaL_buffinitsize"><code>luaL_buffinitsize</code></a></h3><p>
-<span class="apii">[-?, +?, <em>m</em>]</span>
+<span class="apii">[-?, +?, <em>e</em>]</span>
 <pre>char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz);</pre>
 
 <p>
@@ -5762,11 +5785,11 @@ this function returns false (without pushing any value on the stack).
 
 <hr><h3><a name="luaL_checkany"><code>luaL_checkany</code></a></h3><p>
 <span class="apii">[-0, +0, <em>v</em>]</span>
-<pre>void luaL_checkany (lua_State *L, int narg);</pre>
+<pre>void luaL_checkany (lua_State *L, int arg);</pre>
 
 <p>
 Checks whether the function has an argument
-of any type (including <b>nil</b>) at position <code>narg</code>.
+of any type (including <b>nil</b>) at position <code>arg</code>.
 
 
 
@@ -5774,10 +5797,10 @@ of any type (including <b>nil</b>) at position <code>narg</code>.
 
 <hr><h3><a name="luaL_checkint"><code>luaL_checkint</code></a></h3><p>
 <span class="apii">[-0, +0, <em>v</em>]</span>
-<pre>int luaL_checkint (lua_State *L, int narg);</pre>
+<pre>int luaL_checkint (lua_State *L, int arg);</pre>
 
 <p>
-Checks whether the function argument <code>narg</code> is a number
+Checks whether the function argument <code>arg</code> is a number
 and returns this number cast to an <code>int</code>.
 
 
@@ -5786,10 +5809,10 @@ and returns this number cast to an <code>int</code>.
 
 <hr><h3><a name="luaL_checkinteger"><code>luaL_checkinteger</code></a></h3><p>
 <span class="apii">[-0, +0, <em>v</em>]</span>
-<pre>lua_Integer luaL_checkinteger (lua_State *L, int narg);</pre>
+<pre>lua_Integer luaL_checkinteger (lua_State *L, int arg);</pre>
 
 <p>
-Checks whether the function argument <code>narg</code> is a number
+Checks whether the function argument <code>arg</code> is a number
 and returns this number cast to a <a href="#lua_Integer"><code>lua_Integer</code></a>.
 
 
@@ -5798,10 +5821,10 @@ and returns this number cast to a <a href="#lua_Integer"><code>lua_Integer</code
 
 <hr><h3><a name="luaL_checklong"><code>luaL_checklong</code></a></h3><p>
 <span class="apii">[-0, +0, <em>v</em>]</span>
-<pre>long luaL_checklong (lua_State *L, int narg);</pre>
+<pre>long luaL_checklong (lua_State *L, int arg);</pre>
 
 <p>
-Checks whether the function argument <code>narg</code> is a number
+Checks whether the function argument <code>arg</code> is a number
 and returns this number cast to a <code>long</code>.
 
 
@@ -5810,10 +5833,10 @@ and returns this number cast to a <code>long</code>.
 
 <hr><h3><a name="luaL_checklstring"><code>luaL_checklstring</code></a></h3><p>
 <span class="apii">[-0, +0, <em>v</em>]</span>
-<pre>const char *luaL_checklstring (lua_State *L, int narg, size_t *l);</pre>
+<pre>const char *luaL_checklstring (lua_State *L, int arg, size_t *l);</pre>
 
 <p>
-Checks whether the function argument <code>narg</code> is a string
+Checks whether the function argument <code>arg</code> is a string
 and returns this string;
 if <code>l</code> is not <code>NULL</code> fills <code>*l</code>
 with the string's length.
@@ -5829,10 +5852,10 @@ so all conversions and caveats of that function apply here.
 
 <hr><h3><a name="luaL_checknumber"><code>luaL_checknumber</code></a></h3><p>
 <span class="apii">[-0, +0, <em>v</em>]</span>
-<pre>lua_Number luaL_checknumber (lua_State *L, int narg);</pre>
+<pre>lua_Number luaL_checknumber (lua_State *L, int arg);</pre>
 
 <p>
-Checks whether the function argument <code>narg</code> is a number
+Checks whether the function argument <code>arg</code> is a number
 and returns this number.
 
 
@@ -5842,12 +5865,12 @@ and returns this number.
 <hr><h3><a name="luaL_checkoption"><code>luaL_checkoption</code></a></h3><p>
 <span class="apii">[-0, +0, <em>v</em>]</span>
 <pre>int luaL_checkoption (lua_State *L,
-                      int narg,
+                      int arg,
                       const char *def,
                       const char *const lst[]);</pre>
 
 <p>
-Checks whether the function argument <code>narg</code> is a string and
+Checks whether the function argument <code>arg</code> is a string and
 searches for this string in the array <code>lst</code>
 (which must be NULL-terminated).
 Returns the index in the array where the string was found.
@@ -5858,7 +5881,7 @@ if the string cannot be found.
 <p>
 If <code>def</code> is not <code>NULL</code>,
 the function uses <code>def</code> as a default value when
-there is no argument <code>narg</code> or when this argument is <b>nil</b>.
+there is no argument <code>arg</code> or when this argument is <b>nil</b>.
 
 
 <p>
@@ -5886,10 +5909,10 @@ raising an error if the stack cannot grow to that size.
 
 <hr><h3><a name="luaL_checkstring"><code>luaL_checkstring</code></a></h3><p>
 <span class="apii">[-0, +0, <em>v</em>]</span>
-<pre>const char *luaL_checkstring (lua_State *L, int narg);</pre>
+<pre>const char *luaL_checkstring (lua_State *L, int arg);</pre>
 
 <p>
-Checks whether the function argument <code>narg</code> is a string
+Checks whether the function argument <code>arg</code> is a string
 and returns this string.
 
 
@@ -5903,10 +5926,10 @@ so all conversions and caveats of that function apply here.
 
 <hr><h3><a name="luaL_checktype"><code>luaL_checktype</code></a></h3><p>
 <span class="apii">[-0, +0, <em>v</em>]</span>
-<pre>void luaL_checktype (lua_State *L, int narg, int t);</pre>
+<pre>void luaL_checktype (lua_State *L, int arg, int t);</pre>
 
 <p>
-Checks whether the function argument <code>narg</code> has type <code>t</code>.
+Checks whether the function argument <code>arg</code> has type <code>t</code>.
 See <a href="#lua_type"><code>lua_type</code></a> for the encoding of types for <code>t</code>.
 
 
@@ -5915,10 +5938,10 @@ See <a href="#lua_type"><code>lua_type</code></a> for the encoding of types for
 
 <hr><h3><a name="luaL_checkudata"><code>luaL_checkudata</code></a></h3><p>
 <span class="apii">[-0, +0, <em>v</em>]</span>
-<pre>void *luaL_checkudata (lua_State *L, int narg, const char *tname);</pre>
+<pre>void *luaL_checkudata (lua_State *L, int arg, const char *tname);</pre>
 
 <p>
-Checks whether the function argument <code>narg</code> is a userdata
+Checks whether the function argument <code>arg</code> is a userdata
 of the type <code>tname</code> (see <a href="#luaL_newmetatable"><code>luaL_newmetatable</code></a>) and
 returns the userdata address (see <a href="#lua_touserdata"><code>lua_touserdata</code></a>).
 
@@ -5928,10 +5951,10 @@ 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 narg);</pre>
+<pre>lua_Unsigned luaL_checkunsigned (lua_State *L, int arg);</pre>
 
 <p>
-Checks whether the function argument <code>narg</code> is a number
+Checks whether the function argument <code>arg</code> is a number
 and returns this number cast to a <a href="#lua_Unsigned"><code>lua_Unsigned</code></a>.
 
 
@@ -5955,7 +5978,7 @@ are using the same address space.
 
 
 <hr><h3><a name="luaL_dofile"><code>luaL_dofile</code></a></h3><p>
-<span class="apii">[-0, +?, <em>m</em>]</span>
+<span class="apii">[-0, +?, <em>e</em>]</span>
 <pre>int luaL_dofile (lua_State *L, const char *filename);</pre>
 
 <p>
@@ -6014,7 +6037,7 @@ as <code>return luaL_error(<em>args</em>)</code>.
 
 
 <hr><h3><a name="luaL_execresult"><code>luaL_execresult</code></a></h3><p>
-<span class="apii">[-0, +3, <em>m</em>]</span>
+<span class="apii">[-0, +3, <em>e</em>]</span>
 <pre>int luaL_execresult (lua_State *L, int stat);</pre>
 
 <p>
@@ -6027,7 +6050,7 @@ process-related functions in the standard library
 
 
 <hr><h3><a name="luaL_fileresult"><code>luaL_fileresult</code></a></h3><p>
-<span class="apii">[-0, +(1|3), <em>m</em>]</span>
+<span class="apii">[-0, +(1|3), <em>e</em>]</span>
 <pre>int luaL_fileresult (lua_State *L, int stat, const char *fname);</pre>
 
 <p>
@@ -6040,7 +6063,7 @@ file-related functions in the standard library
 
 
 <hr><h3><a name="luaL_getmetafield"><code>luaL_getmetafield</code></a></h3><p>
-<span class="apii">[-0, +(0|1), <em>m</em>]</span>
+<span class="apii">[-0, +(0|1), <em>e</em>]</span>
 <pre>int luaL_getmetafield (lua_State *L, int obj, const char *e);</pre>
 
 <p>
@@ -6067,7 +6090,7 @@ in the registry (see <a href="#luaL_newmetatable"><code>luaL_newmetatable</code>
 
 
 <hr><h3><a name="luaL_getsubtable"><code>luaL_getsubtable</code></a></h3><p>
-<span class="apii">[-0, +1, <em>m</em>]</span>
+<span class="apii">[-0, +1, <em>e</em>]</span>
 <pre>int luaL_getsubtable (lua_State *L, int idx, const char *fname);</pre>
 
 <p>
@@ -6083,7 +6106,7 @@ and false if it creates a new table.
 
 
 <hr><h3><a name="luaL_gsub"><code>luaL_gsub</code></a></h3><p>
-<span class="apii">[-0, +1, <em>m</em>]</span>
+<span class="apii">[-0, +1, <em>e</em>]</span>
 <pre>const char *luaL_gsub (lua_State *L,
                        const char *s,
                        const char *p,
@@ -6100,7 +6123,7 @@ Pushes the resulting string on the stack and returns it.
 
 
 <hr><h3><a name="luaL_len"><code>luaL_len</code></a></h3><p>
-<span class="apii">[-0, +1, <em>e</em>]</span>
+<span class="apii">[-0, +0, <em>e</em>]</span>
 <pre>int luaL_len (lua_State *L, int index);</pre>
 
 <p>
@@ -6108,7 +6131,7 @@ Returns the "length" of the value at the given acceptable index
 as a number;
 it is equivalent to the '<code>#</code>' operator in Lua (see <a href="#3.4.6">&sect;3.4.6</a>).
 Raises an error if the result of the operation is not a number.
-(This only can happen through metamethods.)
+(This case only can happen through metamethods.)
 
 
 
@@ -6153,7 +6176,7 @@ The string <code>mode</code> works as in function <a href="#lua_load"><code>lua_
 
 
 <hr><h3><a name="luaL_loadfile"><code>luaL_loadfile</code></a></h3><p>
-<span class="apii">[-0, +1, <em>m</em>]</span>
+<span class="apii">[-0, +1, <em>e</em>]</span>
 <pre>int luaL_loadfile (lua_State *L, const char *filename);</pre>
 
 <p>
@@ -6164,7 +6187,7 @@ Equivalent to <a href="#luaL_loadfilex"><code>luaL_loadfilex</code></a> with <co
 
 
 <hr><h3><a name="luaL_loadfilex"><code>luaL_loadfilex</code></a></h3><p>
-<span class="apii">[-0, +1, <em>m</em>]</span>
+<span class="apii">[-0, +1, <em>e</em>]</span>
 <pre>int luaL_loadfilex (lua_State *L, const char *filename,
                                             const char *mode);</pre>
 
@@ -6218,7 +6241,7 @@ it does not run it.
 
 
 <hr><h3><a name="luaL_newlib"><code>luaL_newlib</code></a></h3><p>
-<span class="apii">[-0, +1, <em>m</em>]</span>
+<span class="apii">[-0, +1, <em>e</em>]</span>
 <pre>int luaL_newlib (lua_State *L, const luaL_Reg *l);</pre>
 
 <p>
@@ -6234,7 +6257,7 @@ It is implemented as the following macro:
 
 
 <hr><h3><a name="luaL_newlibtable"><code>luaL_newlibtable</code></a></h3><p>
-<span class="apii">[-0, +1, <em>m</em>]</span>
+<span class="apii">[-0, +1, <em>e</em>]</span>
 <pre>int luaL_newlibtable (lua_State *L, const luaL_Reg l[]);</pre>
 
 <p>
@@ -6255,7 +6278,7 @@ not a pointer to it.
 
 
 <hr><h3><a name="luaL_newmetatable"><code>luaL_newmetatable</code></a></h3><p>
-<span class="apii">[-0, +1, <em>m</em>]</span>
+<span class="apii">[-0, +1, <em>e</em>]</span>
 <pre>int luaL_newmetatable (lua_State *L, const char *tname);</pre>
 
 <p>
@@ -6309,10 +6332,10 @@ Opens all standard Lua libraries into the given state.
 
 <hr><h3><a name="luaL_optint"><code>luaL_optint</code></a></h3><p>
 <span class="apii">[-0, +0, <em>v</em>]</span>
-<pre>int luaL_optint (lua_State *L, int narg, int d);</pre>
+<pre>int luaL_optint (lua_State *L, int arg, int d);</pre>
 
 <p>
-If the function argument <code>narg</code> is a number,
+If the function argument <code>arg</code> is a number,
 returns this number cast to an <code>int</code>.
 If this argument is absent or is <b>nil</b>,
 returns <code>d</code>.
@@ -6325,11 +6348,11 @@ Otherwise, raises an error.
 <hr><h3><a name="luaL_optinteger"><code>luaL_optinteger</code></a></h3><p>
 <span class="apii">[-0, +0, <em>v</em>]</span>
 <pre>lua_Integer luaL_optinteger (lua_State *L,
-                             int narg,
+                             int arg,
                              lua_Integer d);</pre>
 
 <p>
-If the function argument <code>narg</code> is a number,
+If the function argument <code>arg</code> is a number,
 returns this number cast to a <a href="#lua_Integer"><code>lua_Integer</code></a>.
 If this argument is absent or is <b>nil</b>,
 returns <code>d</code>.
@@ -6341,10 +6364,10 @@ Otherwise, raises an error.
 
 <hr><h3><a name="luaL_optlong"><code>luaL_optlong</code></a></h3><p>
 <span class="apii">[-0, +0, <em>v</em>]</span>
-<pre>long luaL_optlong (lua_State *L, int narg, long d);</pre>
+<pre>long luaL_optlong (lua_State *L, int arg, long d);</pre>
 
 <p>
-If the function argument <code>narg</code> is a number,
+If the function argument <code>arg</code> is a number,
 returns this number cast to a <code>long</code>.
 If this argument is absent or is <b>nil</b>,
 returns <code>d</code>.
@@ -6357,12 +6380,12 @@ Otherwise, raises an error.
 <hr><h3><a name="luaL_optlstring"><code>luaL_optlstring</code></a></h3><p>
 <span class="apii">[-0, +0, <em>v</em>]</span>
 <pre>const char *luaL_optlstring (lua_State *L,
-                             int narg,
+                             int arg,
                              const char *d,
                              size_t *l);</pre>
 
 <p>
-If the function argument <code>narg</code> is a string,
+If the function argument <code>arg</code> is a string,
 returns this string.
 If this argument is absent or is <b>nil</b>,
 returns <code>d</code>.
@@ -6379,10 +6402,10 @@ fills the position <code>*l</code> with the result's length.
 
 <hr><h3><a name="luaL_optnumber"><code>luaL_optnumber</code></a></h3><p>
 <span class="apii">[-0, +0, <em>v</em>]</span>
-<pre>lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number d);</pre>
+<pre>lua_Number luaL_optnumber (lua_State *L, int arg, lua_Number d);</pre>
 
 <p>
-If the function argument <code>narg</code> is a number,
+If the function argument <code>arg</code> is a number,
 returns this number.
 If this argument is absent or is <b>nil</b>,
 returns <code>d</code>.
@@ -6395,11 +6418,11 @@ Otherwise, raises an error.
 <hr><h3><a name="luaL_optstring"><code>luaL_optstring</code></a></h3><p>
 <span class="apii">[-0, +0, <em>v</em>]</span>
 <pre>const char *luaL_optstring (lua_State *L,
-                            int narg,
+                            int arg,
                             const char *d);</pre>
 
 <p>
-If the function argument <code>narg</code> is a string,
+If the function argument <code>arg</code> is a string,
 returns this string.
 If this argument is absent or is <b>nil</b>,
 returns <code>d</code>.
@@ -6412,11 +6435,11 @@ 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 narg,
+                               int arg,
                                lua_Unsigned u);</pre>
 
 <p>
-If the function argument <code>narg</code> is a number,
+If the function argument <code>arg</code> is a number,
 returns this number cast to a <a href="#lua_Unsigned"><code>lua_Unsigned</code></a>.
 If this argument is absent or is <b>nil</b>,
 returns <code>u</code>.
@@ -6427,7 +6450,7 @@ Otherwise, raises an error.
 
 
 <hr><h3><a name="luaL_prepbuffer"><code>luaL_prepbuffer</code></a></h3><p>
-<span class="apii">[-?, +?, <em>m</em>]</span>
+<span class="apii">[-?, +?, <em>e</em>]</span>
 <pre>char *luaL_prepbuffer (luaL_Buffer *B);</pre>
 
 <p>
@@ -6439,7 +6462,7 @@ with the predefined size <a name="pdf-LUAL_BUFFERSIZE"><code>LUAL_BUFFERSIZE</co
 
 
 <hr><h3><a name="luaL_prepbuffsize"><code>luaL_prepbuffsize</code></a></h3><p>
-<span class="apii">[-?, +?, <em>m</em>]</span>
+<span class="apii">[-?, +?, <em>e</em>]</span>
 <pre>char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz);</pre>
 
 <p>
@@ -6455,7 +6478,7 @@ it to the buffer.
 
 
 <hr><h3><a name="luaL_pushresult"><code>luaL_pushresult</code></a></h3><p>
-<span class="apii">[-?, +1, <em>m</em>]</span>
+<span class="apii">[-?, +1, <em>e</em>]</span>
 <pre>void luaL_pushresult (luaL_Buffer *B);</pre>
 
 <p>
@@ -6467,7 +6490,7 @@ the top of the stack.
 
 
 <hr><h3><a name="luaL_pushresultsize"><code>luaL_pushresultsize</code></a></h3><p>
-<span class="apii">[-?, +1, <em>m</em>]</span>
+<span class="apii">[-?, +1, <em>e</em>]</span>
 <pre>void luaL_pushresultsize (luaL_Buffer *B, size_t sz);</pre>
 
 <p>
@@ -6478,7 +6501,7 @@ Equivalent to the sequence <a href="#luaL_addsize"><code>luaL_addsize</code></a>
 
 
 <hr><h3><a name="luaL_ref"><code>luaL_ref</code></a></h3><p>
-<span class="apii">[-1, +0, <em>m</em>]</span>
+<span class="apii">[-1, +0, <em>e</em>]</span>
 <pre>int luaL_ref (lua_State *L, int t);</pre>
 
 <p>
@@ -6582,8 +6605,8 @@ in the registry (see <a href="#luaL_newmetatable"><code>luaL_newmetatable</code>
 
 
 <hr><h3><a name="luaL_testudata"><code>luaL_testudata</code></a></h3><p>
-<span class="apii">[-0, +0, <em>m</em>]</span>
-<pre>void *luaL_testudata (lua_State *L, int narg, const char *tname);</pre>
+<span class="apii">[-0, +0, <em>e</em>]</span>
+<pre>void *luaL_testudata (lua_State *L, int arg, const char *tname);</pre>
 
 <p>
 This function works like <a href="#luaL_checkudata"><code>luaL_checkudata</code></a>,
@@ -6618,7 +6641,7 @@ and uses the result of the call as its result.
 
 
 <hr><h3><a name="luaL_traceback"><code>luaL_traceback</code></a></h3><p>
-<span class="apii">[-0, +1, <em>m</em>]</span>
+<span class="apii">[-0, +1, <em>e</em>]</span>
 <pre>void luaL_traceback (lua_State *L, lua_State *L1, const char *msg,
                      int level);</pre>
 
@@ -6665,7 +6688,7 @@ If <code>ref</code> is <a href="#pdf-LUA_NOREF"><code>LUA_NOREF</code></a> or <a
 
 
 <hr><h3><a name="luaL_where"><code>luaL_where</code></a></h3><p>
-<span class="apii">[-0, +1, <em>m</em>]</span>
+<span class="apii">[-0, +1, <em>e</em>]</span>
 <pre>void luaL_where (lua_State *L, int lvl);</pre>
 
 <p>
@@ -6749,7 +6772,7 @@ the host program can open them individually by using
 <a name="pdf-luaopen_string"><code>luaopen_string</code></a> (for the string library),
 <a name="pdf-luaopen_table"><code>luaopen_table</code></a> (for the table library),
 <a name="pdf-luaopen_math"><code>luaopen_math</code></a> (for the mathematical library),
-<a name="pdf-luaopen_bitlib"><code>luaopen_bitlib</code></a> (for the bit library),
+<a name="pdf-luaopen_bit32"><code>luaopen_bit32</code></a> (for the bit library),
 <a name="pdf-luaopen_io"><code>luaopen_io</code></a> (for the I/O library),
 <a name="pdf-luaopen_os"><code>luaopen_os</code></a> (for the Operating System library),
 and <a name="pdf-luaopen_debug"><code>luaopen_debug</code></a> (for the debug library).
@@ -7914,24 +7937,26 @@ If <code>repl</code> is a string, then its value is used for replacement.
 The character&nbsp;<code>%</code> works as an escape character:
 any sequence in <code>repl</code> of the form <code>%<em>d</em></code>,
 with <em>d</em> between 1 and 9,
-stands for the value of the <em>d</em>-th captured substring (see below).
+stands for the value of the <em>d</em>-th captured substring.
 The sequence <code>%0</code> stands for the whole match.
 The sequence <code>%%</code> stands for a single&nbsp;<code>%</code>.
 
 
 <p>
 If <code>repl</code> is a table, then the table is queried for every match,
-using the first capture as the key;
-if the pattern specifies no captures,
-then the whole match is used as the key.
+using the first capture as the key.
 
 
 <p>
 If <code>repl</code> is a function, then this function is called every time a
 match occurs, with all captured substrings passed as arguments,
-in order;
+in order.
+
+
+<p>
+In any case,
 if the pattern specifies no captures,
-then the whole match is passed as a sole argument.
+then it behaves as if the whole pattern was inside a capture.
 
 
 <p>
@@ -10091,6 +10116,9 @@ You can avoid some incompatibilities by compiling Lua with
 appropriate options (see file <code>luaconf.h</code>).
 However,
 all these compatibility options will be removed in the next version of Lua.
+Similarly,
+all features marked as deprecated in Lua&nbsp;5.1
+have been removed in Lua&nbsp;5.2.
 
 
 
@@ -10387,10 +10415,10 @@ Here is the complete syntax of Lua in extended BNF.
 <HR>
 <SMALL CLASS="footer">
 Last update:
-Mon Dec 12 15:21:08 BRST 2011
+Fri Jun  8 16:13:40 BRT 2012
 </SMALL>
 <!--
-Last change: revised for Lua 5.2.0
+Last change: revised for Lua 5.2.1
 -->
 
 </body></html>
index f0c77a1..2ff294e 100644 (file)
@@ -43,7 +43,6 @@ Welcome to Lua 5.2
 <A HREF="#license">license</A>
 &middot;
 <A HREF="contents.html">reference manual</A>
-<HR>
 
 <H2><A NAME="about">About Lua</A></H2>
 
@@ -101,14 +100,6 @@ Try also
 <A HREF="http://luaforwindows.luaforge.net/">Lua for Windows</A>,
 an easy-to-use distribution of Lua that includes many useful libraries.
 
-<!--
-<P>
-If you only want to try Lua,
-try the
-<A HREF="demo.html">live demo</A>.
-<P>
--->
-
 <H3>Building Lua</H3>
 
 <P>
@@ -118,7 +109,7 @@ Here are the details.
 <OL>
 <LI>
 Open a terminal window and move to
-the top-level directory, which is named <TT>lua-5.2.0</TT>.
+the top-level directory, which is named <TT>lua-5.2.1</TT>.
 The Makefile there controls both the build process and the installation process.
 <P>
 <LI>
@@ -381,7 +372,7 @@ For details, see
 <A HREF="http://www.lua.org/license.html">this</A>.
 
 <BLOCKQUOTE STYLE="padding-bottom: 0em">
-Copyright &copy; 1994&ndash;2011 Lua.org, PUC-Rio.
+Copyright &copy; 1994&ndash;2012 Lua.org, PUC-Rio.
 
 <P>
 Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -409,10 +400,10 @@ THE SOFTWARE.
 <HR>
 <SMALL CLASS="footer">
 Last update:
-Wed Nov 23 16:17:22 BRST 2011
+Tue May 29 21:57:51 BRT 2012
 </SMALL>
 <!--
-Last change: revised for Lua 5.2.0
+Last change: revised for Lua 5.2.1
 -->
 
 </BODY>
index bba1693..8c9ee67 100644 (file)
@@ -56,7 +56,7 @@ o:    $(ALL_O)
 a:     $(ALL_A)
 
 $(LUA_A): $(BASE_O)
-       $(AR) $@ $?
+       $(AR) $@ $(BASE_O)
        $(RANLIB) $@
 
 $(LUA_T): $(LUA_O) $(LUA_A)
index e96ceb9..1854fe6 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lapi.c,v 2.159 2011/11/30 12:32:05 roberto Exp $
+** $Id: lapi.c,v 2.164 2012/06/08 15:14:04 roberto Exp $
 ** Lua API
 ** See Copyright Notice in lua.h
 */
@@ -950,7 +950,7 @@ LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc,
     ci->u.c.k = k;  /* save continuation */
     ci->u.c.ctx = ctx;  /* save context */
     /* save information for error recovery */
-    ci->u.c.extra = savestack(L, c.func);
+    ci->extra = savestack(L, c.func);
     ci->u.c.old_allowhook = L->allowhook;
     ci->u.c.old_errfunc = L->errfunc;
     L->errfunc = func;
@@ -1045,17 +1045,17 @@ LUA_API int lua_gc (lua_State *L, int what, int data) {
     }
     case LUA_GCSTEP: {
       if (g->gckind == KGC_GEN) {  /* generational mode? */
-        res = (g->lastmajormem == 0);  /* 1 if will do major collection */
+        res = (g->GCestimate == 0);  /* true if it will do major collection */
         luaC_forcestep(L);  /* do a single step */
       }
       else {
-        while (data-- >= 0) {
-          luaC_forcestep(L);
-          if (g->gcstate == GCSpause) {  /* end of cycle? */
-            res = 1;  /* signal it */
-            break;
-          }
-        }
+       lu_mem debt = cast(lu_mem, data) * 1024 - GCSTEPSIZE;
+       if (g->gcrunning)
+         debt += g->GCdebt;  /* include current debt */
+       luaE_setdebt(g, debt);
+       luaC_forcestep(L);
+       if (g->gcstate == GCSpause)  /* end of cycle? */
+         res = 1;  /* signal it */
       }
       break;
     }
index 0aa80fd..36ae7e6 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lauxlib.c,v 1.240 2011/12/06 16:33:55 roberto Exp $
+** $Id: lauxlib.c,v 1.244 2012/05/31 20:28:45 roberto Exp $
 ** Auxiliary functions for building Lua libraries
 ** See Copyright Notice in lua.h
 */
@@ -520,11 +520,11 @@ LUALIB_API char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz) {
 
 LUALIB_API int luaL_ref (lua_State *L, int t) {
   int ref;
-  t = lua_absindex(L, t);
   if (lua_isnil(L, -1)) {
     lua_pop(L, 1);  /* remove from stack */
     return LUA_REFNIL;  /* `nil' has a unique fixed reference */
   }
+  t = lua_absindex(L, t);
   lua_rawgeti(L, t, freelist);  /* get first free element */
   ref = (int)lua_tointeger(L, -1);  /* ref = t[freelist] */
   lua_pop(L, 1);  /* remove it from stack */
@@ -616,8 +616,10 @@ static int skipBOM (LoadF *lf) {
 static int skipcomment (LoadF *lf, int *cp) {
   int c = *cp = skipBOM(lf);
   if (c == '#') {  /* first line is a comment (Unix exec. file)? */
-    while ((c = getc(lf->f)) != EOF && c != '\n') ;  /* skip first line */
-    *cp = getc(lf->f);  /* skip end-of-line */
+    do {  /* skip first line */
+      c = getc(lf->f);
+    } while (c != EOF && c != '\n') ;
+    *cp = getc(lf->f);  /* skip end-of-line, if present */
     return 1;  /* there was a comment */
   }
   else return 0;  /* no comment */
@@ -843,6 +845,7 @@ LUALIB_API void luaL_openlib (lua_State *L, const char *libname,
 ** Returns with only the table at the stack.
 */
 LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
+  luaL_checkversion(L);
   luaL_checkstack(L, nup, "too many upvalues");
   for (; l->name != NULL; l++) {  /* fill the table with given functions */
     int i;
@@ -863,8 +866,8 @@ LUALIB_API int luaL_getsubtable (lua_State *L, int idx, const char *fname) {
   lua_getfield(L, idx, fname);
   if (lua_istable(L, -1)) return 1;  /* table already there */
   else {
-    idx = lua_absindex(L, idx);
     lua_pop(L, 1);  /* remove previous result */
+    idx = lua_absindex(L, idx);
     lua_newtable(L);
     lua_pushvalue(L, -1);  /* copy to be left at top */
     lua_setfield(L, idx, fname);  /* assign new table to field */
@@ -889,10 +892,8 @@ LUALIB_API void luaL_requiref (lua_State *L, const char *modname,
   lua_setfield(L, -2, modname);  /* _LOADED[modname] = module */
   lua_pop(L, 1);  /* remove _LOADED table */
   if (glb) {
-    lua_pushglobaltable(L);
-    lua_pushvalue(L, -2);  /* copy of 'mod' */
-    lua_setfield(L, -2, modname);  /* _G[modname] = module */
-    lua_pop(L, 1);  /* remove _G table */
+    lua_pushvalue(L, -1);  /* copy of 'mod' */
+    lua_setglobal(L, modname);  /* _G[modname] = module */
   }
 }
 
index 1dfae30..dbfcb02 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lbaselib.c,v 1.273 2011/11/30 13:03:24 roberto Exp $
+** $Id: lbaselib.c,v 1.274 2012/04/27 14:13:19 roberto Exp $
 ** Basic library
 ** See Copyright Notice in lua.h
 */
@@ -293,6 +293,7 @@ static const char *generic_reader (lua_State *L, void *ud, size_t *size) {
   lua_pushvalue(L, 1);  /* get function */
   lua_call(L, 0, 1);  /* call it */
   if (lua_isnil(L, -1)) {
+    lua_pop(L, 1);  /* pop result */
     *size = 0;
     return NULL;
   }
index 0edde26..c7932d9 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lcorolib.c,v 1.3 2011/08/23 17:24:34 roberto Exp $
+** $Id: lcorolib.c,v 1.4 2012/04/27 18:59:04 roberto Exp $
 ** Coroutine Library
 ** See Copyright Notice in lua.h
 */
@@ -80,8 +80,9 @@ static int luaB_auxwrap (lua_State *L) {
 
 
 static int luaB_cocreate (lua_State *L) {
-  lua_State *NL = lua_newthread(L);
+  lua_State *NL;
   luaL_checktype(L, 1, LUA_TFUNCTION);
+  NL = lua_newthread(L);
   lua_pushvalue(L, 1);  /* move function to top */
   lua_xmove(L, NL, 1);  /* move function from L to NL */
   return 1;
index 3c2f159..c022694 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: ldblib.c,v 1.131 2011/10/24 14:54:05 roberto Exp $
+** $Id: ldblib.c,v 1.132 2012/01/19 20:14:44 roberto Exp $
 ** Interface from Lua to its debug API
 ** See Copyright Notice in lua.h
 */
@@ -253,14 +253,15 @@ static int db_upvaluejoin (lua_State *L) {
 }
 
 
-#define gethooktable(L)        luaL_getsubtable(L, LUA_REGISTRYINDEX, HOOKKEY);
+#define gethooktable(L)        luaL_getsubtable(L, LUA_REGISTRYINDEX, HOOKKEY)
 
 
 static void hookf (lua_State *L, lua_Debug *ar) {
   static const char *const hooknames[] =
     {"call", "return", "line", "count", "tail call"};
   gethooktable(L);
-  lua_rawgetp(L, -1, L);
+  lua_pushthread(L);
+  lua_rawget(L, -2);
   if (lua_isfunction(L, -1)) {
     lua_pushstring(L, hooknames[(int)ar->event]);
     if (ar->currentline >= 0)
@@ -306,10 +307,15 @@ static int db_sethook (lua_State *L) {
     count = luaL_optint(L, arg+3, 0);
     func = hookf; mask = makemask(smask, count);
   }
-  gethooktable(L);
+  if (gethooktable(L) == 0) {  /* creating hook table? */
+    lua_pushstring(L, "k");
+    lua_setfield(L, -2, "__mode");  /** hooktable.__mode = "k" */
+    lua_pushvalue(L, -1);
+    lua_setmetatable(L, -2);  /* setmetatable(hooktable) = hooktable */
+  }
+  lua_pushthread(L1); lua_xmove(L1, L, 1);
   lua_pushvalue(L, arg+1);
-  lua_rawsetp(L, -2, L1);  /* set new hook */
-  lua_pop(L, 1);  /* remove hook table */
+  lua_rawset(L, -3);  /* set new hook */
   lua_sethook(L1, func, mask, count);  /* set hooks */
   return 0;
 }
@@ -325,7 +331,8 @@ static int db_gethook (lua_State *L) {
     lua_pushliteral(L, "external hook");
   else {
     gethooktable(L);
-    lua_rawgetp(L, -1, L1);   /* get hook */
+    lua_pushthread(L1); lua_xmove(L1, L, 1);
+    lua_rawget(L, -2);   /* get hook */
     lua_remove(L, -2);  /* remove hook table */
   }
   lua_pushstring(L, unmakemask(mask, buff));
index 31b7ae4..43f8f04 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: ldebug.c,v 2.88 2011/11/30 12:43:51 roberto Exp $
+** $Id: ldebug.c,v 2.89 2012/01/20 22:05:50 roberto Exp $
 ** Debug Interface
 ** See Copyright Notice in lua.h
 */
@@ -30,6 +30,9 @@
 
 
 
+#define noLuaClosure(f)                ((f) == NULL || (f)->c.tt == LUA_TCCL)
+
+
 static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name);
 
 
@@ -173,7 +176,7 @@ LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
 
 
 static void funcinfo (lua_Debug *ar, Closure *cl) {
-  if (cl == NULL || cl->c.isC) {
+  if (noLuaClosure(cl)) {
     ar->source = "=[C]";
     ar->linedefined = -1;
     ar->lastlinedefined = -1;
@@ -191,7 +194,7 @@ static void funcinfo (lua_Debug *ar, Closure *cl) {
 
 
 static void collectvalidlines (lua_State *L, Closure *f) {
-  if (f == NULL || f->c.isC) {
+  if (noLuaClosure(f)) {
     setnilvalue(L->top);
     incr_top(L);
   }
@@ -210,7 +213,7 @@ static void collectvalidlines (lua_State *L, Closure *f) {
 
 
 static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
-                    Closure *f, CallInfo *ci) {
+                       Closure *f, CallInfo *ci) {
   int status = 1;
   for (; *what; what++) {
     switch (*what) {
@@ -224,7 +227,7 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
       }
       case 'u': {
         ar->nups = (f == NULL) ? 0 : f->c.nupvalues;
-        if (f == NULL || f->c.isC) {
+        if (noLuaClosure(f)) {
           ar->isvararg = 1;
           ar->nparams = 0;
         }
index 26f9a67..d18e33c 100644 (file)
--- a/src/ldo.c
+++ b/src/ldo.c
@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.c,v 2.102 2011/11/29 15:55:08 roberto Exp $
+** $Id: ldo.c,v 2.105 2012/06/08 15:14:04 roberto Exp $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
@@ -402,8 +402,6 @@ static void finishCcall (lua_State *L) {
   int n;
   lua_assert(ci->u.c.k != NULL);  /* must have a continuation */
   lua_assert(L->nny == 0);
-  /* finish 'luaD_call' */
-  L->nCcalls--;
   /* finish 'lua_callk' */
   adjustresults(L, ci->nresults);
   /* call continuation function */
@@ -453,7 +451,7 @@ static int recover (lua_State *L, int status) {
   CallInfo *ci = findpcall(L);
   if (ci == NULL) return 0;  /* no recovery point */
   /* "finish" luaD_pcall */
-  oldtop = restorestack(L, ci->u.c.extra);
+  oldtop = restorestack(L, ci->extra);
   luaF_close(L, oldtop);
   seterrorobj(L, status, oldtop);
   L->ci = ci;
@@ -484,9 +482,10 @@ static l_noret resume_error (lua_State *L, const char *msg, StkId firstArg) {
 ** do the work for 'lua_resume' in protected mode
 */
 static void resume (lua_State *L, void *ud) {
+  int nCcalls = L->nCcalls;
   StkId firstArg = cast(StkId, ud);
   CallInfo *ci = L->ci;
-  if (L->nCcalls >= LUAI_MAXCCALLS)
+  if (nCcalls >= LUAI_MAXCCALLS)
     resume_error(L, "C stack overflow", firstArg);
   if (L->status == LUA_OK) {  /* may be starting a coroutine */
     if (ci != &L->base_ci)  /* not in base level? */
@@ -499,10 +498,10 @@ static void resume (lua_State *L, void *ud) {
     resume_error(L, "cannot resume dead coroutine", firstArg);
   else {  /* resuming from previous yield */
     L->status = LUA_OK;
+    ci->func = restorestack(L, ci->extra);
     if (isLua(ci))  /* yielded inside a hook? */
       luaV_execute(L);  /* just continue running Lua code */
     else {  /* 'common' yield */
-      ci->func = restorestack(L, ci->u.c.extra);
       if (ci->u.c.k != NULL) {  /* does it have a continuation? */
         int n;
         ci->u.c.status = LUA_YIELD;  /* 'default' status */
@@ -513,11 +512,11 @@ static void resume (lua_State *L, void *ud) {
         api_checknelems(L, n);
         firstArg = L->top - n;  /* yield results come from continuation */
       }
-      L->nCcalls--;  /* finish 'luaD_call' */
       luaD_poscall(L, firstArg);  /* finish 'luaD_precall' */
     }
     unroll(L, NULL);
   }
+  lua_assert(nCcalls == L->nCcalls);
 }
 
 
@@ -564,13 +563,13 @@ LUA_API int lua_yieldk (lua_State *L, int nresults, int ctx, lua_CFunction k) {
       luaG_runerror(L, "attempt to yield from outside a coroutine");
   }
   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");
   }
   else {
     if ((ci->u.c.k = k) != NULL)  /* is there a continuation? */
       ci->u.c.ctx = ctx;  /* save context */
-    ci->u.c.extra = savestack(L, ci->func);  /* save current 'func' */
     ci->func = L->top - nresults - 1;  /* protect stack below results */
     luaD_throw(L, LUA_YIELD);
   }
@@ -627,24 +626,23 @@ static void checkmode (lua_State *L, const char *mode, const char *x) {
 
 static void f_parser (lua_State *L, void *ud) {
   int i;
-  Proto *tf;
   Closure *cl;
   struct SParser *p = cast(struct SParser *, ud);
   int c = zgetc(p->z);  /* read first character */
   if (c == LUA_SIGNATURE[0]) {
     checkmode(L, p->mode, "binary");
-    tf = luaU_undump(L, p->z, &p->buff, p->name);
+    cl = luaU_undump(L, p->z, &p->buff, p->name);
   }
   else {
     checkmode(L, p->mode, "text");
-    tf = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c);
+    cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c);
+  }
+  lua_assert(cl->l.nupvalues == cl->l.p->sizeupvalues);
+  for (i = 0; i < cl->l.nupvalues; i++) {  /* initialize upvalues */
+    UpVal *up = luaF_newupval(L);
+    cl->l.upvals[i] = up;
+    luaC_objbarrier(L, cl, up);
   }
-  setptvalue2s(L, L->top, tf);
-  incr_top(L);
-  cl = luaF_newLclosure(L, tf);
-  setclLvalue(L, L->top - 1, cl);
-  for (i = 0; i < tf->sizeupvalues; i++)  /* initialize upvalues */
-    cl->l.upvals[i] = luaF_newupval(L);
 }
 
 
index 699e1dc..d5e6a47 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: ldump.c,v 1.19 2011/11/23 17:48:18 lhf Exp $
+** $Id: ldump.c,v 2.17 2012/01/23 23:02:10 roberto Exp $
 ** save precompiled Lua chunks
 ** See Copyright Notice in lua.h
 */
@@ -84,8 +84,8 @@ static void DumpConstants(const Proto* f, DumpState* D)
  for (i=0; i<n; i++)
  {
   const TValue* o=&f->k[i];
-  DumpChar(ttype(o),D);
-  switch (ttype(o))
+  DumpChar(ttypenv(o),D);
+  switch (ttypenv(o))
   {
    case LUA_TNIL:
        break;
@@ -98,6 +98,7 @@ static void DumpConstants(const Proto* f, DumpState* D)
    case LUA_TSTRING:
        DumpString(rawtsvalue(o),D);
        break;
+    default: lua_assert(0);
   }
  }
  n=f->sizep;
index 1a1a8bb..4fd27fe 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lfunc.c,v 2.27 2010/06/30 14:11:17 roberto Exp $
+** $Id: lfunc.c,v 2.29 2012/05/08 13:53:33 roberto Exp $
 ** Auxiliary functions to manipulate prototypes and closures
 ** See Copyright Notice in lua.h
 */
 
 
 Closure *luaF_newCclosure (lua_State *L, int n) {
-  Closure *c = &luaC_newobj(L, LUA_TFUNCTION, sizeCclosure(n), NULL, 0)->cl;
-  c->c.isC = 1;
+  Closure *c = &luaC_newobj(L, LUA_TCCL, sizeCclosure(n), NULL, 0)->cl;
   c->c.nupvalues = cast_byte(n);
   return c;
 }
 
 
-Closure *luaF_newLclosure (lua_State *L, Proto *p) {
-  int n = p->sizeupvalues;
-  Closure *c = &luaC_newobj(L, LUA_TFUNCTION, sizeLclosure(n), NULL, 0)->cl;
-  c->l.isC = 0;
-  c->l.p = p;
+Closure *luaF_newLclosure (lua_State *L, int n) {
+  Closure *c = &luaC_newobj(L, LUA_TLCL, sizeLclosure(n), NULL, 0)->cl;
+  c->l.p = NULL;
   c->l.nupvalues = cast_byte(n);
   while (n--) c->l.upvals[n] = NULL;
   return c;
@@ -146,13 +143,6 @@ void luaF_freeproto (lua_State *L, Proto *f) {
 }
 
 
-void luaF_freeclosure (lua_State *L, Closure *c) {
-  int size = (c->c.isC) ? sizeCclosure(c->c.nupvalues) :
-                          sizeLclosure(c->l.nupvalues);
-  luaM_freemem(L, c, size);
-}
-
-
 /*
 ** Look for n-th local variable at line `line' in function `func'.
 ** Returns NULL if not found.
index da18923..e236a71 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lfunc.h,v 2.6 2010/06/04 13:06:15 roberto Exp $
+** $Id: lfunc.h,v 2.8 2012/05/08 13:53:33 roberto Exp $
 ** Auxiliary functions to manipulate prototypes and closures
 ** See Copyright Notice in lua.h
 */
 
 LUAI_FUNC Proto *luaF_newproto (lua_State *L);
 LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems);
-LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, Proto *p);
+LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems);
 LUAI_FUNC UpVal *luaF_newupval (lua_State *L);
 LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level);
 LUAI_FUNC void luaF_close (lua_State *L, StkId level);
 LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f);
-LUAI_FUNC void luaF_freeclosure (lua_State *L, Closure *c);
 LUAI_FUNC void luaF_freeupval (lua_State *L, UpVal *uv);
 LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number,
                                          int pc);
index cdd92e5..06f972a 100644 (file)
--- a/src/lgc.c
+++ b/src/lgc.c
@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.c,v 2.116 2011/12/02 13:18:41 roberto Exp $
+** $Id: lgc.c,v 2.133 2012/05/31 21:28:59 roberto Exp $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
 
 
 
-/* how much to allocate before next GC step */
-#define GCSTEPSIZE     1024
+/*
+** cost of sweeping one element (the size of a small object divided
+** by some adjust for the sweep speed)
+*/
+#define GCSWEEPCOST    ((sizeof(TString) + 4) / 4)
 
 /* maximum number of elements to sweep in each single step */
-#define GCSWEEPMAX     40
-
-/* cost of sweeping one element */
-#define GCSWEEPCOST    1
+#define GCSWEEPMAX     (cast_int((GCSTEPSIZE / GCSWEEPCOST) / 4))
 
 /* maximum number of finalizers to call in each GC step */
 #define GCFINALIZENUM  4
 
-/* cost of marking the root set */
-#define GCROOTCOST     10
 
-/* cost of atomic step */
-#define GCATOMICCOST   1000
+/*
+** macro to adjust 'stepmul': 'stepmul' is actually used like
+** 'stepmul / STEPMULADJ' (value chosen by tests)
+*/
+#define STEPMULADJ             200
+
+/*
+** macro to adjust 'pause': 'pause' is actually used like
+** 'pause / PAUSEADJ' (value chosen by tests)
+*/
+#define PAUSEADJ               200
+
 
-/* basic cost to traverse one object (to be added to the links the
-   object may have) */
-#define TRAVCOST       5
 
 
 /*
 ** standard negative debt for GC; a reasonable "time" to wait before
 ** starting a new cycle
 */
-#define stddebt(g)     (-cast(l_mem, gettotalbytes(g)/100) * g->gcpause)
+#define stddebtest(g,e)        (-cast(l_mem, (e)/PAUSEADJ) * g->gcpause)
+#define stddebt(g)     stddebtest(g, gettotalbytes(g))
 
 
 /*
@@ -65,8 +71,6 @@
 #define white2gray(x)  resetbits(gch(x)->marked, WHITEBITS)
 #define black2gray(x)  resetbit(gch(x)->marked, BLACKBIT)
 
-#define stringmark(s)  ((void)((s) && resetbits((s)->tsv.marked, WHITEBITS)))
-
 
 #define isfinalized(x)         testbit(gch(x)->marked, FINALIZEDBIT)
 
@@ -123,10 +127,10 @@ static void removeentry (Node *n) {
 ** other objects: if really collected, cannot keep them; for objects
 ** being finalized, keep them in keys, but not in values
 */
-static int iscleared (const TValue *o) {
+static int iscleared (global_State *g, const TValue *o) {
   if (!iscollectable(o)) return 0;
   else if (ttisstring(o)) {
-    stringmark(rawtsvalue(o));  /* strings are `values', so are never weak */
+    markobject(g, rawtsvalue(o));  /* strings are `values', so are never weak */
     return 0;
   }
   else return iswhite(gcvalue(o));
@@ -217,7 +221,8 @@ void luaC_checkupvalcolor (global_State *g, UpVal *uv) {
 GCObject *luaC_newobj (lua_State *L, int tt, size_t sz, GCObject **list,
                        int offset) {
   global_State *g = G(L);
-  GCObject *o = obj2gco(cast(char *, luaM_newobject(L, tt, sz)) + offset);
+  char *raw = cast(char *, luaM_newobject(L, novariant(tt), sz));
+  GCObject *o = obj2gco(raw + offset);
   if (list == NULL)
     list = &g->allgc;  /* standard list for collectable objects */
   gch(o)->marked = luaC_white(g);
@@ -239,54 +244,63 @@ GCObject *luaC_newobj (lua_State *L, int tt, size_t sz, GCObject **list,
 
 
 /*
-** mark an object. Userdata and closed upvalues are visited and turned
-** black here. Strings remain gray (it is the same as making them
-** black). Other objects are marked gray and added to appropriate list
-** to be visited (and turned black) later. (Open upvalues are already
-** linked in 'headuv' list.)
+** mark an object. Userdata, strings, and closed upvalues are visited
+** and turned black here. Other objects are marked gray and added
+** to appropriate list to be visited (and turned black) later. (Open
+** upvalues are already linked in 'headuv' list.)
 */
 static void reallymarkobject (global_State *g, GCObject *o) {
-  lua_assert(iswhite(o) && !isdead(g, o));
+  lu_mem size;
   white2gray(o);
   switch (gch(o)->tt) {
-    case LUA_TSTRING: {
-      return;  /* for strings, gray is as good as black */
+    case LUA_TSHRSTR:
+    case LUA_TLNGSTR: {
+      size = sizestring(gco2ts(o));
+      break;  /* nothing else to mark; make it black */
     }
     case LUA_TUSERDATA: {
       Table *mt = gco2u(o)->metatable;
       markobject(g, mt);
       markobject(g, gco2u(o)->env);
-      gray2black(o);  /* all pointers marked */
-      return;
+      size = sizeudata(gco2u(o));
+      break;
     }
     case LUA_TUPVAL: {
       UpVal *uv = gco2uv(o);
       markvalue(g, uv->v);
-      if (uv->v == &uv->u.value)  /* closed? (open upvalues remain gray) */
-        gray2black(o);  /* make it black */
+      if (uv->v != &uv->u.value)  /* open? */
+        return;  /* open upvalues remain gray */
+      size = sizeof(UpVal);
+      break;
+    }
+    case LUA_TLCL: {
+      gco2lcl(o)->gclist = g->gray;
+      g->gray = o;
       return;
     }
-    case LUA_TFUNCTION: {
-      gco2cl(o)->c.gclist = g->gray;
+    case LUA_TCCL: {
+      gco2ccl(o)->gclist = g->gray;
       g->gray = o;
-      break;
+      return;
     }
     case LUA_TTABLE: {
       linktable(gco2t(o), &g->gray);
-      break;
+      return;
     }
     case LUA_TTHREAD: {
       gco2th(o)->gclist = g->gray;
       g->gray = o;
-      break;
+      return;
     }
     case LUA_TPROTO: {
       gco2p(o)->gclist = g->gray;
       g->gray = o;
-      break;
+      return;
     }
-    default: lua_assert(0);
+    default: lua_assert(0); return;
   }
+  gray2black(o);
+  g->GCmemtrav += size;
 }
 
 
@@ -359,7 +373,7 @@ static void traverseweakvalue (global_State *g, Table *h) {
     else {
       lua_assert(!ttisnil(gkey(n)));
       markvalue(g, gkey(n));  /* mark key */
-      if (!hasclears && iscleared(gval(n)))  /* is there a white value? */
+      if (!hasclears && iscleared(g, gval(n)))  /* is there a white value? */
         hasclears = 1;  /* table will have to be cleared */
     }
   }
@@ -388,7 +402,7 @@ static int traverseephemeron (global_State *g, Table *h) {
     checkdeadkey(n);
     if (ttisnil(gval(n)))  /* entry is empty? */
       removeentry(n);  /* remove it */
-    else if (iscleared(gkey(n))) {  /* key is not marked (yet)? */
+    else if (iscleared(g, gkey(n))) {  /* key is not marked (yet)? */
       hasclears = 1;  /* table must be cleared */
       if (valiswhite(gval(n)))  /* value not marked yet? */
         prop = 1;  /* must propagate again */
@@ -426,30 +440,26 @@ static void traversestrongtable (global_State *g, Table *h) {
 }
 
 
-static int traversetable (global_State *g, Table *h) {
+static lu_mem traversetable (global_State *g, Table *h) {
+  const char *weakkey, *weakvalue;
   const TValue *mode = gfasttm(g, h->metatable, TM_MODE);
   markobject(g, h->metatable);
-  if (mode && ttisstring(mode)) {  /* is there a weak mode? */
-    int weakkey = (strchr(svalue(mode), 'k') != NULL);
-    int weakvalue = (strchr(svalue(mode), 'v') != NULL);
-    if (weakkey || weakvalue) {  /* is really weak? */
-      black2gray(obj2gco(h));  /* keep table gray */
-      if (!weakkey) {  /* strong keys? */
-        traverseweakvalue(g, h);
-        return TRAVCOST + sizenode(h);
-      }
-      else if (!weakvalue) {  /* strong values? */
-        traverseephemeron(g, h);
-        return TRAVCOST + h->sizearray + sizenode(h);
-      }
-      else {
-        linktable(h, &g->allweak);  /* nothing to traverse now */
-        return TRAVCOST;
-      }
-    }  /* else go through */
+  if (mode && ttisstring(mode) &&  /* is there a weak mode? */
+      ((weakkey = strchr(svalue(mode), 'k')),
+       (weakvalue = strchr(svalue(mode), 'v')),
+       (weakkey || weakvalue))) {  /* is really weak? */
+    black2gray(obj2gco(h));  /* keep table gray */
+    if (!weakkey)  /* strong keys? */
+      traverseweakvalue(g, h);
+    else if (!weakvalue)  /* strong values? */
+      traverseephemeron(g, h);
+    else  /* all weak */
+      linktable(h, &g->allweak);  /* nothing to traverse now */
   }
-  traversestrongtable(g, h);
-  return TRAVCOST + h->sizearray + (2 * sizenode(h));
+  else  /* not weak */
+    traversestrongtable(g, h);
+  return sizeof(Table) + sizeof(TValue) * h->sizearray +
+                         sizeof(Node) * sizenode(h);
 }
 
 
@@ -457,86 +467,101 @@ static int traverseproto (global_State *g, Proto *f) {
   int i;
   if (f->cache && iswhite(obj2gco(f->cache)))
     f->cache = NULL;  /* allow cache to be collected */
-  stringmark(f->source);
+  markobject(g, f->source);
   for (i = 0; i < f->sizek; i++)  /* mark literals */
     markvalue(g, &f->k[i]);
   for (i = 0; i < f->sizeupvalues; i++)  /* mark upvalue names */
-    stringmark(f->upvalues[i].name);
+    markobject(g, f->upvalues[i].name);
   for (i = 0; i < f->sizep; i++)  /* mark nested protos */
     markobject(g, f->p[i]);
   for (i = 0; i < f->sizelocvars; i++)  /* mark local-variable names */
-    stringmark(f->locvars[i].varname);
-  return TRAVCOST + f->sizek + f->sizeupvalues + f->sizep + f->sizelocvars;
+    markobject(g, f->locvars[i].varname);
+  return sizeof(Proto) + sizeof(Instruction) * f->sizecode +
+                         sizeof(Proto *) * f->sizep +
+                         sizeof(TValue) * f->sizek +
+                         sizeof(int) * f->sizelineinfo +
+                         sizeof(LocVar) * f->sizelocvars +
+                         sizeof(Upvaldesc) * f->sizeupvalues;
 }
 
 
-static int traverseclosure (global_State *g, Closure *cl) {
-  if (cl->c.isC) {
-    int i;
-    for (i=0; i<cl->c.nupvalues; i++)  /* mark its upvalues */
-      markvalue(g, &cl->c.upvalue[i]);
-  }
-  else {
-    int i;
-    lua_assert(cl->l.nupvalues == cl->l.p->sizeupvalues);
-    markobject(g, cl->l.p);  /* mark its prototype */
-    for (i=0; i<cl->l.nupvalues; i++)  /* mark its upvalues */
-      markobject(g, cl->l.upvals[i]);
-  }
-  return TRAVCOST + cl->c.nupvalues;
+static lu_mem traverseCclosure (global_State *g, CClosure *cl) {
+  int i;
+  for (i = 0; i < cl->nupvalues; i++)  /* mark its upvalues */
+    markvalue(g, &cl->upvalue[i]);
+  return sizeCclosure(cl->nupvalues);
+}
+
+static lu_mem traverseLclosure (global_State *g, LClosure *cl) {
+  int i;
+  markobject(g, cl->p);  /* mark its prototype */
+  for (i = 0; i < cl->nupvalues; i++)  /* mark its upvalues */
+    markobject(g, cl->upvals[i]);
+  return sizeLclosure(cl->nupvalues);
 }
 
 
-static int traversestack (global_State *g, lua_State *L) {
-  StkId o = L->stack;
+static lu_mem traversestack (global_State *g, lua_State *th) {
+  StkId o = th->stack;
   if (o == NULL)
     return 1;  /* stack not completely built yet */
-  for (; o < L->top; o++)
+  for (; o < th->top; o++)
     markvalue(g, o);
   if (g->gcstate == GCSatomic) {  /* final traversal? */
-    StkId lim = L->stack + L->stacksize;  /* real end of stack */
+    StkId lim = th->stack + th->stacksize;  /* real end of stack */
     for (; o < lim; o++)  /* clear not-marked stack slice */
       setnilvalue(o);
   }
-  return TRAVCOST + cast_int(o - L->stack);
+  return sizeof(lua_State) + sizeof(TValue) * th->stacksize;
 }
 
 
 /*
 ** traverse one gray object, turning it to black (except for threads,
 ** which are always gray).
-** Returns number of values traversed.
 */
-static int propagatemark (global_State *g) {
+static void propagatemark (global_State *g) {
+  lu_mem size;
   GCObject *o = g->gray;
   lua_assert(isgray(o));
   gray2black(o);
   switch (gch(o)->tt) {
     case LUA_TTABLE: {
       Table *h = gco2t(o);
-      g->gray = h->gclist;
-      return traversetable(g, h);
+      g->gray = h->gclist;  /* remove from 'gray' list */
+      size = traversetable(g, h);
+      break;
+    }
+    case LUA_TLCL: {
+      LClosure *cl = gco2lcl(o);
+      g->gray = cl->gclist;  /* remove from 'gray' list */
+      size = traverseLclosure(g, cl);
+      break;
     }
-    case LUA_TFUNCTION: {
-      Closure *cl = gco2cl(o);
-      g->gray = cl->c.gclist;
-      return traverseclosure(g, cl);
+    case LUA_TCCL: {
+      CClosure *cl = gco2ccl(o);
+      g->gray = cl->gclist;  /* remove from 'gray' list */
+      size = traverseCclosure(g, cl);
+      break;
     }
     case LUA_TTHREAD: {
       lua_State *th = gco2th(o);
-      g->gray = th->gclist;
+      g->gray = th->gclist;  /* remove from 'gray' list */
       th->gclist = g->grayagain;
-      g->grayagain = o;
+      g->grayagain = o;  /* insert into 'grayagain' list */
       black2gray(o);
-      return traversestack(g, th);
+      size = traversestack(g, th);
+      break;
     }
     case LUA_TPROTO: {
       Proto *p = gco2p(o);
-      g->gray = p->gclist;
-      return traverseproto(g, p);
+      g->gray = p->gclist;  /* remove from 'gray' list */
+      size = traverseproto(g, p);
+      break;
     }
-    default: lua_assert(0); return 0;
+    default: lua_assert(0); return;
   }
+  g->GCmemtrav += size;
 }
 
 
@@ -599,12 +624,12 @@ static void convergeephemerons (global_State *g) {
 ** clear entries with unmarked keys from all weaktables in list 'l' up
 ** to element 'f'
 */
-static void clearkeys (GCObject *l, GCObject *f) {
+static void clearkeys (global_State *g, GCObject *l, GCObject *f) {
   for (; l != f; l = gco2t(l)->gclist) {
     Table *h = gco2t(l);
     Node *n, *limit = gnodelast(h);
     for (n = gnode(h, 0); n < limit; n++) {
-      if (!ttisnil(gval(n)) && (iscleared(gkey(n)))) {
+      if (!ttisnil(gval(n)) && (iscleared(g, gkey(n)))) {
         setnilvalue(gval(n));  /* remove value ... */
         removeentry(n);  /* and remove entry from table */
       }
@@ -617,18 +642,18 @@ static void clearkeys (GCObject *l, GCObject *f) {
 ** clear entries with unmarked values from all weaktables in list 'l' up
 ** to element 'f'
 */
-static void clearvalues (GCObject *l, GCObject *f) {
+static void clearvalues (global_State *g, GCObject *l, GCObject *f) {
   for (; l != f; l = gco2t(l)->gclist) {
     Table *h = gco2t(l);
     Node *n, *limit = gnodelast(h);
     int i;
     for (i = 0; i < h->sizearray; i++) {
       TValue *o = &h->array[i];
-      if (iscleared(o))  /* value was collected? */
+      if (iscleared(g, o))  /* value was collected? */
         setnilvalue(o);  /* remove value */
     }
     for (n = gnode(h, 0); n < limit; n++) {
-      if (!ttisnil(gval(n)) && iscleared(gval(n))) {
+      if (!ttisnil(gval(n)) && iscleared(g, gval(n))) {
         setnilvalue(gval(n));  /* remove value ... */
         removeentry(n);  /* and remove entry from table */
       }
@@ -640,13 +665,22 @@ static void clearvalues (GCObject *l, GCObject *f) {
 static void freeobj (lua_State *L, GCObject *o) {
   switch (gch(o)->tt) {
     case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break;
-    case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break;
+    case LUA_TLCL: {
+      luaM_freemem(L, o, sizeLclosure(gco2lcl(o)->nupvalues));
+      break;
+    }
+    case LUA_TCCL: {
+      luaM_freemem(L, o, sizeCclosure(gco2ccl(o)->nupvalues));
+      break;
+    }
     case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break;
     case LUA_TTABLE: luaH_free(L, gco2t(o)); break;
     case LUA_TTHREAD: luaE_freethread(L, gco2th(o)); break;
     case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break;
-    case LUA_TSTRING: {
+    case LUA_TSHRSTR:
       G(L)->strt.nuse--;
+      /* go through */
+    case LUA_TLNGSTR: {
       luaM_freemem(L, o, sizestring(gco2ts(o)));
       break;
     }
@@ -689,7 +723,6 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
   int ow = otherwhite(g);
   int toclear, toset;  /* bits to clear and to set in all live objects */
   int tostop;  /* stop sweep when this is true */
-  l_mem debt = g->GCdebt;  /* current debt */
   if (isgenerational(g)) {  /* generational mode? */
     toclear = ~0;  /* clear nothing */
     toset = bitmask(OLDBIT);  /* set the old bit of all surviving objects */
@@ -708,19 +741,30 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
       freeobj(L, curr);  /* erase 'curr' */
     }
     else {
+      if (testbits(marked, tostop))
+        return NULL;  /* stop sweeping this list */
       if (gch(curr)->tt == LUA_TTHREAD)
         sweepthread(L, gco2th(curr));  /* sweep thread's upvalues */
-      if (testbits(marked, tostop)) {
-        static GCObject *nullp = NULL;
-        p = &nullp;  /* stop sweeping this list */
-        break;
-      }
       /* update marks */
       gch(curr)->marked = cast_byte((marked & toclear) | toset);
       p = &gch(curr)->next;  /* go to next element */
     }
   }
-  luaE_setdebt(g, debt);  /* sweeping should not change debt */
+  return (*p == NULL) ? NULL : p;
+}
+
+
+/*
+** sweep a list until a live object (or end of list)
+*/
+static GCObject **sweeptolive (lua_State *L, GCObject **p, int *n) {
+  GCObject ** old = p;
+  int i = 0;
+  do {
+    i++;
+    p = sweeplist(L, p, 1);
+  } while (p == old);
+  if (n) *n += i;
   return p;
 }
 
@@ -783,12 +827,14 @@ static void GCTM (lua_State *L, int propagateerrors) {
     L->allowhook = oldah;  /* restore hooks */
     g->gcrunning = running;  /* restore state */
     if (status != LUA_OK && propagateerrors) {  /* error while running __gc? */
-      if (status == LUA_ERRRUN) {  /* is there an error msg.? */
-        luaO_pushfstring(L, "error in __gc metamethod (%s)",
-                                        lua_tostring(L, -1));
+      if (status == LUA_ERRRUN) {  /* is there an error object? */
+        const char *msg = (ttisstring(L->top - 1))
+                            ? svalue(L->top - 1)
+                            : "no message";
+        luaO_pushfstring(L, "error in __gc metamethod (%s)", msg);
         status = LUA_ERRGCMM;  /* error in __gc metamethod */
       }
-      luaD_throw(L, status);  /* re-send error */
+      luaD_throw(L, status);  /* re-throw error */
     }
   }
 }
@@ -834,12 +880,21 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
     return;  /* nothing to be done */
   else {  /* move 'o' to 'finobj' list */
     GCObject **p;
-    for (p = &g->allgc; *p != o; p = &gch(*p)->next) ;
-    *p = gch(o)->next;  /* remove 'o' from root list */
-    gch(o)->next = g->finobj;  /* link it in list 'finobj' */
+    GCheader *ho = gch(o);
+    if (g->sweepgc == &ho->next) {  /* avoid removing current sweep object */
+      lua_assert(issweepphase(g));
+      g->sweepgc = sweeptolive(L, g->sweepgc, NULL);
+    }
+    /* search for pointer pointing to 'o' */
+    for (p = &g->allgc; *p != o; p = &gch(*p)->next) { /* empty */ }
+    *p = ho->next;  /* remove 'o' from root list */
+    ho->next = g->finobj;  /* link it in list 'finobj' */
     g->finobj = o;
-    l_setbit(gch(o)->marked, SEPARATED);  /* mark it as such */
-    resetoldbit(o);  /* see MOVE OLD rule */
+    l_setbit(ho->marked, SEPARATED);  /* mark it as such */
+    if (!keepinvariant(g))  /* not keeping invariant? */
+      makewhite(g, o);  /* "sweep" object */
+    else
+      resetoldbit(o);  /* see MOVE OLD rule */
   }
 }
 
@@ -856,6 +911,28 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
 #define sweepphases  \
        (bitmask(GCSsweepstring) | bitmask(GCSsweepudata) | bitmask(GCSsweep))
 
+
+/*
+** enter first sweep phase (strings) and prepare pointers for other
+** sweep phases.  The calls to 'sweeptolive' make pointers point to an
+** object inside the list (instead of to the header), so that the real
+** sweep do not need to skip objects created between "now" and the start
+** of the real sweep.
+** Returns how many objects it sweeped.
+*/
+static int entersweep (lua_State *L) {
+  global_State *g = G(L);
+  int n = 0;
+  g->gcstate = GCSsweepstring;
+  lua_assert(g->sweepgc == NULL && g->sweepfin == NULL);
+  /* prepare to sweep strings, finalizable objects, and regular objects */
+  g->sweepstrgc = 0;
+  g->sweepfin = sweeptolive(L, &g->finobj, &n);
+  g->sweepgc = sweeptolive(L, &g->allgc, &n);
+  return n;
+}
+
+
 /*
 ** change GC mode
 */
@@ -865,15 +942,14 @@ void luaC_changemode (lua_State *L, int mode) {
   if (mode == KGC_GEN) {  /* change to generational mode */
     /* make sure gray lists are consistent */
     luaC_runtilstate(L, bitmask(GCSpropagate));
-    g->lastmajormem = gettotalbytes(g);
+    g->GCestimate = gettotalbytes(g);
     g->gckind = KGC_GEN;
   }
   else {  /* change to incremental mode */
     /* sweep all objects to turn them back to white
        (as white has not changed, nothing extra will be collected) */
-    g->sweepstrgc = 0;
-    g->gcstate = GCSsweepstring;
     g->gckind = KGC_NORMAL;
+    entersweep(L);
     luaC_runtilstate(L, ~sweepphases);
   }
 }
@@ -907,8 +983,9 @@ void luaC_freeallobjects (lua_State *L) {
 }
 
 
-static void atomic (lua_State *L) {
+static l_mem atomic (lua_State *L) {
   global_State *g = G(L);
+  l_mem work = -g->GCmemtrav;  /* start counting work */
   GCObject *origweak, *origall;
   lua_assert(!iswhite(obj2gco(g->mainthread)));
   markobject(g, L);  /* mark running thread */
@@ -917,77 +994,87 @@ static void atomic (lua_State *L) {
   markmt(g);  /* mark basic metatables */
   /* remark occasional upvalues of (maybe) dead threads */
   remarkupvals(g);
+  propagateall(g);  /* propagate changes */
+  work += g->GCmemtrav;  /* stop counting (do not (re)count grays) */
   /* traverse objects caught by write barrier and by 'remarkupvals' */
   retraversegrays(g);
+  work -= g->GCmemtrav;  /* restart counting */
   convergeephemerons(g);
   /* at this point, all strongly accessible objects are marked. */
   /* clear values from weak tables, before checking finalizers */
-  clearvalues(g->weak, NULL);
-  clearvalues(g->allweak, NULL);
+  clearvalues(g, g->weak, NULL);
+  clearvalues(g, g->allweak, NULL);
   origweak = g->weak; origall = g->allweak;
+  work += g->GCmemtrav;  /* stop counting (objects being finalized) */
   separatetobefnz(L, 0);  /* separate objects to be finalized */
-  markbeingfnz(g);  /* mark userdata that will be finalized */
+  markbeingfnz(g);  /* mark objects that will be finalized */
   propagateall(g);  /* remark, to propagate `preserveness' */
+  work -= g->GCmemtrav;  /* restart counting */
   convergeephemerons(g);
   /* at this point, all resurrected objects are marked. */
   /* remove dead objects from weak tables */
-  clearkeys(g->ephemeron, NULL);  /* clear keys from all ephemeron tables */
-  clearkeys(g->allweak, NULL);  /* clear keys from all allweak tables */
+  clearkeys(g, g->ephemeron, NULL);  /* clear keys from all ephemeron tables */
+  clearkeys(g, g->allweak, NULL);  /* clear keys from all allweak tables */
   /* clear values from resurrected weak tables */
-  clearvalues(g->weak, origweak);
-  clearvalues(g->allweak, origall);
-  g->sweepstrgc = 0;  /* prepare to sweep strings */
-  g->gcstate = GCSsweepstring;
+  clearvalues(g, g->weak, origweak);
+  clearvalues(g, g->allweak, origall);
   g->currentwhite = cast_byte(otherwhite(g));  /* flip current white */
-  /*lua_checkmemory(L);*/
+  work += g->GCmemtrav;  /* complete counting */
+  return work;  /* estimate of memory marked by 'atomic' */
 }
 
 
-static l_mem singlestep (lua_State *L) {
+static lu_mem singlestep (lua_State *L) {
   global_State *g = G(L);
   switch (g->gcstate) {
     case GCSpause: {
+      g->GCmemtrav = 0;  /* start to count memory traversed */
       if (!isgenerational(g))
         markroot(g);  /* start a new collection */
-      /* in any case, root must be marked */
+      /* in any case, root must be marked at this point */
       lua_assert(!iswhite(obj2gco(g->mainthread))
               && !iswhite(gcvalue(&g->l_registry)));
       g->gcstate = GCSpropagate;
-      return GCROOTCOST;
+      return g->GCmemtrav;
     }
     case GCSpropagate: {
-      if (g->gray)
-        return propagatemark(g);
+      if (g->gray) {
+        lu_mem oldtrav = g->GCmemtrav;
+        propagatemark(g);
+        return g->GCmemtrav - oldtrav;  /* memory traversed in this step */
+      }
       else {  /* no more `gray' objects */
+        lu_mem work;
+        int sw;
         g->gcstate = GCSatomic;  /* finish mark phase */
-        atomic(L);
-        return GCATOMICCOST;
+        g->GCestimate = g->GCmemtrav;  /* save what was counted */;
+        work = atomic(L);  /* add what was traversed by 'atomic' */
+        g->GCestimate += work;  /* estimate of total memory traversed */ 
+        sw = entersweep(L);
+        return work + sw * GCSWEEPCOST;
       }
     }
     case GCSsweepstring: {
-      if (g->sweepstrgc < g->strt.size) {
-        sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]);
-        return GCSWEEPCOST;
-      }
-      else {  /* no more strings to sweep */
-        g->sweepgc = &g->finobj;  /* prepare to sweep finalizable objects */
+      int i;
+      for (i = 0; i < GCSWEEPMAX && g->sweepstrgc + i < g->strt.size; i++)
+        sweepwholelist(L, &g->strt.hash[g->sweepstrgc + i]);
+      g->sweepstrgc += i;
+      if (g->sweepstrgc >= g->strt.size)  /* no more strings to sweep? */
         g->gcstate = GCSsweepudata;
-        return 0;
-      }
+      return i * GCSWEEPCOST;
     }
     case GCSsweepudata: {
-      if (*g->sweepgc) {
-        g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX);
+      if (g->sweepfin) {
+        g->sweepfin = sweeplist(L, g->sweepfin, GCSWEEPMAX);
         return GCSWEEPMAX*GCSWEEPCOST;
       }
       else {
-        g->sweepgc = &g->allgc;  /* go to next phase */
         g->gcstate = GCSsweep;
-        return GCSWEEPCOST;
+        return 0;
       }
     }
     case GCSsweep: {
-      if (*g->sweepgc) {
+      if (g->sweepgc) {
         g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX);
         return GCSWEEPMAX*GCSWEEPCOST;
       }
@@ -1018,43 +1105,52 @@ void luaC_runtilstate (lua_State *L, int statesmask) {
 
 static void generationalcollection (lua_State *L) {
   global_State *g = G(L);
-  if (g->lastmajormem == 0) {  /* signal for another major collection? */
+  if (g->GCestimate == 0) {  /* signal for another major collection? */
     luaC_fullgc(L, 0);  /* perform a full regular collection */
-    g->lastmajormem = gettotalbytes(g);  /* update control */
+    g->GCestimate = gettotalbytes(g);  /* update control */
   }
   else {
+    lu_mem estimate = g->GCestimate;
     luaC_runtilstate(L, ~bitmask(GCSpause));  /* run complete cycle */
     luaC_runtilstate(L, bitmask(GCSpause));
-    if (gettotalbytes(g) > g->lastmajormem/100 * g->gcmajorinc)
-      g->lastmajormem = 0;  /* signal for a major collection */
+    if (gettotalbytes(g) > (estimate / 100) * g->gcmajorinc)
+      g->GCestimate = 0;  /* signal for a major collection */
   }
   luaE_setdebt(g, stddebt(g));
 }
 
 
-static void step (lua_State *L) {
+static void incstep (lua_State *L) {
   global_State *g = G(L);
-  l_mem lim = g->gcstepmul;  /* how much to work */
+  l_mem debt = g->GCdebt;
+  int stepmul = g->gcstepmul;
+  if (stepmul < 40) stepmul = 40;  /* avoid ridiculous low values */
+  /* convert debt from Kb to 'work units' (avoid zero debt and overflows) */
+  debt = (debt / STEPMULADJ) + 1;
+  debt = (debt < MAX_LMEM / stepmul) ? debt * stepmul : MAX_LMEM;
   do {  /* always perform at least one single step */
-    lim -= singlestep(L);
-  } while (lim > 0 && g->gcstate != GCSpause);
-  if (g->gcstate != GCSpause)
-    luaE_setdebt(g, g->GCdebt - GCSTEPSIZE);
+    lu_mem work = singlestep(L);  /* do some work */
+    debt -= work;
+  } while (debt > -GCSTEPSIZE && g->gcstate != GCSpause);
+  if (g->gcstate == GCSpause)
+    debt = stddebtest(g, g->GCestimate);  /* pause until next cycle */
   else
-    luaE_setdebt(g, stddebt(g));
+    debt = (debt / stepmul) * STEPMULADJ;  /* convert 'work units' to Kb */
+  luaE_setdebt(g, debt);
 }
 
 
 /*
-** performs a basic GC step even if the collector is stopped
+** performs a basic GC step
 */
 void luaC_forcestep (lua_State *L) {
   global_State *g = G(L);
   int i;
   if (isgenerational(g)) generationalcollection(L);
-  else step(L);
-  for (i = 0; i < GCFINALIZENUM && g->tobefnz; i++)
-    GCTM(L, 1);  /* Call a few pending finalizers */
+  else incstep(L);
+  /* run a few finalizers (or all of them at the end of a collect cycle) */
+  for (i = 0; g->tobefnz && (i < GCFINALIZENUM || g->gcstate == GCSpause); i++)
+    GCTM(L, 1);  /* call one finalizer */
 }
 
 
@@ -1062,10 +1158,13 @@ void luaC_forcestep (lua_State *L) {
 ** performs a basic GC step only if collector is running
 */
 void luaC_step (lua_State *L) {
-  if (G(L)->gcrunning) luaC_forcestep(L);
+  global_State *g = G(L);
+  if (g->gcrunning) luaC_forcestep(L);
+  else luaE_setdebt(g, -GCSTEPSIZE);  /* avoid being called too often */
 }
 
 
+
 /*
 ** performs a full GC cycle; if "isemergency", does not call
 ** finalizers (which could change stack positions)
@@ -1073,16 +1172,19 @@ void luaC_step (lua_State *L) {
 void luaC_fullgc (lua_State *L, int isemergency) {
   global_State *g = G(L);
   int origkind = g->gckind;
+  int someblack = keepinvariant(g);
   lua_assert(origkind != KGC_EMERGENCY);
-  if (!isemergency)   /* do not run finalizers during emergency GC */
+  if (isemergency)  /* do not run finalizers during emergency GC */
+    g->gckind = KGC_EMERGENCY;
+  else {
+    g->gckind = KGC_NORMAL;
     callallpendingfinalizers(L, 1);
-  if (keepinvariant(g)) {  /* marking phase? */
+  }
+  if (someblack) {  /* may there be some black objects? */
     /* must sweep all objects to turn them back to white
        (as white has not changed, nothing will be collected) */
-    g->sweepstrgc = 0;
-    g->gcstate = GCSsweepstring;
+    entersweep(L);
   }
-  g->gckind = isemergency ? KGC_EMERGENCY : KGC_NORMAL;
   /* finish any pending sweep phase to start a new cycle */
   luaC_runtilstate(L, bitmask(GCSpause));
   /* run entire collector */
index aa5dfce..bdd5cce 100644 (file)
--- a/src/lgc.h
+++ b/src/lgc.h
@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.h,v 2.52 2011/10/03 17:54:25 roberto Exp $
+** $Id: lgc.h,v 2.56 2012/05/23 15:43:14 roberto Exp $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
 */
 
 
+
+/* how much to allocate before next GC step */
+#if !defined(GCSTEPSIZE)
+/* ~100 small strings */
+#define GCSTEPSIZE     (cast_int(100 * sizeof(TString)))
+#endif
+
+
 /*
 ** Possible states of the Garbage Collector
 */
index 74deebb..c4d8c65 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: llex.c,v 2.59 2011/11/30 12:43:51 roberto Exp $
+** $Id: llex.c,v 2.61 2012/01/23 23:05:51 roberto Exp $
 ** Lexical Analyzer
 ** See Copyright Notice in lua.h
 */
@@ -67,7 +67,7 @@ void luaX_init (lua_State *L) {
   for (i=0; i<NUM_RESERVED; i++) {
     TString *ts = luaS_new(L, luaX_tokens[i]);
     luaS_fix(ts);  /* reserved words are never collected */
-    ts->tsv.reserved = cast_byte(i+1);  /* reserved word */
+    ts->tsv.extra = cast_byte(i+1);  /* reserved word */
   }
 }
 
@@ -222,13 +222,24 @@ static void trydecpoint (LexState *ls, SemInfo *seminfo) {
 
 
 /* LUA_NUMBER */
+/*
+** this function is quite liberal in what it accepts, as 'luaO_str2d'
+** will reject ill-formed numerals.
+*/
 static void read_numeral (LexState *ls, SemInfo *seminfo) {
+  const char *expo = "Ee";
+  int first = ls->current;
   lua_assert(lisdigit(ls->current));
-  do {
-    save_and_next(ls);
-    if (check_next(ls, "EePp"))  /* exponent part? */
+  save_and_next(ls);
+  if (first == '0' && check_next(ls, "Xx"))  /* hexadecimal? */
+    expo = "Pp";
+  for (;;) {
+    if (check_next(ls, expo))  /* exponent part? */
       check_next(ls, "+-");  /* optional exponent sign */
-  } while (lislalnum(ls->current) || ls->current == '.');
+    if (lisxdigit(ls->current) || ls->current == '.')
+      save_and_next(ls);
+    else  break;
+  }
   save(ls, '\0');
   buffreplace(ls, '.', ls->decpoint);  /* follow locale for decimal point */
   if (!buff2d(ls->buff, &seminfo->r))  /* format error? */
@@ -480,8 +491,8 @@ static int llex (LexState *ls, SemInfo *seminfo) {
           ts = luaX_newstring(ls, luaZ_buffer(ls->buff),
                                   luaZ_bufflen(ls->buff));
           seminfo->ts = ts;
-          if (ts->tsv.reserved > 0)  /* reserved word? */
-            return ts->tsv.reserved - 1 + FIRST_RESERVED;
+          if (isreserved(ts))  /* reserved word? */
+            return ts->tsv.extra - 1 + FIRST_RESERVED;
           else {
             return TK_NAME;
           }
index 48dc81f..fc9de1a 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: llimits.h,v 1.95 2011/12/06 16:58:36 roberto Exp $
+** $Id: llimits.h,v 1.99 2012/05/28 20:32:28 roberto Exp $
 ** Limits, basic types, and some other `installation-dependent' definitions
 ** See Copyright Notice in lua.h
 */
@@ -31,6 +31,8 @@ typedef unsigned char lu_byte;
 
 #define MAX_LUMEM      ((lu_mem)(~(lu_mem)0)-2)
 
+#define MAX_LMEM       ((l_mem) ((MAX_LUMEM >> 1) - 2))
+
 
 #define MAX_INT (INT_MAX-2)  /* maximum value of an int (-2 for safety) */
 
@@ -209,31 +211,36 @@ typedef lu_int32 Instruction;
 
 #elif defined(LUA_IEEE754TRICK)                /* }{ */
 /* the next trick should work on any machine using IEEE754 with
-   a 32-bit integer type */
+   a 32-bit int type */
 
 union luai_Cast { double l_d; LUA_INT32 l_p[2]; };
 
 #if !defined(LUA_IEEEENDIAN)   /* { */
 #define LUAI_EXTRAIEEE \
   static const union luai_Cast ieeeendian = {-(33.0 + 6755399441055744.0)};
-#define LUA_IEEEENDIAN         (ieeeendian.l_p[1] == 33)
+#define LUA_IEEEENDIANLOC      (ieeeendian.l_p[1] == 33)
 #else
+#define LUA_IEEEENDIANLOC      LUA_IEEEENDIAN
 #define LUAI_EXTRAIEEE         /* empty */
 #endif                         /* } */
 
 #define lua_number2int32(i,n,t) \
   { LUAI_EXTRAIEEE \
     volatile union luai_Cast u; u.l_d = (n) + 6755399441055744.0; \
-    (i) = (t)u.l_p[LUA_IEEEENDIAN]; }
+    (i) = (t)u.l_p[LUA_IEEEENDIANLOC]; }
 
 #define luai_hashnum(i,n)  \
   { volatile union luai_Cast u; u.l_d = (n) + 1.0;  /* avoid -0 */ \
     (i) = u.l_p[0]; (i) += u.l_p[1]; }  /* add double bits for his hash */
 
 #define lua_number2int(i,n)            lua_number2int32(i, n, int)
-#define lua_number2integer(i,n)                lua_number2int32(i, n, lua_Integer)
 #define lua_number2unsigned(i,n)       lua_number2int32(i, n, lua_Unsigned)
 
+/* the trick can be expanded to lua_Integer when it is a 32-bit value */
+#if defined(LUA_IEEELL)
+#define lua_number2integer(i,n)                lua_number2int32(i, n, lua_Integer)
+#endif
+
 #endif                         /* } */
 
 
index b17237f..c3c605e 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lmathlib.c,v 1.80 2011/07/05 12:49:35 roberto Exp $
+** $Id: lmathlib.c,v 1.81 2012/05/18 17:47:53 roberto Exp $
 ** Standard mathematical library
 ** See Copyright Notice in lua.h
 */
 #include "lualib.h"
 
 
-#undef PI
-#define PI (3.14159265358979323846)
-#define RADIANS_PER_DEGREE (PI/180.0)
-
-
 /* macro 'l_tg' allows the addition of an 'l' or 'f' to all math operations */
 #if !defined(l_tg)
 #define l_tg(x)                (x)
 #endif
 
 
+#undef PI
+#define PI (l_tg(3.1415926535897932384626433832795))
+#define RADIANS_PER_DEGREE (PI/180.0)
+
+
 
 static int math_abs (lua_State *L) {
   lua_pushnumber(L, l_tg(fabs)(luaL_checknumber(L, 1)));
index 792deb3..3f88496 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lmem.c,v 1.83 2011/11/30 12:42:49 roberto Exp $
+** $Id: lmem.c,v 1.84 2012/05/23 15:41:53 roberto Exp $
 ** Interface to Memory Manager
 ** See Copyright Notice in lua.h
 */
@@ -94,22 +94,6 @@ void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) {
   }
   lua_assert((nsize == 0) == (newblock == NULL));
   g->GCdebt = (g->GCdebt + nsize) - realosize;
-#if defined(TRACEMEM)
-  { /* auxiliary patch to monitor garbage collection.
-    ** To plot, gnuplot with following command:
-    ** plot TRACEMEM using 1:2 with lines, TRACEMEM using 1:3 with lines
-    */
-    static unsigned long total = 0;  /* our "time" */
-    static FILE *f = NULL;  /* output file */
-    total++;  /* "time" always grows */
-    if ((total % 200) == 0) {
-      if (f == NULL) f = fopen(TRACEMEM, "w");
-      fprintf(f, "%lu %u %d %d\n", total,
-              gettotalbytes(g), g->GCdebt, g->gcstate * 10000);
-    }
-  }
-#endif
-
   return newblock;
 }
 
index 783bc12..a995927 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: loadlib.c,v 1.108 2011/12/12 16:34:03 roberto Exp $
+** $Id: loadlib.c,v 1.111 2012/05/30 12:33:44 roberto Exp $
 ** Dynamic library loader for Lua
 ** See Copyright Notice in lua.h
 **
@@ -92,9 +92,9 @@
 #define LUA_OFSEP      "_"
 
 
-#define LIBPREFIX      "LOADLIB: "
+/* table (in the registry) that keeps handles for all loaded C libraries */
+#define CLIBS          "_CLIBS"
 
-#define POF            LUA_POF
 #define LIB_FAIL       "open"
 
 
@@ -248,48 +248,54 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
 #endif
 
 
-
-static void **ll_register (lua_State *L, const char *path) {
-  void **plib;
-  lua_pushfstring(L, "%s%s", LIBPREFIX, path);
-  lua_gettable(L, LUA_REGISTRYINDEX);  /* check library in registry? */
-  if (!lua_isnil(L, -1))  /* is there an entry? */
-    plib = (void **)lua_touserdata(L, -1);
-  else {  /* no entry yet; create one */
-    lua_pop(L, 1);  /* remove result from gettable */
-    plib = (void **)lua_newuserdata(L, sizeof(const void *));
-    *plib = NULL;
-    luaL_setmetatable(L, "_LOADLIB");
-    lua_pushfstring(L, "%s%s", LIBPREFIX, path);
-    lua_pushvalue(L, -2);
-    lua_settable(L, LUA_REGISTRYINDEX);
-  }
+static void *ll_checkclib (lua_State *L, const char *path) {
+  void *plib;
+  lua_getfield(L, LUA_REGISTRYINDEX, CLIBS);
+  lua_getfield(L, -1, path);
+  plib = lua_touserdata(L, -1);  /* plib = CLIBS[path] */
+  lua_pop(L, 2);  /* pop CLIBS table and 'plib' */
   return plib;
 }
 
 
+static void ll_addtoclib (lua_State *L, const char *path, void *plib) {
+  lua_getfield(L, LUA_REGISTRYINDEX, CLIBS);
+  lua_pushlightuserdata(L, plib);
+  lua_pushvalue(L, -1);
+  lua_setfield(L, -3, path);  /* CLIBS[path] = plib */
+  lua_rawseti(L, -2, luaL_len(L, -2) + 1);  /* CLIBS[#CLIBS + 1] = plib */
+  lua_pop(L, 1);  /* pop CLIBS table */
+}
+
+
 /*
-** __gc tag method: calls library's `ll_unloadlib' function with the lib
-** handle
+** __gc tag method for CLIBS table: calls 'll_unloadlib' for all lib
+** handles in list CLIBS
 */
 static int gctm (lua_State *L) {
-  void **lib = (void **)luaL_checkudata(L, 1, "_LOADLIB");
-  if (*lib) ll_unloadlib(*lib);
-  *lib = NULL;  /* mark library as closed */
+  int 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));
+    lua_pop(L, 1);  /* pop handle */
+  }
   return 0;
 }
 
 
 static int ll_loadfunc (lua_State *L, const char *path, const char *sym) {
-  void **reg = ll_register(L, path);
-  if (*reg == NULL) *reg = ll_load(L, path, *sym == '*');
-  if (*reg == NULL) return ERRLIB;  /* unable to load library */
+  void *reg = ll_checkclib(L, path);  /* check loaded C libraries */
+  if (reg == NULL) {  /* must load library? */
+    reg = ll_load(L, path, *sym == '*');
+    if (reg == NULL) return ERRLIB;  /* unable to load library */
+    ll_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 = ll_sym(L, reg, sym);
     if (f == NULL)
       return ERRFUNC;  /* unable to find function */
     lua_pushcfunction(L, f);  /* else create new function */
@@ -418,12 +424,12 @@ static int loadfunc (lua_State *L, const char *filename, const char *modname) {
   if (mark) {
     int stat;
     funcname = lua_pushlstring(L, modname, mark - modname);
-    funcname = lua_pushfstring(L, POF"%s", funcname);
+    funcname = lua_pushfstring(L, LUA_POF"%s", funcname);
     stat = ll_loadfunc(L, filename, funcname);
     if (stat != ERRFUNC) return stat;
     modname = mark + 1;  /* else go ahead and try old-style name */
   }
-  funcname = lua_pushfstring(L, POF"%s", modname);
+  funcname = lua_pushfstring(L, LUA_POF"%s", modname);
   return ll_loadfunc(L, filename, funcname);
 }
 
@@ -476,9 +482,9 @@ static void findloader (lua_State *L, const char *name) {
   lua_getfield(L, lua_upvalueindex(1), "searchers");  /* will be at index 3 */
   if (!lua_istable(L, 3))
     luaL_error(L, LUA_QL("package.searchers") " must be a table");
-  /*  iterate over available seachers to find a loader */
+  /*  iterate over available searchers to find a loader */
   for (i = 1; ; i++) {
-    lua_rawgeti(L, 3, i);  /* get a seacher */
+    lua_rawgeti(L, 3, i);  /* get a searcher */
     if (lua_isnil(L, -1)) {  /* no more searchers? */
       lua_pop(L, 1);  /* remove nil */
       luaL_pushresult(&msg);  /* create error message */
@@ -666,18 +672,10 @@ static const luaL_Reg ll_funcs[] = {
 };
 
 
-static const lua_CFunction searchers[] =
-  {searcher_preload, searcher_Lua, searcher_C, searcher_Croot, NULL};
-
-
-LUAMOD_API int luaopen_package (lua_State *L) {
+static void createsearcherstable (lua_State *L) {
+  static const lua_CFunction searchers[] =
+    {searcher_preload, searcher_Lua, searcher_C, searcher_Croot, NULL};
   int i;
-  /* create new type _LOADLIB */
-  luaL_newmetatable(L, "_LOADLIB");
-  lua_pushcfunction(L, gctm);
-  lua_setfield(L, -2, "__gc");
-  /* create `package' table */
-  luaL_newlib(L, pk_funcs);
   /* create 'searchers' table */
   lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0);
   /* fill it with pre-defined searchers */
@@ -686,6 +684,19 @@ LUAMOD_API int luaopen_package (lua_State *L) {
     lua_pushcclosure(L, searchers[i], 1);
     lua_rawseti(L, -2, i+1);
   }
+}
+
+
+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 */
+  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);
+  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' */
index 06246bf..ca75a02 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lobject.h,v 2.64 2011/10/31 17:48:22 roberto Exp $
+** $Id: lobject.h,v 2.70 2012/05/11 14:10:50 roberto Exp $
 ** Type definitions for Lua objects
 ** See Copyright Notice in lua.h
 */
@@ -36,6 +36,9 @@
 ** bit 6: whether value is collectable
 */
 
+#define VARBITS                (3 << 4)
+
+
 /*
 ** LUA_TFUNCTION variants:
 ** 0 - Lua function
 #define LUA_TCCL       (LUA_TFUNCTION | (2 << 4))  /* C closure */
 
 
+/*
+** LUA_TSTRING variants */
+#define LUA_TSHRSTR    (LUA_TSTRING | (0 << 4))  /* short strings */
+#define LUA_TLNGSTR    (LUA_TSTRING | (1 << 4))  /* long strings */
+
+
 /* Bit mark for collectable types */
 #define BIT_ISCOLLECTABLE      (1 << 6)
 
@@ -109,23 +118,28 @@ typedef struct lua_TValue TValue;
 /* raw type tag of a TValue */
 #define rttype(o)      ((o)->tt_)
 
+/* tag with no variants (bits 0-3) */
+#define novariant(x)   ((x) & 0x0F)
+
 /* type tag of a TValue (bits 0-3 for tags + variant bits 4-5) */
 #define ttype(o)       (rttype(o) & 0x3F)
 
-
 /* type tag of a TValue with no variants (bits 0-3) */
-#define ttypenv(o)     (rttype(o) & 0x0F)
+#define ttypenv(o)     (novariant(rttype(o)))
 
 
 /* Macros to test type */
 #define checktag(o,t)          (rttype(o) == (t))
+#define checktype(o,t)         (ttypenv(o) == (t))
 #define ttisnumber(o)          checktag((o), LUA_TNUMBER)
 #define ttisnil(o)             checktag((o), LUA_TNIL)
 #define ttisboolean(o)         checktag((o), LUA_TBOOLEAN)
 #define ttislightuserdata(o)   checktag((o), LUA_TLIGHTUSERDATA)
-#define ttisstring(o)          checktag((o), ctb(LUA_TSTRING))
+#define ttisstring(o)          checktype((o), LUA_TSTRING)
+#define ttisshrstring(o)       checktag((o), ctb(LUA_TSHRSTR))
+#define ttislngstring(o)       checktag((o), ctb(LUA_TLNGSTR))
 #define ttistable(o)           checktag((o), ctb(LUA_TTABLE))
-#define ttisfunction(o)                (ttypenv(o) == LUA_TFUNCTION)
+#define ttisfunction(o)                checktype(o, LUA_TFUNCTION)
 #define ttisclosure(o)         ((rttype(o) & 0x1F) == LUA_TFUNCTION)
 #define ttisCclosure(o)                checktag((o), ctb(LUA_TCCL))
 #define ttisLclosure(o)                checktag((o), ctb(LUA_TLCL))
@@ -161,7 +175,7 @@ typedef struct lua_TValue TValue;
 
 
 /* Macros for internal tests */
-#define righttt(obj)           (ttypenv(obj) == gcvalue(obj)->gch.tt)
+#define righttt(obj)           (ttype(obj) == gcvalue(obj)->gch.tt)
 
 #define checkliveness(g,obj) \
        lua_longassert(!iscollectable(obj) || \
@@ -193,7 +207,8 @@ typedef struct lua_TValue TValue;
 
 #define setsvalue(L,obj,x) \
   { TValue *io=(obj); \
-    val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TSTRING)); \
+    TString *x_ = (x); \
+    val_(io).gc=cast(GCObject *, x_); settt_(io, ctb(x_->tsv.tt)); \
     checkliveness(G(L),io); }
 
 #define setuvalue(L,obj,x) \
@@ -221,11 +236,6 @@ typedef struct lua_TValue TValue;
     val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TTABLE)); \
     checkliveness(G(L),io); }
 
-#define setptvalue(L,obj,x) \
-  { TValue *io=(obj); \
-    val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TPROTO)); \
-    checkliveness(G(L),io); }
-
 #define setdeadvalue(obj)      settt_(obj, LUA_TDEADKEY)
 
 
@@ -256,6 +266,8 @@ typedef struct lua_TValue TValue;
 #define setsvalue2n    setsvalue
 
 
+/* check whether a number is valid (useful only for NaN trick) */
+#define luai_checknum(L,o,c)   { /* empty */ }
 
 
 /*
@@ -263,10 +275,7 @@ typedef struct lua_TValue TValue;
 ** NaN Trick
 ** =======================================================
 */
-
-#if defined(LUA_NANTRICK) \
- || defined(LUA_NANTRICK_LE) \
- || defined(LUA_NANTRICK_BE)
+#if defined(LUA_NANTRICK)
 
 /*
 ** numbers are represented in the 'd_' field. All other values have the
@@ -274,15 +283,23 @@ typedef struct lua_TValue TValue;
 ** a "signaled NaN", which is never generated by regular operations by
 ** the CPU (nor by 'strtod')
 */
-#if !defined(NNMARK)
+
+/* allows for external implementation for part of the trick */
+#if !defined(NNMARK)   /* { */
+
+
+#if !defined(LUA_IEEEENDIAN)
+#error option 'LUA_NANTRICK' needs 'LUA_IEEEENDIAN'
+#endif
+
+
 #define NNMARK         0x7FF7A500
 #define NNMASK         0x7FFFFF00
-#endif
 
 #undef TValuefields
 #undef NILCONSTANT
 
-#if defined(LUA_NANTRICK_LE)
+#if (LUA_IEEEENDIAN == 0)      /* { */
 
 /* little endian */
 #define TValuefields  \
@@ -293,7 +310,7 @@ typedef struct lua_TValue TValue;
 #define d_(o)          ((o)->u.d__)
 #define tt_(o)         ((o)->u.i.tt__)
 
-#elif defined(LUA_NANTRICK_BE)
+#else                          /* }{ */
 
 /* big endian */
 #define TValuefields  \
@@ -304,10 +321,9 @@ typedef struct lua_TValue TValue;
 #define d_(o)          ((o)->u.d__)
 #define tt_(o)         ((o)->u.i.tt__)
 
-#elif !defined(TValuefields)
-#error option 'LUA_NANTRICK' needs declaration for 'TValuefields'
+#endif                         /* } */
 
-#endif
+#endif                 /* } */
 
 
 /* correspondence with standard representation */
@@ -348,21 +364,18 @@ typedef struct lua_TValue TValue;
 */
 
 #undef checktag
+#undef checktype
 #define checktag(o,t)  (tt_(o) == tag2tt(t))
+#define checktype(o,t) (ctb(tt_(o) | VARBITS) == ctb(tag2tt(t) | VARBITS))
 
 #undef ttisequal
 #define ttisequal(o1,o2)  \
        (ttisnumber(o1) ? ttisnumber(o2) : (tt_(o1) == tt_(o2)))
 
 
-
+#undef luai_checknum
 #define luai_checknum(L,o,c)   { if (!ttisnumber(o)) c; }
 
-
-#else
-
-#define luai_checknum(L,o,c)   { /* empty */ }
-
 #endif
 /* }====================================================== */
 
@@ -401,7 +414,7 @@ typedef union TString {
   L_Umaxalign dummy;  /* ensures maximum alignment for strings */
   struct {
     CommonHeader;
-    lu_byte reserved;
+    lu_byte extra;  /* reserved words for short strings; "has hash" for longs */
     unsigned int hash;
     size_t len;  /* number of characters in string */
   } tsv;
@@ -501,7 +514,7 @@ typedef struct UpVal {
 */
 
 #define ClosureHeader \
-       CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist
+       CommonHeader; lu_byte nupvalues; GCObject *gclist
 
 typedef struct CClosure {
   ClosureHeader;
index 2e34676..ef73692 100644 (file)
@@ -1,5 +1,6 @@
 /*
-** $Id: lopcodes.c,v 1.48 2011/04/19 16:22:13 roberto Exp $
+** $Id: lopcodes.c,v 1.49 2012/05/14 13:34:18 roberto Exp $
+** Opcodes for Lua virtual machine
 ** See Copyright Notice in lua.h
 */
 
index 881667d..489755b 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: loslib.c,v 1.38 2011/11/30 12:35:05 roberto Exp $
+** $Id: loslib.c,v 1.39 2012/05/23 15:37:09 roberto Exp $
 ** Standard Operating System library
 ** See Copyright Notice in lua.h
 */
 #if !defined(LUA_STRFTIMEOPTIONS)
 
 #if !defined(LUA_USE_POSIX)
-#define LUA_STRFTIMEOPTIONS     { "aAbBcdHIjmMpSUwWxXyYz%", "" }
+#define LUA_STRFTIMEOPTIONS    { "aAbBcdHIjmMpSUwWxXyYz%", "" }
 #else
-#define LUA_STRFTIMEOPTIONS     { "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%", "", \
-                                "E", "cCxXyY",  \
-                                "O", "deHImMSuUVwWy" }
+#define LUA_STRFTIMEOPTIONS \
+       { "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%", "" \
+         "", "E", "cCxXyY",  \
+         "O", "deHImMSuUVwWy" }
 #endif
 
 #endif
@@ -43,7 +44,7 @@
 */
 #if defined(LUA_USE_MKSTEMP)
 #include <unistd.h>
-#define LUA_TMPNAMBUFSIZE       32
+#define LUA_TMPNAMBUFSIZE      32
 #define lua_tmpnam(b,e) { \
         strcpy(b, "/tmp/lua_XXXXXX"); \
         e = mkstemp(b); \
@@ -52,8 +53,8 @@
 
 #elif !defined(lua_tmpnam)
 
-#define LUA_TMPNAMBUFSIZE       L_tmpnam
-#define lua_tmpnam(b,e)         { e = (tmpnam(b) == NULL); }
+#define LUA_TMPNAMBUFSIZE      L_tmpnam
+#define lua_tmpnam(b,e)                { e = (tmpnam(b) == NULL); }
 
 #endif
 
index 4d68936..b3eb3ca 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.c,v 2.124 2011/12/02 13:23:56 roberto Exp $
+** $Id: lparser.c,v 2.128 2012/05/20 14:51:23 roberto Exp $
 ** Lua Parser
 ** See Copyright Notice in lua.h
 */
@@ -222,7 +222,7 @@ static int searchupvalue (FuncState *fs, TString *name) {
   int i;
   Upvaldesc *up = fs->f->upvalues;
   for (i = 0; i < fs->nups; i++) {
-    if (eqstr(up[i].name, name)) return i;
+    if (luaS_eqstr(up[i].name, name)) return i;
   }
   return -1;  /* not found */
 }
@@ -246,7 +246,7 @@ static int newupvalue (FuncState *fs, TString *name, expdesc *v) {
 static int searchvar (FuncState *fs, TString *n) {
   int i;
   for (i=fs->nactvar-1; i >= 0; i--) {
-    if (eqstr(n, getlocvar(fs, i)->varname))
+    if (luaS_eqstr(n, getlocvar(fs, i)->varname))
       return i;
   }
   return -1;  /* not found */
@@ -342,7 +342,7 @@ static void closegoto (LexState *ls, int g, Labeldesc *label) {
   FuncState *fs = ls->fs;
   Labellist *gl = &ls->dyd->gt;
   Labeldesc *gt = &gl->arr[g];
-  lua_assert(eqstr(gt->name, label->name));
+  lua_assert(luaS_eqstr(gt->name, label->name));
   if (gt->nactvar < label->nactvar) {
     TString *vname = getlocvar(fs, gt->nactvar)->varname;
     const char *msg = luaO_pushfstring(ls->L,
@@ -369,7 +369,7 @@ static int findlabel (LexState *ls, int g) {
   /* check labels in current block for a match */
   for (i = bl->firstlabel; i < dyd->label.n; i++) {
     Labeldesc *lb = &dyd->label.arr[i];
-    if (eqstr(lb->name, gt->name)) {  /* correct label? */
+    if (luaS_eqstr(lb->name, gt->name)) {  /* correct label? */
       if (gt->nactvar > lb->nactvar &&
           (bl->upval || dyd->label.n > bl->firstlabel))
         luaK_patchclose(ls->fs, gt->pc, lb->nactvar);
@@ -403,7 +403,7 @@ static void findgotos (LexState *ls, Labeldesc *lb) {
   Labellist *gl = &ls->dyd->gt;
   int i = ls->fs->bl->firstgoto;
   while (i < gl->n) {
-    if (eqstr(gl->arr[i].name, lb->name))
+    if (luaS_eqstr(gl->arr[i].name, lb->name))
       closegoto(ls, i, lb);
     else
       i++;
@@ -461,7 +461,7 @@ static void breaklabel (LexState *ls) {
 ** message when label name is a reserved word (which can only be 'break')
 */
 static l_noret undefgoto (LexState *ls, Labeldesc *gt) {
-  const char *msg = (gt->name->tsv.reserved > 0)
+  const char *msg = isreserved(gt->name)
                     ? "<%s> at line %d not inside a loop"
                     : "no visible label " LUA_QS " for <goto> at line %d";
   msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line);
@@ -493,21 +493,30 @@ static void leaveblock (FuncState *fs) {
 
 
 /*
-** adds prototype being created into its parent list of prototypes
-** and codes instruction to create new closure
+** adds a new prototype into list of prototypes
 */
-static void codeclosure (LexState *ls, Proto *clp, expdesc *v) {
-  FuncState *fs = ls->fs->prev;
-  Proto *f = fs->f;  /* prototype of function creating new closure */
+static Proto *addprototype (LexState *ls) {
+  Proto *clp;
+  lua_State *L = ls->L;
+  FuncState *fs = ls->fs;
+  Proto *f = fs->f;  /* prototype of current function */
   if (fs->np >= f->sizep) {
     int oldsize = f->sizep;
-    luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *,
-                    MAXARG_Bx, "functions");
+    luaM_growvector(L, f->p, fs->np, f->sizep, Proto *, MAXARG_Bx, "functions");
     while (oldsize < f->sizep) f->p[oldsize++] = NULL;
   }
-  f->p[fs->np++] = clp;
-  luaC_objbarrier(ls->L, f, clp);
-  init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1));
+  f->p[fs->np++] = clp = luaF_newproto(L);
+  luaC_objbarrier(L, f, clp);
+  return clp;
+}
+
+
+/*
+** codes instruction to create new closure in parent function
+*/
+static void codeclosure (LexState *ls, expdesc *v) {
+  FuncState *fs = ls->fs->prev;
+  init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np - 1));
   luaK_exp2nextreg(fs, v);  /* fix it at stack top (for GC) */
 }
 
@@ -529,13 +538,9 @@ static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) {
   fs->nactvar = 0;
   fs->firstlocal = ls->dyd->actvar.n;
   fs->bl = NULL;
-  f = luaF_newproto(L);
-  fs->f = f;
+  f = fs->f;
   f->source = ls->source;
   f->maxstacksize = 2;  /* registers 0/1 are always valid */
-  /* anchor prototype (to avoid being collected) */
-  setptvalue2s(L, L->top, f);
-  incr_top(L);
   fs->h = luaH_new(L);
   /* anchor table of constants (to avoid being collected) */
   sethvalue2s(L, L->top, fs->h);
@@ -568,20 +573,6 @@ static void close_func (LexState *ls) {
   anchor_token(ls);
   L->top--;  /* pop table of constants */
   luaC_checkGC(L);
-  L->top--;  /* pop prototype (after possible collection) */
-}
-
-
-/*
-** opens the main function, which is a regular vararg function with an
-** upvalue named LUA_ENV
-*/
-static void open_mainfunc (LexState *ls, FuncState *fs, BlockCnt *bl) {
-  expdesc v;
-  open_func(ls, fs, bl);
-  fs->f->is_vararg = 1;  /* main function is always vararg */
-  init_exp(&v, VLOCAL, 0);
-  newupvalue(fs, ls->envn, &v);  /* create environment upvalue */
 }
 
 
@@ -795,8 +786,9 @@ static void body (LexState *ls, expdesc *e, int ismethod, int line) {
   /* body ->  `(' parlist `)' block END */
   FuncState new_fs;
   BlockCnt bl;
-  open_func(ls, &new_fs, &bl);
+  new_fs.f = addprototype(ls);
   new_fs.f->linedefined = line;
+  open_func(ls, &new_fs, &bl);
   checknext(ls, '(');
   if (ismethod) {
     new_localvarliteral(ls, "self");  /* create 'self' parameter */
@@ -807,7 +799,7 @@ static void body (LexState *ls, expdesc *e, int ismethod, int line) {
   statlist(ls);
   new_fs.f->lastlinedefined = ls->linenumber;
   check_match(ls, TK_END, TK_FUNCTION, line);
-  codeclosure(ls, new_fs.f, e);
+  codeclosure(ls, e);
   close_func(ls);
 }
 
@@ -879,8 +871,8 @@ static void funcargs (LexState *ls, expdesc *f, int line) {
 */
 
 
-static void prefixexp (LexState *ls, expdesc *v) {
-  /* prefixexp -> NAME | '(' expr ')' */
+static void primaryexp (LexState *ls, expdesc *v) {
+  /* primaryexp -> NAME | '(' expr ')' */
   switch (ls->t.token) {
     case '(': {
       int line = ls->linenumber;
@@ -901,12 +893,12 @@ static void prefixexp (LexState *ls, expdesc *v) {
 }
 
 
-static void primaryexp (LexState *ls, expdesc *v) {
-  /* primaryexp ->
-        prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */
+static void suffixedexp (LexState *ls, expdesc *v) {
+  /* suffixedexp ->
+       primaryexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs } */
   FuncState *fs = ls->fs;
   int line = ls->linenumber;
-  prefixexp(ls, v);
+  primaryexp(ls, v);
   for (;;) {
     switch (ls->t.token) {
       case '.': {  /* fieldsel */
@@ -941,7 +933,7 @@ static void primaryexp (LexState *ls, expdesc *v) {
 
 static void simpleexp (LexState *ls, expdesc *v) {
   /* simpleexp -> NUMBER | STRING | NIL | TRUE | FALSE | ... |
-                  constructor | FUNCTION body | primaryexp */
+                  constructor | FUNCTION body | suffixedexp */
   switch (ls->t.token) {
     case TK_NUMBER: {
       init_exp(v, VKNUM, 0);
@@ -981,7 +973,7 @@ static void simpleexp (LexState *ls, expdesc *v) {
       return;
     }
     default: {
-      primaryexp(ls, v);
+      suffixedexp(ls, v);
       return;
     }
   }
@@ -1141,10 +1133,10 @@ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) {
 static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {
   expdesc e;
   check_condition(ls, vkisvar(lh->v.k), "syntax error");
-  if (testnext(ls, ',')) {  /* assignment -> `,' primaryexp assignment */
+  if (testnext(ls, ',')) {  /* assignment -> ',' suffixedexp assignment */
     struct LHS_assign nv;
     nv.prev = lh;
-    primaryexp(ls, &nv.v);
+    suffixedexp(ls, &nv.v);
     if (nv.v.k != VINDEXED)
       check_conflict(ls, lh, &nv.v);
     checklimit(ls->fs, nvars + ls->L->nCcalls, LUAI_MAXCCALLS,
@@ -1200,7 +1192,7 @@ static void gotostat (LexState *ls, int pc) {
 static void checkrepeated (FuncState *fs, Labellist *ll, TString *label) {
   int i;
   for (i = fs->bl->firstlabel; i < ll->n; i++) {
-    if (eqstr(label, ll->arr[i].name)) {
+    if (luaS_eqstr(label, ll->arr[i].name)) {
       const char *msg = luaO_pushfstring(fs->ls->L,
                           "label " LUA_QS " already defined on line %d",
                           getstr(label), ll->arr[i].line);
@@ -1210,6 +1202,13 @@ static void checkrepeated (FuncState *fs, Labellist *ll, TString *label) {
 }
 
 
+/* skip no-op statements */
+static void skipnoopstat (LexState *ls) {
+  while (ls->t.token == ';' || ls->t.token == TK_DBCOLON)
+    statement(ls);
+}
+
+
 static void labelstat (LexState *ls, TString *label, int line) {
   /* label -> '::' NAME '::' */
   FuncState *fs = ls->fs;
@@ -1219,9 +1218,7 @@ static void labelstat (LexState *ls, TString *label, int line) {
   checknext(ls, TK_DBCOLON);  /* skip double colon */
   /* create new entry for this label */
   l = newlabelentry(ls, ll, label, line, fs->pc);
-  /* skip other no-op statements */
-  while (ls->t.token == ';' || ls->t.token == TK_DBCOLON)
-    statement(ls);
+  skipnoopstat(ls);  /* skip other no-op statements */
   if (block_follow(ls, 0)) {  /* label is last no-op statement in the block? */
     /* assume that locals are already out of scope */
     ll->arr[l].nactvar = fs->bl->nactvar;
@@ -1384,6 +1381,7 @@ static void test_then_block (LexState *ls, int *escapelist) {
     luaK_goiffalse(ls->fs, &v);  /* will jump to label if condition is true */
     enterblock(fs, &bl, 0);  /* must enter block before 'goto' */
     gotostat(ls, v.t);  /* handle goto/break */
+    skipnoopstat(ls);  /* skip other no-op statements */
     if (block_follow(ls, 0)) {  /* 'goto' is the entire block? */
       leaveblock(fs);
       return;  /* and that is it */
@@ -1480,13 +1478,15 @@ static void exprstat (LexState *ls) {
   /* stat -> func | assignment */
   FuncState *fs = ls->fs;
   struct LHS_assign v;
-  primaryexp(ls, &v.v);
-  if (v.v.k == VCALL)  /* stat -> func */
-    SETARG_C(getcode(fs, &v.v), 1);  /* call statement uses no results */
-  else {  /* stat -> assignment */
+  suffixedexp(ls, &v.v);
+  if (ls->t.token == '=' || ls->t.token == ',') { /* stat -> assignment ? */
     v.prev = NULL;
     assignment(ls, &v, 1);
   }
+  else {  /* stat -> func */
+    check_condition(ls, v.v.k == VCALL, "syntax error");
+    SETARG_C(getcode(fs, &v.v), 1);  /* call statement uses no results */
+  }
 }
 
 
@@ -1594,27 +1594,42 @@ static void statement (LexState *ls) {
 /* }====================================================================== */
 
 
-Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
-                    Dyndata *dyd, const char *name, int firstchar) {
+/*
+** compiles the main function, which is a regular vararg function with an
+** upvalue named LUA_ENV
+*/
+static void mainfunc (LexState *ls, FuncState *fs) {
+  BlockCnt bl;
+  expdesc v;
+  open_func(ls, fs, &bl);
+  fs->f->is_vararg = 1;  /* main function is always vararg */
+  init_exp(&v, VLOCAL, 0);  /* create and... */
+  newupvalue(fs, ls->envn, &v);  /* ...set environment upvalue */
+  luaX_next(ls);  /* read first token */
+  statlist(ls);  /* parse main body */
+  check(ls, TK_EOS);
+  close_func(ls);
+}
+
+
+Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
+                      Dyndata *dyd, const char *name, int firstchar) {
   LexState lexstate;
   FuncState funcstate;
-  BlockCnt bl;
-  TString *tname = luaS_new(L, name);
-  setsvalue2s(L, L->top, tname);  /* push name to protect it */
+  Closure *cl = luaF_newLclosure(L, 1);  /* create main closure */
+  /* anchor closure (to avoid being collected) */
+  setclLvalue(L, L->top, cl);
   incr_top(L);
+  funcstate.f = cl->l.p = luaF_newproto(L);
+  funcstate.f->source = luaS_new(L, name);  /* create and anchor TString */
   lexstate.buff = buff;
   lexstate.dyd = dyd;
   dyd->actvar.n = dyd->gt.n = dyd->label.n = 0;
-  luaX_setinput(L, &lexstate, z, tname, firstchar);
-  open_mainfunc(&lexstate, &funcstate, &bl);
-  luaX_next(&lexstate);  /* read first token */
-  statlist(&lexstate);  /* main body */
-  check(&lexstate, TK_EOS);
-  close_func(&lexstate);
-  L->top--;  /* pop name */
+  luaX_setinput(L, &lexstate, z, funcstate.f->source, firstchar);
+  mainfunc(&lexstate, &funcstate);
   lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs);
   /* all scopes should be correctly finished */
   lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0);
-  return funcstate.f;
+  return cl;  /* it's on the stack too */
 }
 
index caabf46..301167d 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.h,v 1.69 2011/07/27 18:09:01 roberto Exp $
+** $Id: lparser.h,v 1.70 2012/05/08 13:53:33 roberto Exp $
 ** Lua Parser
 ** See Copyright Notice in lua.h
 */
@@ -112,8 +112,8 @@ typedef struct FuncState {
 } FuncState;
 
 
-LUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
-                              Dyndata *dyd, const char *name, int firstchar);
+LUAI_FUNC Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
+                                Dyndata *dyd, const char *name, int firstchar);
 
 
 #endif
index 6e2801c..3c00c28 100644 (file)
@@ -1,11 +1,12 @@
 /*
-** $Id: lstate.c,v 2.92 2011/10/03 17:54:25 roberto Exp $
+** $Id: lstate.c,v 2.98 2012/05/30 12:33:44 roberto Exp $
 ** Global State
 ** See Copyright Notice in lua.h
 */
 
 
 #include <stddef.h>
+#include <string.h>
 
 #define lstate_c
 #define LUA_CORE
 #endif
 
 
-#define MEMERRMSG       "not enough memory"
+#define MEMERRMSG      "not enough memory"
+
+
+/*
+** a macro to help the creation of a unique random seed when a state is
+** created; the seed is used to randomize hashes.
+*/
+#if !defined(luai_makeseed)
+#include <time.h>
+#define luai_makeseed()                cast(size_t, time(NULL))
+#endif
+
 
 
 /*
@@ -66,6 +78,28 @@ typedef struct LG {
 
 
 /*
+** Compute an initial seed as random as possible. In ANSI, rely on
+** Address Space Layout Randomization (if present) to increase
+** randomness..
+*/
+#define addbuff(b,p,e) \
+  { size_t t = cast(size_t, e); \
+    memcpy(buff + p, &t, sizeof(t)); p += sizeof(t); }
+
+static unsigned int makeseed (lua_State *L) {
+  char buff[4 * sizeof(size_t)];
+  unsigned int h = luai_makeseed();
+  int p = 0;
+  addbuff(buff, p, L);  /* heap variable */
+  addbuff(buff, p, &h);  /* local variable */
+  addbuff(buff, p, luaO_nilobject);  /* global variable */
+  addbuff(buff, p, &lua_newstate);  /* public function */
+  lua_assert(p == sizeof(buff));
+  return luaS_hash(buff, p, h);
+}
+
+
+/*
 ** set GCdebt to a new value keeping the value (totalbytes + GCdebt)
 ** invariant
 */
@@ -242,10 +276,11 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
   g->frealloc = f;
   g->ud = ud;
   g->mainthread = L;
+  g->seed = makeseed(L);
   g->uvhead.u.l.prev = &g->uvhead;
   g->uvhead.u.l.next = &g->uvhead;
   g->gcrunning = 0;  /* no GC while building state */
-  g->lastmajormem = 0;
+  g->GCestimate = 0;
   g->strt.size = 0;
   g->strt.nuse = 0;
   g->strt.hash = NULL;
@@ -257,6 +292,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
   g->allgc = NULL;
   g->finobj = NULL;
   g->tobefnz = NULL;
+  g->sweepgc = g->sweepfin = NULL;
   g->gray = g->grayagain = NULL;
   g->weak = g->ephemeron = g->allweak = NULL;
   g->totalbytes = sizeof(LG);
index 4743d74..29f810b 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.h,v 2.74 2011/09/30 12:45:07 roberto Exp $
+** $Id: lstate.h,v 2.81 2012/06/08 15:14:04 roberto Exp $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -72,6 +72,7 @@ typedef struct CallInfo {
   struct CallInfo *previous, *next;  /* dynamic call link */
   short nresults;  /* expected number of results from this function */
   lu_byte callstatus;
+  ptrdiff_t extra;
   union {
     struct {  /* only for Lua functions */
       StkId base;  /* base for this function */
@@ -81,7 +82,6 @@ typedef struct CallInfo {
       int ctx;  /* context info. in case of yields */
       lua_CFunction k;  /* continuation in case of yields */
       ptrdiff_t old_errfunc;
-      ptrdiff_t extra;
       lu_byte old_allowhook;
       lu_byte status;
     } c;
@@ -100,6 +100,7 @@ typedef struct CallInfo {
 #define CIST_YPCALL    (1<<4)  /* call is a yieldable protected call */
 #define CIST_STAT      (1<<5)  /* call has an error status (pcall) */
 #define CIST_TAIL      (1<<6)  /* call was tail called */
+#define CIST_HOOKYIELD (1<<7)  /* last hook called yielded */
 
 
 #define isLua(ci)      ((ci)->callstatus & CIST_LUA)
@@ -113,9 +114,11 @@ typedef struct global_State {
   void *ud;         /* auxiliary data to `frealloc' */
   lu_mem totalbytes;  /* number of bytes currently allocated - GCdebt */
   l_mem GCdebt;  /* bytes allocated not yet compensated by the collector */
-  lu_mem lastmajormem;  /* memory in use after last major collection */
+  lu_mem GCmemtrav;  /* memory traversed by the GC */
+  lu_mem GCestimate;  /* an estimate of the non-garbage memory in use */
   stringtable strt;  /* hash table for strings */
   TValue l_registry;
+  unsigned int seed;  /* randomized seed for hashes */
   lu_byte currentwhite;
   lu_byte gcstate;  /* state of garbage collector */
   lu_byte gckind;  /* kind of GC running */
@@ -123,7 +126,8 @@ typedef struct global_State {
   int sweepstrgc;  /* position of sweep in `strt' */
   GCObject *allgc;  /* list of all collectable objects */
   GCObject *finobj;  /* list of collectable objects with finalizers */
-  GCObject **sweepgc;  /* current position of sweep */
+  GCObject **sweepgc;  /* current position of sweep in list 'allgc' */
+  GCObject **sweepfin;  /* current position of sweep in list 'finobj' */
   GCObject *gray;  /* list of gray objects */
   GCObject *grayagain;  /* list of objects to be traversed atomically */
   GCObject *weak;  /* list of tables with weak values */
@@ -193,11 +197,15 @@ union GCObject {
 #define gch(o)         (&(o)->gch)
 
 /* macros to convert a GCObject into a specific value */
-#define rawgco2ts(o)   check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts))
+#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 gco2cl(o)      check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl))
+#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 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 gco2uv(o)      check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv))
index adec415..8b959f1 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lstring.c,v 2.19 2011/05/03 16:01:57 roberto Exp $
+** $Id: lstring.c,v 2.24 2012/05/11 14:14:42 roberto Exp $
 ** String table (keeps all strings handled by Lua)
 ** See Copyright Notice in lua.h
 */
 #include "lstring.h"
 
 
+/*
+** Lua will use at most ~(2^LUAI_HASHLIMIT) bytes from a string to
+** compute its hash
+*/
+#if !defined(LUAI_HASHLIMIT)
+#define LUAI_HASHLIMIT         5
+#endif
+
+
+/*
+** 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);
+  return (a == b) ||  /* same instance or... */
+    ((len == b->tsv.len) &&  /* equal length and ... */
+     (memcmp(getstr(a), getstr(b), len) == 0));  /* equal contents */
+}
+
+
+/*
+** equality for strings
+*/
+int luaS_eqstr (TString *a, TString *b) {
+  return (a->tsv.tt == b->tsv.tt) &&
+         (a->tsv.tt == LUA_TSHRSTR ? eqshrstr(a, b) : luaS_eqlngstr(a, b));
+}
+
+
+unsigned int luaS_hash (const char *str, size_t l, unsigned int seed) {
+  unsigned int h = seed ^ l;
+  size_t l1;
+  size_t step = (l >> LUAI_HASHLIMIT) + 1;
+  for (l1 = l; l1 >= step; l1 -= step)
+    h = h ^ ((h<<5) + (h>>2) + cast_byte(str[l1 - 1]));
+  return h;
+}
 
+
+/*
+** resizes the string table
+*/
 void luaS_resize (lua_State *L, int newsize) {
   int i;
   stringtable *tb = &G(L)->strt;
@@ -50,37 +92,49 @@ void luaS_resize (lua_State *L, int newsize) {
 }
 
 
-static TString *newlstr (lua_State *L, const char *str, size_t l,
-                                       unsigned int h) {
-  size_t totalsize;  /* total size of TString object */
-  GCObject **list;  /* (pointer to) list where it will be inserted */
+/*
+** creates a new string object
+*/
+static TString *createstrobj (lua_State *L, const char *str, size_t l,
+                              int tag, unsigned int h, GCObject **list) {
   TString *ts;
-  stringtable *tb = &G(L)->strt;
-  if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char))
-    luaM_toobig(L);
-  if (tb->nuse >= cast(lu_int32, tb->size) && tb->size <= MAX_INT/2)
-    luaS_resize(L, tb->size*2);  /* too crowded */
+  size_t totalsize;  /* total size of TString object */
   totalsize = sizeof(TString) + ((l + 1) * sizeof(char));
-  list = &tb->hash[lmod(h, tb->size)];
-  ts = &luaC_newobj(L, LUA_TSTRING, totalsize, list, 0)->ts;
+  ts = &luaC_newobj(L, tag, totalsize, list, 0)->ts;
   ts->tsv.len = l;
   ts->tsv.hash = h;
-  ts->tsv.reserved = 0;
+  ts->tsv.extra = 0;
   memcpy(ts+1, str, l*sizeof(char));
   ((char *)(ts+1))[l] = '\0';  /* ending 0 */
-  tb->nuse++;
   return ts;
 }
 
 
-TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
+/*
+** creates a new short string, inserting it into string table
+*/
+static TString *newshrstr (lua_State *L, const char *str, size_t l,
+                                       unsigned int h) {
+  GCObject **list;  /* (pointer to) list where it will be inserted */
+  stringtable *tb = &G(L)->strt;
+  TString *s;
+  if (tb->nuse >= cast(lu_int32, tb->size) && tb->size <= MAX_INT/2)
+    luaS_resize(L, tb->size*2);  /* too crowded */
+  list = &tb->hash[lmod(h, tb->size)];
+  s = createstrobj(L, str, l, LUA_TSHRSTR, h, list);
+  tb->nuse++;
+  return s;
+}
+
+
+/*
+** checks whether short string exists and reuses it or creates a new one
+*/
+static TString *internshrstr (lua_State *L, const char *str, size_t l) {
   GCObject *o;
-  unsigned int h = cast(unsigned int, l);  /* seed */
-  size_t step = (l>>5)+1;  /* if string is too long, don't hash all its chars */
-  size_t l1;
-  for (l1=l; l1>=step; l1-=step)  /* compute hash */
-    h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1]));
-  for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)];
+  global_State *g = G(L);
+  unsigned int h = luaS_hash(str, l, g->seed);
+  for (o = g->strt.hash[lmod(h, g->strt.size)];
        o != NULL;
        o = gch(o)->next) {
     TString *ts = rawgco2ts(o);
@@ -92,10 +146,27 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
       return ts;
     }
   }
-  return newlstr(L, str, l, h);  /* not found; create a new string */
+  return newshrstr(L, str, l, h);  /* not found; create a new string */
+}
+
+
+/*
+** new string (with explicit length)
+*/
+TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
+  if (l <= LUAI_MAXSHORTLEN)  /* short string? */
+    return internshrstr(L, str, l);
+  else {
+    if (l + 1 > (MAX_SIZET - sizeof(TString))/sizeof(char))
+      luaM_toobig(L);
+    return createstrobj(L, str, l, LUA_TLNGSTR, G(L)->seed, NULL);
+  }
 }
 
 
+/*
+** new zero-terminated string
+*/
 TString *luaS_new (lua_State *L, const char *str) {
   return luaS_newlstr(L, str, strlen(str));
 }
index d708a1b..d312ff3 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lstring.h,v 1.46 2010/04/05 16:26:37 roberto Exp $
+** $Id: lstring.h,v 1.49 2012/02/01 21:57:15 roberto Exp $
 ** String table (keep all strings handled by Lua)
 ** See Copyright Notice in lua.h
 */
 
 
 /*
-** as all string are internalized, string equality becomes
-** pointer equality
+** test whether a string is a reserved word
 */
-#define eqstr(a,b)     ((a) == (b))
+#define isreserved(s)  ((s)->tsv.tt == LUA_TSHRSTR && (s)->tsv.extra > 0)
 
+
+/*
+** equality for short strings, which are always internalized
+*/
+#define eqshrstr(a,b)  check_exp((a)->tsv.tt == LUA_TSHRSTR, (a) == (b))
+
+
+LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, unsigned int seed);
+LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b);
+LUAI_FUNC int luaS_eqstr (TString *a, TString *b);
 LUAI_FUNC void luaS_resize (lua_State *L, int newsize);
 LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e);
 LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
index f5d61fd..e13098b 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lstrlib.c,v 1.173 2011/11/30 18:24:56 roberto Exp $
+** $Id: lstrlib.c,v 1.176 2012/05/23 15:37:09 roberto Exp $
 ** Standard library for string operations and pattern-matching
 ** See Copyright Notice in lua.h
 */
@@ -30,7 +30,7 @@
 
 
 /* macro to `unsign' a character */
-#define uchar(c)        ((unsigned char)(c))
+#define uchar(c)       ((unsigned char)(c))
 
 
 
@@ -119,7 +119,9 @@ static int str_rep (lua_State *L) {
     char *p = luaL_buffinitsize(L, &b, totallen);
     while (n-- > 1) {  /* first n-1 copies (followed by separator) */
       memcpy(p, s, l * sizeof(char)); p += l;
-      memcpy(p, sep, lsep * sizeof(char)); p += lsep;
+      if (lsep > 0) {  /* avoid empty 'memcpy' (may be expensive) */
+        memcpy(p, sep, lsep * sizeof(char)); p += lsep;
+      }
     }
     memcpy(p, s, l * sizeof(char));  /* last copy (not followed by separator) */
     luaL_pushresultsize(&b, totallen);
@@ -745,20 +747,17 @@ static int str_gsub (lua_State *L) {
 #if !defined(LUA_INTFRMLEN)    /* { */
 #if defined(LUA_USE_LONGLONG)
 
-#define LUA_INTFRMLEN           "ll"
-#define LUA_INTFRM_T            long long
+#define LUA_INTFRMLEN          "ll"
+#define LUA_INTFRM_T           long long
 
 #else
 
-#define LUA_INTFRMLEN           "l"
-#define LUA_INTFRM_T            long
+#define LUA_INTFRMLEN          "l"
+#define LUA_INTFRM_T           long
 
 #endif
 #endif                         /* } */
 
-#define MAX_UINTFRM    ((lua_Number)(~(unsigned LUA_INTFRM_T)0))
-#define MAX_INTFRM     ((lua_Number)((~(unsigned LUA_INTFRM_T)0)/2))
-#define MIN_INTFRM     (-(lua_Number)((~(unsigned LUA_INTFRM_T)0)/2) - 1)
 
 /*
 ** LUA_FLTFRMLEN is the length modifier for float conversions in
@@ -767,8 +766,8 @@ static int str_gsub (lua_State *L) {
 */
 #if !defined(LUA_FLTFRMLEN)
 
-#define LUA_FLTFRMLEN           ""
-#define LUA_FLTFRM_T            double
+#define LUA_FLTFRMLEN          ""
+#define LUA_FLTFRM_T           double
 
 #endif
 
@@ -870,18 +869,22 @@ static int str_format (lua_State *L) {
         }
         case 'd':  case 'i': {
           lua_Number n = luaL_checknumber(L, arg);
-          luaL_argcheck(L, (MIN_INTFRM - 1) < n && n < (MAX_INTFRM + 1), arg,
+          LUA_INTFRM_T ni = (LUA_INTFRM_T)n;
+          lua_Number diff = n - (lua_Number)ni;
+          luaL_argcheck(L, -1 < diff && diff < 1, arg,
                         "not a number in proper range");
           addlenmod(form, LUA_INTFRMLEN);
-          nb = sprintf(buff, form, (LUA_INTFRM_T)n);
+          nb = sprintf(buff, form, ni);
           break;
         }
         case 'o':  case 'u':  case 'x':  case 'X': {
           lua_Number n = luaL_checknumber(L, arg);
-          luaL_argcheck(L, 0 <= n && n < (MAX_UINTFRM + 1), arg,
+          unsigned LUA_INTFRM_T ni = (unsigned LUA_INTFRM_T)n;
+          lua_Number diff = n - (lua_Number)ni;
+          luaL_argcheck(L, -1 < diff && diff < 1, arg,
                         "not a non-negative number in proper range");
           addlenmod(form, LUA_INTFRMLEN);
-          nb = sprintf(buff, form, (unsigned LUA_INTFRM_T)n);
+          nb = sprintf(buff, form, ni);
           break;
         }
         case 'e':  case 'E': case 'f':
index 9581add..ffa5ecb 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: ltable.c,v 2.67 2011/11/30 12:41:45 roberto Exp $
+** $Id: ltable.c,v 2.71 2012/05/23 15:37:09 roberto Exp $
 ** Lua tables (hash)
 ** See Copyright Notice in lua.h
 */
 #define MAXASIZE       (1 << MAXBITS)
 
 
-#define hashpow2(t,n)      (gnode(t, lmod((n), sizenode(t))))
+#define hashpow2(t,n)          (gnode(t, lmod((n), sizenode(t))))
 
-#define hashstr(t,str)  hashpow2(t, (str)->tsv.hash)
-#define hashboolean(t,p)        hashpow2(t, p)
+#define hashstr(t,str)         hashpow2(t, (str)->tsv.hash)
+#define hashboolean(t,p)       hashpow2(t, p)
 
 
 /*
@@ -98,7 +98,15 @@ static Node *mainposition (const Table *t, const TValue *key) {
   switch (ttype(key)) {
     case LUA_TNUMBER:
       return hashnum(t, nvalue(key));
-    case LUA_TSTRING:
+    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 */
+      }
+      return hashstr(t, rawtsvalue(key));
+    }
+    case LUA_TSHRSTR:
       return hashstr(t, rawtsvalue(key));
     case LUA_TBOOLEAN:
       return hashboolean(t, bvalue(key));
@@ -453,12 +461,13 @@ const TValue *luaH_getint (Table *t, int key) {
 
 
 /*
-** search function for strings
+** search function for short strings
 */
 const TValue *luaH_getstr (Table *t, TString *key) {
   Node *n = hashstr(t, key);
+  lua_assert(key->tsv.tt == LUA_TSHRSTR);
   do {  /* check whether `key' is somewhere in the chain */
-    if (ttisstring(gkey(n)) && eqstr(rawtsvalue(gkey(n)), key))
+    if (ttisshrstring(gkey(n)) && eqshrstr(rawtsvalue(gkey(n)), key))
       return gval(n);  /* that's it */
     else n = gnext(n);
   } while (n);
@@ -470,9 +479,9 @@ const TValue *luaH_getstr (Table *t, TString *key) {
 ** main search function
 */
 const TValue *luaH_get (Table *t, const TValue *key) {
-  switch (ttypenv(key)) {
+  switch (ttype(key)) {
     case LUA_TNIL: return luaO_nilobject;
-    case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key));
+    case LUA_TSHRSTR: return luaH_getstr(t, rawtsvalue(key));
     case LUA_TNUMBER: {
       int k;
       lua_Number n = nvalue(key);
index e20ab86..7614c70 100644 (file)
--- a/src/lua.c
+++ b/src/lua.c
@@ -1,5 +1,5 @@
 /*
-** $Id: lua.c,v 1.203 2011/12/12 16:34:03 roberto Exp $
+** $Id: lua.c,v 1.205 2012/05/23 15:37:09 roberto Exp $
 ** Lua stand-alone interpreter
 ** See Copyright Notice in lua.h
 */
 */
 #if defined(LUA_USE_ISATTY)
 #include <unistd.h>
-#define lua_stdin_is_tty()      isatty(0)
+#define lua_stdin_is_tty()     isatty(0)
 #elif defined(LUA_WIN)
 #include <io.h>
 #include <stdio.h>
-#define lua_stdin_is_tty()      _isatty(_fileno(stdin))
+#define lua_stdin_is_tty()     _isatty(_fileno(stdin))
 #else
-#define lua_stdin_is_tty()      1  /* assume stdin is a tty */
+#define lua_stdin_is_tty()     1  /* assume stdin is a tty */
 #endif
 
 
 #include <stdio.h>
 #include <readline/readline.h>
 #include <readline/history.h>
-#define lua_readline(L,b,p)     ((void)L, ((b)=readline(p)) != NULL)
+#define lua_readline(L,b,p)    ((void)L, ((b)=readline(p)) != NULL)
 #define lua_saveline(L,idx) \
         if (lua_rawlen(L,idx) > 0)  /* non-empty line? */ \
           add_history(lua_tostring(L, idx));  /* add it to history */
-#define lua_freeline(L,b)       ((void)L, free(b))
+#define lua_freeline(L,b)      ((void)L, free(b))
 
 #elif !defined(lua_readline)
 
-#define lua_readline(L,b,p)     \
+#define lua_readline(L,b,p) \
         ((void)L, fputs(p, stdout), fflush(stdout),  /* show prompt */ \
         fgets(b, LUA_MAXINPUT, stdin) != NULL)  /* get line */
-#define lua_saveline(L,idx)     { (void)L; (void)idx; }
-#define lua_freeline(L,b)       { (void)L; (void)b; }
+#define lua_saveline(L,idx)    { (void)L; (void)idx; }
+#define lua_freeline(L,b)      { (void)L; (void)b; }
 
 #endif
 
@@ -223,16 +223,11 @@ static int dostring (lua_State *L, const char *s, const char *name) {
 
 static int dolibrary (lua_State *L, const char *name) {
   int status;
-  lua_pushglobaltable(L);
-  lua_getfield(L, -1, "require");
+  lua_getglobal(L, "require");
   lua_pushstring(L, name);
-  status = docall(L, 1, 1);
-  if (status == LUA_OK) {
-    lua_setfield(L, -2, name);  /* global[name] = require return */
-    lua_pop(L, 1);  /* remove global table */
-  }
-  else
-    lua_remove(L, -2);  /* remove global table (below error msg.) */
+  status = docall(L, 1, 1);  /* call 'require(name)' */
+  if (status == LUA_OK)
+    lua_setglobal(L, name);  /* global[name] = require return */
   return report(L, status);
 }
 
index 1fafa45..a3a3a70 100644 (file)
--- a/src/lua.h
+++ b/src/lua.h
@@ -1,5 +1,5 @@
 /*
-** $Id: lua.h,v 1.282 2011/11/29 15:55:08 roberto Exp $
+** $Id: lua.h,v 1.283 2012/04/20 13:18:26 roberto Exp $
 ** Lua - A Scripting Language
 ** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
 ** See Copyright Notice at the end of this file
 #define LUA_VERSION_MAJOR      "5"
 #define LUA_VERSION_MINOR      "2"
 #define LUA_VERSION_NUM                502
-#define LUA_VERSION_RELEASE    "0"
+#define LUA_VERSION_RELEASE    "1"
 
 #define LUA_VERSION    "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
 #define LUA_RELEASE    LUA_VERSION "." LUA_VERSION_RELEASE
-#define LUA_COPYRIGHT  LUA_RELEASE "  Copyright (C) 1994-2011 Lua.org, PUC-Rio"
+#define LUA_COPYRIGHT  LUA_RELEASE "  Copyright (C) 1994-2012 Lua.org, PUC-Rio"
 #define LUA_AUTHORS    "R. Ierusalimschy, L. H. de Figueiredo, W. Celes"
 
 
@@ -413,7 +413,7 @@ struct lua_Debug {
 
 
 /******************************************************************************
-* Copyright (C) 1994-2011 Lua.org, PUC-Rio.  All rights reserved.
+* Copyright (C) 1994-2012 Lua.org, PUC-Rio.
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
index bab401e..e4335df 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: luaconf.h,v 1.170 2011/12/06 16:58:36 roberto Exp $
+** $Id: luaconf.h,v 1.172 2012/05/11 14:14:42 roberto Exp $
 ** Configuration file for Lua
 ** See Copyright Notice in lua.h
 */
        (fprintf(stderr, (s), (p)), fflush(stderr))
 
 
+/*
+@@ LUAI_MAXSHORTLEN is the maximum length for short strings, that is,
+** strings that are internalized. (Cannot be smaller than reserved words
+** or tags for metamethods, as these strings must be internalized;
+** #("function") = 8, #("__newindex") = 10.)
+*/
+#define LUAI_MAXSHORTLEN        40
 
 
 
 #define LUA_UNSIGNED   unsigned LUA_INT32
 
 
-#if defined(LUA_CORE)          /* { */
 
-#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI)   /* { */
+/*
+** Some tricks with doubles
+*/
 
-/* On a Microsoft compiler on a Pentium, use assembler to avoid clashes
-   with a DirectX idiosyncrasy */
+#if defined(LUA_CORE) && \
+    defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI)   /* { */
+/*
+** The next definitions activate some tricks to speed up the
+** conversion from doubles to integer types, mainly to LUA_UNSIGNED.
+**
+@@ MS_ASMTRICK uses Microsoft assembler to avoid clashes with a
+** DirectX idiosyncrasy.
+**
+@@ LUA_IEEE754TRICK uses a trick that should work on any machine
+** using IEEE754 with a 32-bit integer type.
+**
+@@ LUA_IEEELL extends the trick to LUA_INTEGER; should only be
+** defined when LUA_INTEGER is a 32-bit integer.
+**
+@@ LUA_IEEEENDIAN is the endianness of doubles in your machine
+** (0 for little endian, 1 for big endian); if not defined, Lua will
+** check it dynamically for LUA_IEEE754TRICK (but not for LUA_NANTRICK).
+**
+@@ LUA_NANTRICK controls the use of a trick to pack all types into
+** a single double value, using NaN values to represent non-number
+** values. The trick only works on 32-bit machines (ints and pointers
+** are 32-bit values) with numbers represented as IEEE 754-2008 doubles
+** with conventional endianess (12345678 or 87654321), in CPUs that do
+** not produce signaling NaN values (all NaNs are quiet).
+*/
+
+/* Microsoft compiler on a Pentium (32 bit) ? */
 #if defined(LUA_WIN) && defined(_MSC_VER) && defined(_M_IX86)  /* { */
 
 #define MS_ASMTRICK
+#define LUA_IEEEENDIAN         0
+#define LUA_NANTRICK
 
-#else                          /* }{ */
-/* the next definition uses a trick that should work on any machine
-   using IEEE754 with a 32-bit integer type */
-
-#define LUA_IEEE754TRICK
-
-/*
-@@ LUA_IEEEENDIAN is the endianness of doubles in your machine
-** (0 for little endian, 1 for big endian); if not defined, Lua will
-** check it dynamically.
-*/
-/* check for known architectures */
-#if defined(__i386__) || defined(__i386) || defined(__X86__) || \
-    defined (__x86_64)
-#define LUA_IEEEENDIAN 0
-#elif defined(__POWERPC__) || defined(__ppc__)
-#define LUA_IEEEENDIAN 1
-#endif
 
-#endif                         /* } */
+/* pentium 32 bits? */
+#elif defined(__i386__) || defined(__i386) || defined(__X86__) /* }{ */
 
-#endif                 /* } */
+#define LUA_IEEE754TRICK
+#define LUA_IEEELL
+#define LUA_IEEEENDIAN         0
+#define LUA_NANTRICK
 
-#endif                 /* } */
+/* pentium 64 bits? */
+#elif defined(__x86_64)                                                /* }{ */
 
-/* }================================================================== */
+#define LUA_IEEE754TRICK
+#define LUA_IEEEENDIAN         0
 
+#elif defined(__POWERPC__) || defined(__ppc__)                 /* }{ */
 
-/*
-@@ LUA_NANTRICK_LE/LUA_NANTRICK_BE controls the use of a trick to
-** pack all types into a single double value, using NaN values to
-** represent non-number values. The trick only works on 32-bit machines
-** (ints and pointers are 32-bit values) with numbers represented as
-** IEEE 754-2008 doubles with conventional endianess (12345678 or
-** 87654321), in CPUs that do not produce signaling NaN values (all NaNs
-** are quiet).
-*/
-#if defined(LUA_CORE) && \
-    defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI)   /* { */
+#define LUA_IEEE754TRICK
+#define LUA_IEEEENDIAN         1
 
-/* little-endian architectures that satisfy those conditions */
-#if defined(__i386__) || defined(__i386) || defined(__X86__) || \
-    defined(_M_IX86)
+#else                                                          /* }{ */
 
-#define LUA_NANTRICK_LE
+/* assume IEEE754 and a 32-bit integer type */
+#define LUA_IEEE754TRICK
 
-#endif
+#endif                                                         /* } */
 
 #endif                                                 /* } */
 
+/* }================================================================== */
+
 
 
 
index 80c7aa3..54de011 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lundump.c,v 1.71 2011/12/07 10:39:12 lhf Exp $
+** $Id: lundump.c,v 2.22 2012/05/08 13:53:33 roberto Exp $
 ** load precompiled Lua chunks
 ** See Copyright Notice in lua.h
 */
@@ -27,7 +27,7 @@ typedef struct {
  const char* name;
 } LoadState;
 
-static void error(LoadState* S, const char* why)
+static l_noret error(LoadState* S, const char* why)
 {
  luaO_pushfstring(S->L,"%s: %s precompiled chunk",S->name,why);
  luaD_throw(S->L,LUA_ERRSYNTAX);
@@ -39,7 +39,7 @@ static void error(LoadState* S, const char* why)
 #define LoadVector(S,b,n,size) LoadMem(S,b,n,size)
 
 #if !defined(luai_verifycode)
-#define luai_verifycode(L,b,f) (f)
+#define luai_verifycode(L,b,f) /* empty */
 #endif
 
 static void LoadBlock(LoadState* S, void* b, size_t size)
@@ -91,7 +91,7 @@ static void LoadCode(LoadState* S, Proto* f)
  LoadVector(S,f->code,n,sizeof(Instruction));
 }
 
-static Proto* LoadFunction(LoadState* S);
+static void LoadFunction(LoadState* S, Proto* f);
 
 static void LoadConstants(LoadState* S, Proto* f)
 {
@@ -118,13 +118,18 @@ static void LoadConstants(LoadState* S, Proto* f)
    case LUA_TSTRING:
        setsvalue2n(S->L,o,LoadString(S));
        break;
+    default: lua_assert(0);
   }
  }
  n=LoadInt(S);
  f->p=luaM_newvector(S->L,n,Proto*);
  f->sizep=n;
  for (i=0; i<n; i++) f->p[i]=NULL;
- for (i=0; i<n; i++) f->p[i]=LoadFunction(S);
+ for (i=0; i<n; i++)
+ {
+  f->p[i]=luaF_newproto(S->L);
+  LoadFunction(S,f->p[i]);
+ }
 }
 
 static void LoadUpvalues(LoadState* S, Proto* f)
@@ -163,10 +168,8 @@ static void LoadDebug(LoadState* S, Proto* f)
  for (i=0; i<n; i++) f->upvalues[i].name=LoadString(S);
 }
 
-static Proto* LoadFunction(LoadState* S)
+static void LoadFunction(LoadState* S, Proto* f)
 {
- Proto* f=luaF_newproto(S->L);
- setptvalue2s(S->L,S->L->top,f); incr_top(S->L);
  f->linedefined=LoadInt(S);
  f->lastlinedefined=LoadInt(S);
  f->numparams=LoadByte(S);
@@ -176,8 +179,6 @@ static Proto* LoadFunction(LoadState* S)
  LoadConstants(S,f);
  LoadUpvalues(S,f);
  LoadDebug(S,f);
- S->L->top--;
- return f;
 }
 
 /* the code below must be consistent with the code in luaU_header */
@@ -202,9 +203,10 @@ static void LoadHeader(LoadState* S)
 /*
 ** load precompiled chunk
 */
-Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name)
+Closure* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name)
 {
  LoadState S;
+ Closure* cl;
  if (*name=='@' || *name=='=')
   S.name=name+1;
  else if (*name==LUA_SIGNATURE[0])
@@ -215,7 +217,19 @@ Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name)
  S.Z=Z;
  S.b=buff;
  LoadHeader(&S);
- return luai_verifycode(L,buff,LoadFunction(&S));
+ cl=luaF_newLclosure(L,1);
+ setclLvalue(L,L->top,cl); incr_top(L);
+ cl->l.p=luaF_newproto(L);
+ LoadFunction(&S,cl->l.p);
+ if (cl->l.p->sizeupvalues != 1)
+ {
+  Proto* p=cl->l.p;
+  cl=luaF_newLclosure(L,cl->l.p->sizeupvalues);
+  cl->l.p=p;
+  setclLvalue(L,L->top-1,cl);
+ }
+ luai_verifycode(L,buff,cl->l.p);
+ return cl;
 }
 
 #define MYINT(s)       (s[0]-'0')
index b63993f..2b8acce 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lundump.h,v 1.44 2011/05/06 13:35:17 lhf Exp $
+** $Id: lundump.h,v 1.39 2012/05/08 13:53:33 roberto Exp $
 ** load precompiled Lua chunks
 ** See Copyright Notice in lua.h
 */
@@ -11,7 +11,7 @@
 #include "lzio.h"
 
 /* load one chunk; from lundump.c */
-LUAI_FUNC Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name);
+LUAI_FUNC Closure* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name);
 
 /* make header; from lundump.c */
 LUAI_FUNC void luaU_header (lu_byte* h);
index 694971b..b77eac2 100644 (file)
--- a/src/lvm.c
+++ b/src/lvm.c
@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.c,v 2.147 2011/12/07 14:43:55 roberto Exp $
+** $Id: lvm.c,v 2.152 2012/06/08 15:14:04 roberto Exp $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -60,10 +60,15 @@ int luaV_tostring (lua_State *L, StkId obj) {
 static void traceexec (lua_State *L) {
   CallInfo *ci = L->ci;
   lu_byte mask = L->hookmask;
-  if ((mask & LUA_MASKCOUNT) && L->hookcount == 0) {
-    resethookcount(L);
-    luaD_hook(L, LUA_HOOKCOUNT, -1);
+  int counthook = ((mask & LUA_MASKCOUNT) && L->hookcount == 0);
+  if (counthook)
+    resethookcount(L);  /* reset count */
+  if (ci->callstatus & CIST_HOOKYIELD) {  /* called hook last time? */
+    ci->callstatus &= ~CIST_HOOKYIELD;  /* erase mark */
+    return;  /* do not call hook again (VM yielded, so it did not move) */
   }
+  if (counthook)
+    luaD_hook(L, LUA_HOOKCOUNT, -1);  /* call count hook */
   if (mask & LUA_MASKLINE) {
     Proto *p = ci_func(ci)->p;
     int npc = pcRel(ci->u.l.savedpc, p);
@@ -71,11 +76,15 @@ static void traceexec (lua_State *L) {
     if (npc == 0 ||  /* call linehook when enter a new function, */
         ci->u.l.savedpc <= L->oldpc ||  /* when jump back (loop), or when */
         newline != getfuncline(p, pcRel(L->oldpc, p)))  /* enter a new line */
-      luaD_hook(L, LUA_HOOKLINE, newline);
+      luaD_hook(L, LUA_HOOKLINE, newline);  /* call line hook */
   }
   L->oldpc = ci->u.l.savedpc;
   if (L->status == LUA_YIELD) {  /* did hook yield? */
+    if (counthook)
+      L->hookcount = 1;  /* undo decrement to zero */
     ci->u.l.savedpc--;  /* undo increment (resume will increment it again) */
+    ci->callstatus |= CIST_HOOKYIELD;  /* mark that it yieled */
+    ci->func = L->top - 1;  /* protect stack below results */
     luaD_throw(L, LUA_YIELD);
   }
 }
@@ -258,7 +267,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_TSTRING: return eqstr(rawtsvalue(t1), rawtsvalue(t2));
+    case LUA_TSHRSTR: return eqshrstr(rawtsvalue(t1), rawtsvalue(t2));
+    case LUA_TLNGSTR: return luaS_eqlngstr(rawtsvalue(t1), rawtsvalue(t2));
     case LUA_TUSERDATA: {
       if (uvalue(t1) == uvalue(t2)) return 1;
       else if (L == NULL) return 0;
@@ -293,7 +303,7 @@ void luaV_concat (lua_State *L, int total) {
     else if (tsvalue(top-1)->len == 0)  /* second operand is empty? */
       (void)tostring(L, top - 2);  /* result is first operand */
     else if (ttisstring(top-2) && tsvalue(top-2)->len == 0) {
-      setsvalue2s(L, top-2, rawtsvalue(top-1));  /* result is second op. */
+      setobjs2s(L, top - 2, top - 1);  /* result is second op. */
     }
     else {
       /* at least two non-empty string values; get as many as possible */
@@ -394,7 +404,8 @@ static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base,
   int nup = p->sizeupvalues;
   Upvaldesc *uv = p->upvalues;
   int i;
-  Closure *ncl = luaF_newLclosure(L, p);
+  Closure *ncl = luaF_newLclosure(L, nup);
+  ncl->l.p = p;
   setclLvalue(L, ra, ncl);  /* anchor new closure in stack */
   for (i = 0; i < nup; i++) {  /* fill in its upvalues */
     if (uv[i].instack)  /* upvalue refers to local variable? */
@@ -500,7 +511,11 @@ void luaV_finishOp (lua_State *L) {
 
 #define Protect(x)     { {x;}; base = ci->u.l.base; }
 
-#define checkGC(L,c)   Protect(luaC_condGC(L, c); luai_threadyield(L);)
+#define checkGC(L,c)  \
+  Protect( luaC_condGC(L,{L->top = (c);  /* limit of live values */ \
+                          luaC_step(L); \
+                          L->top = ci->top;})  /* restore top */ \
+           luai_threadyield(L); )
 
 
 #define arith_op(op,tm) { \
@@ -593,11 +608,7 @@ void luaV_execute (lua_State *L) {
         sethvalue(L, ra, t);
         if (b != 0 || c != 0)
           luaH_resize(L, t, luaO_fb2int(b), luaO_fb2int(c));
-        checkGC(L,
-          L->top = ra + 1;  /* limit of live values */
-          luaC_step(L);
-          L->top = ci->top;  /* restore top */
-        )
+        checkGC(L, ra + 1);
       )
       vmcase(OP_SELF,
         StkId rb = RB(i);
@@ -649,10 +660,7 @@ void luaV_execute (lua_State *L) {
         ra = RA(i);  /* 'luav_concat' may invoke TMs and move the stack */
         rb = b + base;
         setobjs2s(L, ra, rb);
-        checkGC(L,
-          L->top = (ra >= rb ? ra + 1 : rb);  /* limit of live values */
-          luaC_step(L);
-        )
+        checkGC(L, (ra >= rb ? ra + 1 : rb));
         L->top = ci->top;  /* restore top */
       )
       vmcase(OP_JMP,
@@ -830,11 +838,7 @@ void luaV_execute (lua_State *L) {
           pushclosure(L, p, cl->upvals, base, ra);  /* create a new one */
         else
           setclLvalue(L, ra, ncl);  /* push cashed closure */
-        checkGC(L,
-          L->top = ra + 1;  /* limit of live values */
-          luaC_step(L);
-          L->top = ci->top;  /* restore top */
-        )
+        checkGC(L, ra + 1);
       )
       vmcase(OP_VARARG,
         int b = GETARG_B(i) - 1;
index 354f94e..8b77054 100644 (file)
@@ -1,6 +1,6 @@
 /*
-** $Id: lzio.c,v 1.34 2011/07/15 12:35:32 roberto Exp $
-** a generic input stream interface
+** $Id: lzio.c,v 1.35 2012/05/14 13:34:18 roberto Exp $
+** Buffered streams
 ** See Copyright Notice in lua.h
 */