diff options
author | Peter Drahoš <drahosp@gmail.com> | 2012-06-15 12:17:15 +0200 |
---|---|---|
committer | Peter Drahoš <drahosp@gmail.com> | 2012-06-15 12:17:15 +0200 |
commit | 47bda2e9009c8d290dba0943d437768bddd533d9 (patch) | |
tree | 14972cf2689052dd8a6d016374c961be3b841247 | |
parent | 0c085822a7055ec20aefe7582abe875a7af59f9e (diff) | |
download | lua-47bda2e9009c8d290dba0943d437768bddd533d9.tar.gz |
Updated to Lua 5.2.1
-rw-r--r-- | CMakeLists.txt | 78 | ||||
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | README.md | 4 | ||||
-rw-r--r-- | dist.info | 2 | ||||
-rw-r--r-- | doc/contents.html | 8 | ||||
-rw-r--r-- | doc/lua.css | 10 | ||||
-rw-r--r-- | doc/manual.css | 4 | ||||
-rw-r--r-- | doc/manual.html | 266 | ||||
-rw-r--r-- | doc/readme.html | 17 | ||||
-rw-r--r-- | src/Makefile | 2 | ||||
-rw-r--r-- | src/lapi.c | 20 | ||||
-rw-r--r-- | src/lauxlib.c | 19 | ||||
-rw-r--r-- | src/lbaselib.c | 3 | ||||
-rw-r--r-- | src/lcorolib.c | 5 | ||||
-rw-r--r-- | src/ldblib.c | 21 | ||||
-rw-r--r-- | src/ldebug.c | 13 | ||||
-rw-r--r-- | src/ldo.c | 32 | ||||
-rw-r--r-- | src/ldump.c | 7 | ||||
-rw-r--r-- | src/lfunc.c | 20 | ||||
-rw-r--r-- | src/lfunc.h | 5 | ||||
-rw-r--r-- | src/lgc.c | 456 | ||||
-rw-r--r-- | src/lgc.h | 10 | ||||
-rw-r--r-- | src/llex.c | 27 | ||||
-rw-r--r-- | src/llimits.h | 17 | ||||
-rw-r--r-- | src/lmathlib.c | 12 | ||||
-rw-r--r-- | src/lmem.c | 18 | ||||
-rw-r--r-- | src/loadlib.c | 97 | ||||
-rw-r--r-- | src/lobject.h | 75 | ||||
-rw-r--r-- | src/lopcodes.c | 3 | ||||
-rw-r--r-- | src/loslib.c | 17 | ||||
-rw-r--r-- | src/lparser.c | 153 | ||||
-rw-r--r-- | src/lparser.h | 6 | ||||
-rw-r--r-- | src/lstate.c | 42 | ||||
-rw-r--r-- | src/lstate.h | 20 | ||||
-rw-r--r-- | src/lstring.c | 115 | ||||
-rw-r--r-- | src/lstring.h | 17 | ||||
-rw-r--r-- | src/lstrlib.c | 35 | ||||
-rw-r--r-- | src/ltable.c | 27 | ||||
-rw-r--r-- | src/lua.c | 31 | ||||
-rw-r--r-- | src/lua.h | 8 | ||||
-rw-r--r-- | src/luaconf.h.in | 74 | ||||
-rw-r--r-- | src/lundump.c | 38 | ||||
-rw-r--r-- | src/lundump.h | 4 | ||||
-rw-r--r-- | src/lvm.c | 50 | ||||
-rw-r--r-- | src/lzio.c | 4 |
45 files changed, 1121 insertions, 773 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 3b953a3..e445082 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,11 +1,11 @@ -# Copyright (C) 2007-2011 LuaDist. +# Copyright (C) 2007-2012 LuaDist. # Created by Peter Drahoš, Peter Kapec # Redistribution and use of this file is allowed according to the terms of the MIT license. # For details see the COPYRIGHT file distributed with LuaDist. # Please note that the package source code is licensed under its own license. project ( lua C ) -cmake_minimum_required ( VERSION 2.6 ) +cmake_minimum_required ( VERSION 2.8 ) include ( cmake/dist.cmake ) ## CONFIGURATION @@ -20,7 +20,6 @@ option ( LUA_COMPAT_ALL "Enable backwards compatibility options." ON ) set ( LUA_IDSIZE 60 CACHE NUMBER "gives the maximum size for the description of the source." ) #2DO: LUAI_* and LUAL_* settings, for now defaults are used. - set ( LUA_DIRSEP "/" ) set ( LUA_MODULE_SUFFIX ${CMAKE_SHARED_MODULE_SUFFIX} ) set ( LUA_LDIR ${INSTALL_LMOD} ) @@ -29,10 +28,10 @@ set ( LUA_CDIR ${INSTALL_CMOD} ) if ( LUA_USE_RELATIVE_LOADLIB ) # This will set up relative paths to lib string ( REGEX REPLACE "[^!/]+" ".." LUA_DIR "!/${INSTALL_BIN}/" ) -else () +else ( ) # Direct path to installation - set ( LUA_DIR ${CMAKE_INSTALL_PREFIX} CACHE STRING "Destination from which modules will be resolved. See INSTALL_LMOD and INSTALL_CMOD.") -endif () + set ( LUA_DIR ${CMAKE_INSTALL_PREFIX} CACHE STRING "Destination from which modules will be resolved. See INSTALL_LMOD and INSTALL_CMOD." ) +endif ( ) set ( LUA_PATH_DEFAULT "./?.lua;${LUA_DIR}${LUA_LDIR}/?.lua;${LUA_DIR}${LUA_LDIR}/?/init.lua" ) set ( LUA_CPATH_DEFAULT "./?${LUA_MODULE_SUFFIX};${LUA_DIR}${LUA_CDIR}/?${LUA_MODULE_SUFFIX};${LUA_DIR}${LUA_CDIR}/loadall${LUA_MODULE_SUFFIX}" ) @@ -42,59 +41,58 @@ if ( WIN32 AND NOT CYGWIN ) option ( LUA_WIN "Windows specific build." ON ) option ( LUA_BUILD_AS_DLL "Build Lua library as Dll." ON ) # Paths (Double escapes needed) - set ( LUA_DIRSEP "\\\\" ) - string ( REPLACE "/" ${LUA_DIRSEP} LUA_DIR "${LUA_DIR}" ) + set ( LUA_DIRSEP "\\\\" ) string ( REPLACE " /" ${LUA_DIRSEP} LUA_DIR "${LUA_DIR}" ) string ( REPLACE "/" ${LUA_DIRSEP} LUA_LDIR "${LUA_LDIR}" ) string ( REPLACE "/" ${LUA_DIRSEP} LUA_CDIR "${LUA_CDIR}" ) string ( REPLACE "/" ${LUA_DIRSEP} LUA_PATH_DEFAULT "${LUA_PATH_DEFAULT}" ) string ( REPLACE "/" ${LUA_DIRSEP} LUA_CPATH_DEFAULT "${LUA_CPATH_DEFAULT}" ) -else () +else ( ) # Posix systems (incl. Cygwin) option ( LUA_USE_POSIX "Use POSIX functionality." ON ) option ( LUA_USE_DLOPEN "Use dynamic linker to load modules." ON ) option ( LUA_USE_MKSTEMP "Use mkstep." ON ) option ( LUA_USE_ISATTY "Use tty." ON ) option ( LUA_USE_POPEN "Use popen." ON ) - option ( LUA_USE_ULONGJMP "Use ulongjmp" ON) + option ( LUA_USE_ULONGJMP "Use ulongjmp" ON ) option ( LUA_USE_STRTODHEX "assume 'strtod' handles hexa formats" ON ) option ( LUA_USE_AFORMAT "assume 'printf' handles 'aA' specifiers" ON ) - option ( LUA_USE_LONGLONG "assume support for long long" ON) -endif () + option ( LUA_USE_LONGLONG "assume support for long long" ON ) +endif ( ) ## SETUP # Optional libraries find_package ( Readline ) if ( READLINE_FOUND ) option ( LUA_USE_READLINE "Use readline in the Lua CLI." ON ) -endif () +endif ( ) find_package ( Curses ) if ( CURSES_FOUND ) option ( LUA_USE_CURSES "Use curses in the Lua CLI." ON ) -endif () +endif ( ) # Setup needed variables and libraries if ( LUA_USE_POSIX ) # On POSIX Lua links to standard math library "m" list ( APPEND LIBS m ) -endif () +endif ( ) if ( LUA_USE_DLOPEN ) # Link to dynamic linker library "dl" list ( APPEND LIBS dl ) -endif () +endif ( ) if ( LUA_USE_READLINE ) # Add readline include_directories ( ${READLINE_INCLUDE_DIR} ) list ( APPEND LIBS ${READLINE_LIBRARY} ) -endif () +endif ( ) if ( LUA_USE_CURSES ) # Add curses include_directories ( ${CURSES_INCLUDE_DIR} ) list ( APPEND LIBS ${CURSES_LIBRARY} ) -endif () +endif ( ) ## SOURCES # Generate luaconf.h @@ -102,48 +100,20 @@ configure_file ( src/luaconf.h.in ${CMAKE_CURRENT_BINARY_DIR}/luaconf.h ) # Sources and headers include_directories ( src ${CMAKE_CURRENT_BINARY_DIR} ) -set ( SRC_CORE - src/lapi.c - src/lcode.c - src/lctype.c - src/ldebug.c - src/ldo.c - src/ldump.c - src/lfunc.c - src/lgc.c - src/llex.c - src/lmem.c - src/lobject.c - src/lopcodes.c - src/lparser.c - src/lstate.c - src/lstring.c - src/ltable.c - src/ltm.c - src/lundump.c - src/lvm.c - src/lzio.c) -set ( SRC_LIB - src/lauxlib.c - src/lbaselib.c - src/lbitlib.c - src/lcorolib.c - src/ldblib.c - src/liolib.c - src/lmathlib.c - src/loslib.c - src/lstrlib.c - src/ltablib.c - src/linit.c) +set ( SRC_CORE src/lapi.c src/lcode.c src/lctype.c src/ldebug.c src/ldo.c src/ldump.c + src/lfunc.c src/lgc.c src/llex.c src/lmem.c src/lobject.c src/lopcodes.c src/lparser.c + src/lstate.c src/lstring.c src/ltable.c src/ltm.c src/lundump.c src/lvm.c src/lzio.c ) +set ( SRC_LIB src/lauxlib.c src/lbaselib.c src/lbitlib.c src/lcorolib.c src/ldblib.c + src/liolib.c src/lmathlib.c src/loslib.c src/lstrlib.c src/ltablib.c src/linit.c ) set ( SRC_LUA src/lua.c ) set ( SRC_LUAC src/luac.c ) if ( LUA_USE_RELATIVE_LOADLIB ) # Use modified loadlib list ( APPEND SRC_LIB src/loadlib_rel.c ) -else () +else ( ) list ( APPEND SRC_LIB src/loadlib.c ) -endif () +endif ( ) ## BUILD # Create lua library @@ -161,7 +131,7 @@ install_executable ( lua luac ) install_library ( liblua ) install_data ( README.md ) #install_lua_module ( strict etc/strict.lua ) -install_header (src/lua.h src/lualib.h src/lauxlib.h ${CMAKE_CURRENT_BINARY_DIR}/luaconf.h ) +install_header ( src/lua.h src/lualib.h src/lauxlib.h ${CMAKE_CURRENT_BINARY_DIR}/luaconf.h ) install_doc ( doc/ ) install_foo ( etc/ ) #install_test ( test/ ) @@ -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) @@ -1,9 +1,7 @@ -This is Lua 5.2, released on 12 Dec 2011. +This is Lua 5.2.1, released on 08 Jun 2012. ================ -[![Build Status](https://secure.travis-ci.org/LuaDist/lua.png?branch=master)](http://travis-ci.org/LuaDist/lua) - For installation instructions, license details, and further information about Lua, see doc/readme.html. @@ -1,7 +1,7 @@ --- This file is part of LuaDist project name = "lua" -version = "5.2" +version = "5.2.1" desc = "Lua is a powerful, fast, light-weight, embeddable scripting language." author = "Roberto Ierusalimschy, Waldemar Celes, Luiz Henrique de Figueiredo" diff --git a/doc/contents.html b/doc/contents.html index 5342723..9f50605 100644 --- a/doc/contents.html +++ b/doc/contents.html @@ -33,9 +33,9 @@ For a complete introduction to Lua programming, see the book <A HREF="#index">index</A> <HR> <SMALL> -Copyright © 2011 Lua.org, PUC-Rio. +Copyright © 2011–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> diff --git a/doc/lua.css b/doc/lua.css index 54708f8..7fafbb1 100644 --- a/doc/lua.css +++ b/doc/lua.css @@ -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 ; } diff --git a/doc/manual.css b/doc/manual.css index ac357a8..b49b362 100644 --- a/doc/manual.css +++ b/doc/manual.css @@ -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 ; } diff --git a/doc/manual.html b/doc/manual.html index 360d316..4ba084d 100644 --- a/doc/manual.html +++ b/doc/manual.html @@ -19,9 +19,9 @@ Lua 5.2 Reference Manual by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes <p> <small> -Copyright © 2011 Lua.org, PUC-Rio. +Copyright © 2011–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 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 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, –]</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">§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 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 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">[-?, +?, –]</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, –]</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">[-?, +?, –]</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">[-?, +?, –]</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, –]</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, &b, sz)</code>.< <li>Then copy the string into that space.</li> <li> -Finish by calling <code>luaL_pushresult(&b, sz)</code>, +Finish by calling <code>luaL_pushresultsize(&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">§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 <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 <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 5.1 +have been removed in Lua 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> diff --git a/doc/readme.html b/doc/readme.html index f0c77a1..2ff294e 100644 --- a/doc/readme.html +++ b/doc/readme.html @@ -43,7 +43,6 @@ Welcome to Lua 5.2 <A HREF="#license">license</A> · <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 © 1994–2011 Lua.org, PUC-Rio. +Copyright © 1994–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> diff --git a/src/Makefile b/src/Makefile index bba1693..8c9ee67 100644 --- a/src/Makefile +++ b/src/Makefile @@ -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) @@ -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; } diff --git a/src/lauxlib.c b/src/lauxlib.c index 0aa80fd..36ae7e6 100644 --- a/src/lauxlib.c +++ b/src/lauxlib.c @@ -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 */ } } diff --git a/src/lbaselib.c b/src/lbaselib.c index 1dfae30..dbfcb02 100644 --- a/src/lbaselib.c +++ b/src/lbaselib.c @@ -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; } diff --git a/src/lcorolib.c b/src/lcorolib.c index 0edde26..c7932d9 100644 --- a/src/lcorolib.c +++ b/src/lcorolib.c @@ -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; diff --git a/src/ldblib.c b/src/ldblib.c index 3c2f159..c022694 100644 --- a/src/ldblib.c +++ b/src/ldblib.c @@ -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)); diff --git a/src/ldebug.c b/src/ldebug.c index 31b7ae4..43f8f04 100644 --- a/src/ldebug.c +++ b/src/ldebug.c @@ -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; } @@ -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); } diff --git a/src/ldump.c b/src/ldump.c index 699e1dc..d5e6a47 100644 --- a/src/ldump.c +++ b/src/ldump.c @@ -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; diff --git a/src/lfunc.c b/src/lfunc.c index 1a1a8bb..4fd27fe 100644 --- a/src/lfunc.c +++ b/src/lfunc.c @@ -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 */ @@ -21,18 +21,15 @@ 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. diff --git a/src/lfunc.h b/src/lfunc.h index da18923..e236a71 100644 --- a/src/lfunc.h +++ b/src/lfunc.h @@ -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 */ @@ -20,12 +20,11 @@ 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); @@ -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 */ @@ -24,34 +24,40 @@ -/* 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 */ @@ -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 */ @@ -25,6 +25,14 @@ */ + +/* 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 */ @@ -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; } diff --git a/src/llimits.h b/src/llimits.h index 48dc81f..fc9de1a 100644 --- a/src/llimits.h +++ b/src/llimits.h @@ -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 /* } */ diff --git a/src/lmathlib.c b/src/lmathlib.c index b17237f..c3c605e 100644 --- a/src/lmathlib.c +++ b/src/lmathlib.c @@ -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 */ @@ -17,17 +17,17 @@ #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))); @@ -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; } diff --git a/src/loadlib.c b/src/loadlib.c index 783bc12..a995927 100644 --- a/src/loadlib.c +++ b/src/loadlib.c @@ -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' */ diff --git a/src/lobject.h b/src/lobject.h index 06246bf..ca75a02 100644 --- a/src/lobject.h +++ b/src/lobject.h @@ -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 @@ -49,6 +52,12 @@ #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; diff --git a/src/lopcodes.c b/src/lopcodes.c index 2e34676..ef73692 100644 --- a/src/lopcodes.c +++ b/src/lopcodes.c @@ -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 */ diff --git a/src/loslib.c b/src/loslib.c index 881667d..489755b 100644 --- a/src/loslib.c +++ b/src/loslib.c @@ -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 */ @@ -26,11 +26,12 @@ #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 diff --git a/src/lparser.c b/src/lparser.c index 4d68936..b3eb3ca 100644 --- a/src/lparser.c +++ b/src/lparser.c @@ -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 */ } diff --git a/src/lparser.h b/src/lparser.h index caabf46..301167d 100644 --- a/src/lparser.h +++ b/src/lparser.h @@ -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 diff --git a/src/lstate.c b/src/lstate.c index 6e2801c..3c00c28 100644 --- a/src/lstate.c +++ b/src/lstate.c @@ -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 @@ -38,7 +39,18 @@ #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); diff --git a/src/lstate.h b/src/lstate.h index 4743d74..29f810b 100644 --- a/src/lstate.h +++ b/src/lstate.h @@ -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)) diff --git a/src/lstring.c b/src/lstring.c index adec415..8b959f1 100644 --- a/src/lstring.c +++ b/src/lstring.c @@ -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 */ @@ -18,7 +18,49 @@ #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)); } diff --git a/src/lstring.h b/src/lstring.h index d708a1b..d312ff3 100644 --- a/src/lstring.h +++ b/src/lstring.h @@ -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 */ @@ -23,11 +23,20 @@ /* -** 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); diff --git a/src/lstrlib.c b/src/lstrlib.c index f5d61fd..e13098b 100644 --- a/src/lstrlib.c +++ b/src/lstrlib.c @@ -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': diff --git a/src/ltable.c b/src/ltable.c index 9581add..ffa5ecb 100644 --- a/src/ltable.c +++ b/src/ltable.c @@ -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 */ @@ -48,10 +48,10 @@ #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); @@ -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 */ @@ -45,13 +45,13 @@ */ #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 @@ -66,19 +66,19 @@ #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); } @@ -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 @@ -19,11 +19,11 @@ #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 diff --git a/src/luaconf.h.in b/src/luaconf.h.in index 2bae837..1ed8943 100644 --- a/src/luaconf.h.in +++ b/src/luaconf.h.in @@ -44,6 +44,41 @@ #cmakedefine LUA_USE_ULONGJMP +#if defined(LUA_USE_LINUX) +#define LUA_USE_POSIX +#define LUA_USE_DLOPEN /* needs an extra library: -ldl */ +#define LUA_USE_READLINE /* needs some extra libraries */ +#define LUA_USE_STRTODHEX /* assume 'strtod' handles hexa formats */ +#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ +#define LUA_USE_LONGLONG /* assume support for long long */ +#endif + +#if defined(LUA_USE_MACOSX) +#define LUA_USE_POSIX +#define LUA_USE_DLOPEN /* does not need -ldl */ +#define LUA_USE_READLINE /* needs an extra library: -lreadline */ +#define LUA_USE_STRTODHEX /* assume 'strtod' handles hexa formats */ +#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ +#define LUA_USE_LONGLONG /* assume support for long long */ +#endif + + + +/* +@@ LUA_USE_POSIX includes all functionality listed as X/Open System +@* Interfaces Extension (XSI). +** CHANGE it (define it) if your system is XSI compatible. +*/ +#if defined(LUA_USE_POSIX) +#define LUA_USE_MKSTEMP +#define LUA_USE_ISATTY +#define LUA_USE_POPEN +#define LUA_USE_ULONGJMP +#define LUA_USE_GMTIME_R +#endif + + + /* @@ LUA_PATH_DEFAULT is the default path that Lua uses to look for @* Lua libraries. @@ -53,20 +88,44 @@ ** hierarchy or if you want to install your libraries in ** non-conventional directories. */ -#cmakedefine LUA_MODULE_SUFFIX "@LUA_MODULE_SUFFIX@" -#cmakedefine LUA_DIR "@LUA_DIR@" -#cmakedefine LUA_LDIR "@LUA_LDIR@" -#cmakedefine LUA_CDIR "@LUA_CDIR@" +#if defined(_WIN32) /* { */ +/* +** In Windows, any exclamation mark ('!') in the path is replaced by the +** path of the directory of the executable file of the current process. +*/ +#define LUA_LDIR "!\\lua\\" +#define LUA_CDIR "!\\" +#define LUA_PATH_DEFAULT \ + LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" ".\\?.lua" +#define LUA_CPATH_DEFAULT \ + LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll;" ".\\?.dll" + +#else /* }{ */ + +#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR "/" +#define LUA_ROOT "/usr/local/" +#define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR +#define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR +#define LUA_PATH_DEFAULT \ + LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" "./?.lua" +#define LUA_CPATH_DEFAULT \ + LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so" +#endif /* } */ -#define LUA_PATH_DEFAULT "@LUA_PATH_DEFAULT@" -#define LUA_CPATH_DEFAULT "@LUA_CPATH_DEFAULT@" /* @@ LUA_DIRSEP is the directory separator (for submodules). ** CHANGE it if your machine does not use "/" as the directory separator ** and is not Windows. (On Windows Lua automatically uses "\".) */ -#cmakedefine LUA_DIRSEP "@LUA_DIRSEP@" +#if defined(_WIN32) +#define LUA_DIRSEP "\\" +#else +#define LUA_DIRSEP "/" +#endif + /* @@ LUA_ENV is the name of the variable that holds the current @@ -182,7 +241,6 @@ ** You can define it to get all options, or change specific options ** to fit your specific needs. */ -#cmakedefine LUA_COMPAT_ALL #if defined(LUA_COMPAT_ALL) /* { */ /* diff --git a/src/lundump.c b/src/lundump.c index 80c7aa3..54de011 100644 --- a/src/lundump.c +++ b/src/lundump.c @@ -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') diff --git a/src/lundump.h b/src/lundump.h index b63993f..2b8acce 100644 --- a/src/lundump.h +++ b/src/lundump.h @@ -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); @@ -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; @@ -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 */ |