diff options
author | Peter Drahoš <pd@pride.local> | 2015-12-15 23:58:07 +0100 |
---|---|---|
committer | Peter Drahoš <pd@pride.local> | 2015-12-15 23:58:07 +0100 |
commit | 991244c4fc3cb151b3203a96d2b0cc70cfda39ab (patch) | |
tree | be8a0647b35586b5abc5ace79b75258d9c7a12cc | |
parent | e60f74217c216a6cbb1ee3b7c0b8cb95c07c7f68 (diff) | |
download | lua-991244c4fc3cb151b3203a96d2b0cc70cfda39ab.tar.gz |
Updated to lua-5.3.1
-rw-r--r-- | Makefile | 276 | ||||
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | dist.info | 2 | ||||
-rw-r--r-- | doc/contents.html | 37 | ||||
-rw-r--r-- | doc/index.css | 21 | ||||
-rw-r--r-- | doc/lua.css | 106 | ||||
-rw-r--r-- | doc/manual.css | 14 | ||||
-rw-r--r-- | doc/manual.html | 372 | ||||
-rw-r--r-- | doc/readme.html | 36 | ||||
-rw-r--r-- | src/Makefile | 60 | ||||
-rw-r--r-- | src/lapi.c | 123 | ||||
-rw-r--r-- | src/lapi.h | 6 | ||||
-rw-r--r-- | src/lauxlib.c | 4 | ||||
-rw-r--r-- | src/lbaselib.c | 4 | ||||
-rw-r--r-- | src/lcode.c | 17 | ||||
-rw-r--r-- | src/ldblib.c | 21 | ||||
-rw-r--r-- | src/ldebug.c | 66 | ||||
-rw-r--r-- | src/ldebug.h | 7 | ||||
-rw-r--r-- | src/ldo.c | 26 | ||||
-rw-r--r-- | src/ldo.h | 4 | ||||
-rw-r--r-- | src/ldump.c | 7 | ||||
-rw-r--r-- | src/lfunc.h | 9 | ||||
-rw-r--r-- | src/lgc.c | 46 | ||||
-rw-r--r-- | src/liolib.c | 15 | ||||
-rw-r--r-- | src/llex.c | 28 | ||||
-rw-r--r-- | src/llimits.h | 107 | ||||
-rw-r--r-- | src/lmathlib.c | 5 | ||||
-rw-r--r-- | src/lmem.c | 11 | ||||
-rw-r--r-- | src/loadlib.c | 7 | ||||
-rw-r--r-- | src/lobject.c | 41 | ||||
-rw-r--r-- | src/lobject.h | 35 | ||||
-rw-r--r-- | src/loslib.c | 74 | ||||
-rw-r--r-- | src/lstate.c | 10 | ||||
-rw-r--r-- | src/lstate.h | 4 | ||||
-rw-r--r-- | src/lstring.c | 72 | ||||
-rw-r--r-- | src/lstring.h | 5 | ||||
-rw-r--r-- | src/lstrlib.c | 124 | ||||
-rw-r--r-- | src/ltable.c | 123 | ||||
-rw-r--r-- | src/ltablib.c | 8 | ||||
-rw-r--r-- | src/ltm.c | 5 | ||||
-rw-r--r-- | src/lua.c | 36 | ||||
-rw-r--r-- | src/lua.h | 13 | ||||
-rw-r--r-- | src/luac.c | 6 | ||||
-rw-r--r-- | src/luaconf.h.in | 212 | ||||
-rw-r--r-- | src/luaconf.h.orig | 211 | ||||
-rw-r--r-- | src/lutf8lib.c | 13 | ||||
-rw-r--r-- | src/lvm.c | 256 | ||||
-rw-r--r-- | src/lvm.h | 16 |
48 files changed, 1581 insertions, 1122 deletions
@@ -1,162 +1,114 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Unix Makefiles" Generator, CMake Version 3.4 - -# Default target executed when no arguments are given to make. -default_target: all - -.PHONY : default_target - -# Allow only one "make -f Makefile2" at a time, but pass parallelism. -.NOTPARALLEL: - - -#============================================================================= -# Special targets provided by cmake. - -# Disable implicit rules so canonical targets will work. -.SUFFIXES: - - -# Remove some rules from gmake that .SUFFIXES does not remove. -SUFFIXES = - -.SUFFIXES: .hpux_make_needs_suffix_list - - -# Suppress display of executed commands. -$(VERBOSE).SILENT: - - -# A target that is always out of date. -cmake_force: - -.PHONY : cmake_force - -#============================================================================= -# Set environment variables for the build. - -# The shell in which to execute make rules. -SHELL = /bin/sh - -# The CMake executable. -CMAKE_COMMAND = /usr/local/Cellar/cmake/3.4.0/bin/cmake - -# The command to remove a file. -RM = /usr/local/Cellar/cmake/3.4.0/bin/cmake -E remove -f - -# Escaping for special characters. -EQUALS = = - -# The top-level source directory on which CMake was run. -CMAKE_SOURCE_DIR = /Users/pd/Documents/Projects/LuaDist/Repository - -# The top-level build directory on which CMake was run. -CMAKE_BINARY_DIR = /Users/pd/Documents/Projects/LuaDist/Repository/lua - -#============================================================================= -# Targets provided globally by CMake. - -# Special rule for the target edit_cache -edit_cache: - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..." - /usr/local/Cellar/cmake/3.4.0/bin/ccmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) -.PHONY : edit_cache - -# Special rule for the target edit_cache -edit_cache/fast: edit_cache - -.PHONY : edit_cache/fast - -# Special rule for the target rebuild_cache -rebuild_cache: - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." - /usr/local/Cellar/cmake/3.4.0/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) -.PHONY : rebuild_cache - -# Special rule for the target rebuild_cache -rebuild_cache/fast: rebuild_cache - -.PHONY : rebuild_cache/fast - -# The main all target -all: cmake_check_build_system - $(CMAKE_COMMAND) -E cmake_progress_start /Users/pd/Documents/Projects/LuaDist/Repository/lua/CMakeFiles /Users/pd/Documents/Projects/LuaDist/Repository/lua/CMakeFiles/progress.marks - $(MAKE) -f CMakeFiles/Makefile2 all - $(CMAKE_COMMAND) -E cmake_progress_start /Users/pd/Documents/Projects/LuaDist/Repository/lua/CMakeFiles 0 -.PHONY : all - -# The main clean target -clean: - $(MAKE) -f CMakeFiles/Makefile2 clean -.PHONY : clean - -# The main clean target -clean/fast: clean - -.PHONY : clean/fast - -# Prepare targets for installation. -preinstall: all - $(MAKE) -f CMakeFiles/Makefile2 preinstall -.PHONY : preinstall - -# Prepare targets for installation. -preinstall/fast: - $(MAKE) -f CMakeFiles/Makefile2 preinstall -.PHONY : preinstall/fast - -# clear depends -depend: - $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 -.PHONY : depend - -#============================================================================= -# Target rules for targets named bootstrap - -# Build rule for target. -bootstrap: cmake_check_build_system - $(MAKE) -f CMakeFiles/Makefile2 bootstrap -.PHONY : bootstrap - -# fast build rule for target. -bootstrap/fast: - $(MAKE) -f CMakeFiles/bootstrap.dir/build.make CMakeFiles/bootstrap.dir/build -.PHONY : bootstrap/fast - -#============================================================================= -# Target rules for targets named install - -# Build rule for target. -install: cmake_check_build_system - $(MAKE) -f CMakeFiles/Makefile2 install -.PHONY : install - -# fast build rule for target. -install/fast: - $(MAKE) -f CMakeFiles/install.dir/build.make CMakeFiles/install.dir/build -.PHONY : install/fast - -# Help Target -help: - @echo "The following are some of the valid targets for this Makefile:" - @echo "... all (the default if no target is provided)" - @echo "... clean" - @echo "... depend" - @echo "... edit_cache" - @echo "... rebuild_cache" - @echo "... install" - @echo "... bootstrap" -.PHONY : help - - - -#============================================================================= -# Special targets to cleanup operation of make. - -# Special rule to run CMake to check the build system integrity. -# No rule that depends on this can have commands that come from listfiles -# because they might be regenerated. -cmake_check_build_system: - $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 -.PHONY : cmake_check_build_system - +# Makefile for installing Lua +# See doc/readme.html for installation and customization instructions. + +# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT ======================= + +# Your platform. See PLATS for possible values. +PLAT= none + +# Where to install. The installation starts in the src and doc directories, +# so take care if INSTALL_TOP is not an absolute path. See the local target. +# You may want to make INSTALL_LMOD and INSTALL_CMOD consistent with +# LUA_ROOT, LUA_LDIR, and LUA_CDIR in luaconf.h. +INSTALL_TOP= /usr/local +INSTALL_BIN= $(INSTALL_TOP)/bin +INSTALL_INC= $(INSTALL_TOP)/include +INSTALL_LIB= $(INSTALL_TOP)/lib +INSTALL_MAN= $(INSTALL_TOP)/man/man1 +INSTALL_LMOD= $(INSTALL_TOP)/share/lua/$V +INSTALL_CMOD= $(INSTALL_TOP)/lib/lua/$V + +# How to install. If your install program does not support "-p", then +# you may have to run ranlib on the installed liblua.a. +INSTALL= install -p +INSTALL_EXEC= $(INSTALL) -m 0755 +INSTALL_DATA= $(INSTALL) -m 0644 +# +# If you don't have "install" you can use "cp" instead. +# INSTALL= cp -p +# INSTALL_EXEC= $(INSTALL) +# INSTALL_DATA= $(INSTALL) + +# Other utilities. +MKDIR= mkdir -p +RM= rm -f + +# == END OF USER SETTINGS -- NO NEED TO CHANGE ANYTHING BELOW THIS LINE ======= + +# Convenience platforms targets. +PLATS= aix bsd c89 freebsd generic linux macosx mingw posix solaris + +# What to install. +TO_BIN= lua luac +TO_INC= lua.h luaconf.h lualib.h lauxlib.h lua.hpp +TO_LIB= liblua.a +TO_MAN= lua.1 luac.1 + +# Lua version and release. +V= 5.3 +R= $V.1 + +# Targets start here. +all: $(PLAT) + +$(PLATS) clean: + cd src && $(MAKE) $@ + +test: dummy + src/lua -v + +install: dummy + cd src && $(MKDIR) $(INSTALL_BIN) $(INSTALL_INC) $(INSTALL_LIB) $(INSTALL_MAN) $(INSTALL_LMOD) $(INSTALL_CMOD) + cd src && $(INSTALL_EXEC) $(TO_BIN) $(INSTALL_BIN) + cd src && $(INSTALL_DATA) $(TO_INC) $(INSTALL_INC) + cd src && $(INSTALL_DATA) $(TO_LIB) $(INSTALL_LIB) + cd doc && $(INSTALL_DATA) $(TO_MAN) $(INSTALL_MAN) + +uninstall: + cd src && cd $(INSTALL_BIN) && $(RM) $(TO_BIN) + cd src && cd $(INSTALL_INC) && $(RM) $(TO_INC) + cd src && cd $(INSTALL_LIB) && $(RM) $(TO_LIB) + cd doc && cd $(INSTALL_MAN) && $(RM) $(TO_MAN) + +local: + $(MAKE) install INSTALL_TOP=../install + +none: + @echo "Please do 'make PLATFORM' where PLATFORM is one of these:" + @echo " $(PLATS)" + @echo "See doc/readme.html for complete instructions." + +# make may get confused with test/ and install/ +dummy: + +# echo config parameters +echo: + @cd src && $(MAKE) -s echo + @echo "PLAT= $(PLAT)" + @echo "V= $V" + @echo "R= $R" + @echo "TO_BIN= $(TO_BIN)" + @echo "TO_INC= $(TO_INC)" + @echo "TO_LIB= $(TO_LIB)" + @echo "TO_MAN= $(TO_MAN)" + @echo "INSTALL_TOP= $(INSTALL_TOP)" + @echo "INSTALL_BIN= $(INSTALL_BIN)" + @echo "INSTALL_INC= $(INSTALL_INC)" + @echo "INSTALL_LIB= $(INSTALL_LIB)" + @echo "INSTALL_MAN= $(INSTALL_MAN)" + @echo "INSTALL_LMOD= $(INSTALL_LMOD)" + @echo "INSTALL_CMOD= $(INSTALL_CMOD)" + @echo "INSTALL_EXEC= $(INSTALL_EXEC)" + @echo "INSTALL_DATA= $(INSTALL_DATA)" + +# echo pkg-config data +pc: + @echo "version=$R" + @echo "prefix=$(INSTALL_TOP)" + @echo "libdir=$(INSTALL_LIB)" + @echo "includedir=$(INSTALL_INC)" + +# list targets that do not create files (but not all makes understand .PHONY) +.PHONY: all $(PLATS) clean test install local none dummy echo pecho lecho + +# (end of Makefile) @@ -1,5 +1,5 @@ -This is Lua 5.3.0, released on 06 Jan 2015. +This is Lua 5.3.1, released on 10 Jun 2015. 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.3.0" +version = "5.3.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 e59e421..1272c59 100644 --- a/doc/contents.html +++ b/doc/contents.html @@ -3,35 +3,34 @@ <HEAD> <TITLE>Lua 5.3 Reference Manual - contents</TITLE> <LINK REL="stylesheet" TYPE="text/css" HREF="lua.css"> +<LINK REL="stylesheet" TYPE="text/css" HREF="index.css"> <META HTTP-EQUIV="content-type" CONTENT="text/html; charset=iso-8859-1"> -<STYLE TYPE="text/css"> -ul { - list-style-type: none ; - list-style-position: outside ; -} -</STYLE> </HEAD> <BODY> -<HR> <H1> -<A HREF="http://www.lua.org/"><IMG SRC="logo.gif" ALT="" BORDER=0></A> +<A HREF="http://www.lua.org/"><IMG SRC="logo.gif" ALT="Lua"></A> Lua 5.3 Reference Manual </H1> <P> The reference manual is the official definition of the Lua language. +<BR> For a complete introduction to Lua programming, see the book <A HREF="http://www.lua.org/pil/">Programming in Lua</A>. -<P> +<DIV CLASS="menubar"> <A HREF="manual.html">start</A> · <A HREF="#contents">contents</A> · <A HREF="#index">index</A> -<HR> +· +<A HREF="http://www.lua.org/manual/">other versions</A> +</DIV> + +<P> <SMALL> Copyright © 2015 Lua.org, PUC-Rio. Freely available under the terms of the @@ -39,7 +38,7 @@ Freely available under the terms of the </SMALL> <H2><A NAME="contents">Contents</A></H2> -<UL style="padding: 0"> +<UL CLASS="contents menubar"> <LI><A HREF="manual.html">1 – Introduction</A> <P> <LI><A HREF="manual.html#2">2 – Basic Concepts</A> @@ -136,15 +135,14 @@ Freely available under the terms of the </UL> <H2><A NAME="index">Index</A></H2> -<TABLE WIDTH="100%"> -<TR VALIGN="top"> +<TABLE CLASS="menubar" WIDTH="100%"> +<TR> <TD> <H3><A NAME="functions">Lua functions</A></H3> <P> <A HREF="manual.html#6.1">basic</A><BR> <A HREF="manual.html#pdf-_G">_G</A><BR> <A HREF="manual.html#pdf-_VERSION">_VERSION</A><BR> - <A HREF="manual.html#pdf-assert">assert</A><BR> <A HREF="manual.html#pdf-collectgarbage">collectgarbage</A><BR> <A HREF="manual.html#pdf-dofile">dofile</A><BR> @@ -321,6 +319,7 @@ Freely available under the terms of the <A HREF="manual.html#pdf-utf8.offset">utf8.offset</A><BR> <H3><A NAME="env">environment<BR>variables</A></H3> +<P> <A HREF="manual.html#pdf-LUA_CPATH">LUA_CPATH</A><BR> <A HREF="manual.html#pdf-LUA_CPATH_5_3">LUA_CPATH_5_3</A><BR> <A HREF="manual.html#pdf-LUA_INIT">LUA_INIT</A><BR> @@ -546,6 +545,7 @@ Freely available under the terms of the <A HREF="manual.html#pdf-luaopen_utf8">luaopen_utf8</A><BR> <H3><A NAME="constants">constants</A></H3> +<P> <A HREF="manual.html#pdf-LUA_ERRERR">LUA_ERRERR</A><BR> <A HREF="manual.html#pdf-LUA_ERRFILE">LUA_ERRFILE</A><BR> <A HREF="manual.html#pdf-LUA_ERRGCMM">LUA_ERRGCMM</A><BR> @@ -606,13 +606,12 @@ Freely available under the terms of the </TR> </TABLE> -<HR> -<SMALL CLASS="footer"> +<P CLASS="footer"> Last update: -Tue Dec 9 21:26:07 BRST 2014 -</SMALL> +Wed Jun 3 08:27:30 BRT 2015 +</P> <!-- -Last change: updated for Lua 5.3.0 (final) +Last change: revised for Lua 5.3.1 --> </BODY> diff --git a/doc/index.css b/doc/index.css new file mode 100644 index 0000000..c961835 --- /dev/null +++ b/doc/index.css @@ -0,0 +1,21 @@ +ul { + list-style-type: none ; +} + +ul.contents { + padding: 0 ; +} + +table { + border: none ; + border-spacing: 0 ; + border-collapse: collapse ; +} + +td { + vertical-align: top ; + padding: 0 ; + text-align: left ; + line-height: 1.25 ; + width: 15% ; +} diff --git a/doc/lua.css b/doc/lua.css index 3199a2b..b614f3c 100644 --- a/doc/lua.css +++ b/doc/lua.css @@ -3,84 +3,90 @@ html { } body { - border: solid #a0a0a0 1px ; - border-radius: 20px ; - padding: 26px ; - margin: 16px ; - color: #000000 ; background-color: #FFFFFF ; + color: #000000 ; font-family: Helvetica, Arial, sans-serif ; text-align: justify ; + line-height: 1.25 ; + margin: 16px auto ; + padding: 32px ; + border: solid #a0a0a0 1px ; + border-radius: 20px ; + max-width: 70em ; + width: 90% ; } h1, h2, h3, h4 { + color: #000080 ; font-family: Verdana, Geneva, sans-serif ; font-weight: normal ; font-style: normal ; + text-align: left ; } -h2 { - padding-top: 0.4em ; - padding-bottom: 0.4em ; - padding-left: 0.8em ; - padding-right: 0.8em ; - background-color: #D0D0FF ; - border-radius: 8px ; - border: solid #a0a0a0 1px ; +h1 { + font-size: 28pt ; } -h3 { - padding-left: 0.5em ; - border-left: solid #D0D0FF 1em ; +h1 img { + vertical-align: text-bottom ; } -table h3 { - padding-left: 0px ; - border-left: none ; +h2:before { + content: "\2756" ; + padding-right: 0.5em ; } -a:link { - color: #000080 ; - background-color: inherit ; +a { text-decoration: none ; } -a:visited { - background-color: inherit ; - text-decoration: none ; +a:link { + color: #000080 ; } a:link:hover, a:visited:hover { - color: #000080 ; background-color: #D0D0FF ; - border-radius: 4px; + color: #000080 ; + border-radius: 4px ; } a:link:active, a:visited:active { color: #FF0000 ; } -h1 a img { - vertical-align: text-bottom ; +div.menubar { + padding-bottom: 0.5em ; } -hr { - border: 0 ; - height: 1px ; - color: #a0a0a0 ; - background-color: #a0a0a0 ; - display: none ; +p.menubar { + margin-left: 2.5em ; } -table hr { - display: block ; +.menubar a:hover { + margin: -3px -3px -3px -3px ; + padding: 3px 3px 3px 3px ; + border-radius: 4px ; } :target { - background-color: #F8F8F8 ; + background-color: #F0F0F0 ; + margin: -8px ; padding: 8px ; - border: solid #a0a0a0 2px ; border-radius: 8px ; + outline: none ; +} + +hr { + display: none ; +} + +table hr { + background-color: #a0a0a0 ; + color: #a0a0a0 ; + border: 0 ; + height: 1px ; + display: block ; } .footer { @@ -103,3 +109,25 @@ pre.session { padding: 1em ; border-radius: 8px ; } + +td.gutter { + width: 4% ; +} + +table.columns { + border: none ; + border-spacing: 0 ; + border-collapse: collapse ; +} + +table.columns td { + vertical-align: top ; + padding: 0 ; + padding-bottom: 1em ; + text-align: justify ; + line-height: 1.25 ; +} + +p.logos a:link:hover, p.logos a:visited:hover { + background-color: inherit ; +} diff --git a/doc/manual.css b/doc/manual.css index ca613cd..aa0e677 100644 --- a/doc/manual.css +++ b/doc/manual.css @@ -8,20 +8,14 @@ pre, code { } span.apii { + color: gray ; float: right ; font-family: inherit ; font-style: normal ; font-size: small ; - color: gray ; } -p+h1, ul+h1 { - font-style: normal ; - padding-top: 0.4em ; - padding-bottom: 0.4em ; - padding-left: 16px ; - margin-left: -16px ; - background-color: #D0D0FF ; - border-radius: 8px ; - border: solid #000080 1px ; +h2:before { + content: "" ; + padding-right: 0em ; } diff --git a/doc/manual.html b/doc/manual.html index 5ed8f06..f2eb313 100644 --- a/doc/manual.html +++ b/doc/manual.html @@ -1,39 +1,41 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html> - -<head> -<title>Lua 5.3 Reference Manual</title> -<link rel="stylesheet" type="text/css" href="lua.css"> -<link rel="stylesheet" type="text/css" href="manual.css"> +<HTML> +<HEAD> +<TITLE>Lua 5.3 Reference Manual</TITLE> +<LINK REL="stylesheet" TYPE="text/css" HREF="lua.css"> +<LINK REL="stylesheet" TYPE="text/css" HREF="manual.css"> <META HTTP-EQUIV="content-type" CONTENT="text/html; charset=iso-8859-1"> -</head> +</HEAD> -<body> +<BODY> -<hr> -<h1> -<a href="http://www.lua.org/"><img src="logo.gif" alt="" border="0"></a> +<H1> +<A HREF="http://www.lua.org/"><IMG SRC="logo.gif" ALT="Lua"></A> Lua 5.3 Reference Manual -</h1> +</H1> +<P> by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes -<p> -<small> + +<P> +<SMALL> Copyright © 2015 Lua.org, PUC-Rio. Freely available under the terms of the <a href="http://www.lua.org/license.html">Lua license</a>. -</small> -<hr> -<p> +</SMALL> -<a href="contents.html#contents">contents</A> +<DIV CLASS="menubar"> +<A HREF="contents.html#contents">contents</A> +· +<A HREF="contents.html#index">index</A> · -<a href="contents.html#index">index</A> +<A HREF="http://www.lua.org/manual/">other versions</A> +</DIV> <!-- ====================================================================== --> <p> -<!-- $Id: manual.of,v 1.146 2015/01/06 11:23:01 roberto Exp $ --> +<!-- $Id: manual.of,v 1.151 2015/06/10 21:08:57 roberto Exp $ --> @@ -113,15 +115,15 @@ There are eight basic types in Lua: <em>nil</em>, <em>boolean</em>, <em>number</em>, <em>string</em>, <em>function</em>, <em>userdata</em>, <em>thread</em>, and <em>table</em>. -<em>Nil</em> is the type of the value <b>nil</b>, +The type <em>nil</em> has one single value, <b>nil</b>, whose main property is to be different from any other value; it usually represents the absence of a useful value. -<em>Boolean</em> is the type of the values <b>false</b> and <b>true</b>. +The type <em>boolean</em> has two values, <b>false</b> and <b>true</b>. Both <b>nil</b> and <b>false</b> make a condition false; any other value makes it true. -<em>Number</em> represents both +The type <em>number</em> represents both integer numbers and real (floating-point) numbers. -<em>String</em> represents immutable sequences of bytes. +The type <em>string</em> represents immutable sequences of bytes. Lua is 8-bit clean: strings can contain any 8-bit value, @@ -132,6 +134,7 @@ it makes no assumptions about the contents of a string. <p> The type <em>number</em> uses two internal representations, +or two subtypes, one called <em>integer</em> and the other called <em>float</em>. Lua has explicit rules about when each representation is used, but it also converts between them automatically as needed (see <a href="#3.4.3">§3.4.3</a>). @@ -142,7 +145,7 @@ or to assume complete control over the representation of each number. Standard Lua uses 64-bit integers and double-precision (64-bit) floats, but you can also compile Lua so that it uses 32-bit integers and/or single-precision (32-bit) floats. -The option with 32 bits for both integers and floats +The option with 32 bits for both integers and floats is particularly attractive for small machines and embedded systems. (See macro <code>LUA_32BITS</code> in file <code>luaconf.h</code>.) @@ -185,8 +188,8 @@ even those that do not support threads natively. The type <em>table</em> implements associative arrays, that is, arrays that can be indexed not only with numbers, but with any Lua value except <b>nil</b> and NaN. -(<em>Not a Number</em> is a special numeric value used to represent -undefined or unrepresentable results, such as <code>0/0</code>.) +(<em>Not a Number</em> is a special value used to represent +undefined or unrepresentable numerical results, such as <code>0/0</code>.) Tables can be <em>heterogeneous</em>; that is, they can contain values of all types (except <b>nil</b>). Any key with value <b>nil</b> is not considered part of the table. @@ -393,7 +396,7 @@ using the <a href="#pdf-getmetatable"><code>getmetatable</code></a> function. <p> You can replace the metatable of tables using the <a href="#pdf-setmetatable"><code>setmetatable</code></a> function. -You cannot change the metatable of other types from Lua +You cannot change the metatable of other types from Lua code (except by using the debug library (<a href="#6.10">§6.10</a>)); you must use the C API for that. @@ -425,12 +428,7 @@ for instance, the key for operation "add" is the string "<code>__add</code>". Note that queries for metamethods are always raw; the access to a metamethod does not invoke other metamethods. -You can emulate how Lua queries a metamethod for an object <code>obj</code> -with the following code: -<pre> - rawget(getmetatable(obj) or {}, "__" .. event_name) -</pre> <p> For the unary operators (negation, length, and bitwise not), @@ -510,7 +508,7 @@ the <code>&</code> (bitwise and) operation. Behavior similar to the "add" operation, except that Lua will try a metamethod -if any operator is neither an integer +if any operand is neither an integer nor a value coercible to an integer (see <a href="#3.4.3">§3.4.3</a>). </li> @@ -549,7 +547,7 @@ the <code>..</code> (concatenation) operation. Behavior similar to the "add" operation, except that Lua will try a metamethod -if any operator is neither a string nor a number +if any operand is neither a string nor a number (which is always coercible to a string). </li> @@ -599,6 +597,8 @@ then it will try the "<code>__lt</code>" event, assuming that <code>a <= b</code> is equivalent to <code>not (b < a)</code>. As with the other comparison operators, the result is always a boolean. +(This use of the "<code>__lt</code>" event can be removed in future versions; +it is also slower than a real "<code>__le</code>" metamethod.) </li> <li><b>"index": </b> @@ -661,6 +661,13 @@ followed by the arguments of the original call (<code>args</code>). </ul> +<p> +It is a good practice to add all needed metamethods to a table +before setting it as a metatable of some object. +In particular, the "<code>__gc</code>" metamethod works only when this order +is followed (see <a href="#2.5.1">§2.5.1</a>). + + @@ -752,8 +759,6 @@ and the metatable has a field indexed by the string "<code>__gc</code>". Note that if you set a metatable without a <code>__gc</code> field and later create that field in the metatable, the object will not be marked for finalization. -However, after an object has been marked, -you can freely change the <code>__gc</code> field of its metatable. <p> @@ -794,7 +799,7 @@ Moreover, if the finalizer marks a finalizing object for finalization again, its finalizer will be called again in the next cycle where the object is unreachable. In any case, -the object memory is freed only in the GC cycle where +the object memory is freed only in a GC cycle where the object is unreachable and not marked for finalization. @@ -822,8 +827,8 @@ then the garbage collector will collect that object. <p> A weak table can have weak keys, weak values, or both. -A table with weak keys allows the collection of its keys, -but prevents the collection of its values. +A table with weak values allows the collection of its values, +but prevents the collection of its keys. A table with both weak keys and weak values allows the collection of both keys and values. In any case, if either the key or the value is collected, @@ -913,10 +918,10 @@ You execute a coroutine by calling <a href="#pdf-coroutine.resume"><code>corouti When you first call <a href="#pdf-coroutine.resume"><code>coroutine.resume</code></a>, passing as its first argument a thread returned by <a href="#pdf-coroutine.create"><code>coroutine.create</code></a>, -the coroutine starts its execution, -at the first line of its main function. +the coroutine starts its execution by +calling its main function. Extra arguments passed to <a href="#pdf-coroutine.resume"><code>coroutine.resume</code></a> are passed -as arguments to the coroutine's main function. +as arguments to that function. After the coroutine starts running, it runs until it terminates or <em>yields</em>. @@ -1111,7 +1116,7 @@ into the string contents. Strings in Lua can contain any 8-bit value, including embedded zeros, which can be specified as '<code>\0</code>'. More generally, -we can specify any byte in a literal string by its numerical value. +we can specify any byte in a literal string by its numeric value. This can be done with the escape sequence <code>\x<em>XX</em></code>, where <em>XX</em> is a sequence of exactly two hexadecimal digits, @@ -1186,7 +1191,7 @@ the five literal strings below denote the same string: </pre> <p> -A <em>numerical constant</em> (or <em>numeral</em>) +A <em>numeric constant</em> (or <em>numeral</em>) can be written with an optional fractional part and an optional decimal exponent, marked by a letter '<code>e</code>' or '<code>E</code>'. @@ -1581,11 +1586,11 @@ because now <b>return</b> is the last statement in its (inner) block. <p> The <b>for</b> statement has two forms: -one numeric and one generic. +one numerical and one generic. <p> -The numeric <b>for</b> loop repeats a block of code while a +The numerical <b>for</b> loop repeats a block of code while a control variable runs through an arithmetic progression. It has the following syntax: @@ -1879,13 +1884,13 @@ so that it works for non-integer exponents too. <p> Floor division (<code>//</code>) is a division -that rounds the quotient towards minus infinite, +that rounds the quotient towards minus infinity, that is, the floor of the division of its operands. <p> Modulo is defined as the remainder of a division -that rounds the quotient towards minus infinite (floor division). +that rounds the quotient towards minus infinity (floor division). <p> @@ -1972,8 +1977,9 @@ The conversion from strings to numbers goes as follows: First, the string is converted to an integer or a float, following its syntax and the rules of the Lua lexer. (The string may have also leading and trailing spaces and a sign.) -Then, the resulting number is converted to the required type -(float or integer) according to the previous rules. +Then, the resulting number (float or integer) +is converted to the type (float or integer) required by the context +(e.g., the operation that forced the conversion). <p> @@ -2006,11 +2012,7 @@ Equality (<code>==</code>) first compares the type of its operands. If the types are different, then the result is <b>false</b>. Otherwise, the values of the operands are compared. Strings are compared in the obvious way. -Numbers follow the usual rule for binary operations: -if both operands are integers, -they are compared as integers; -otherwise, they are converted to floats -and compared as such. +Numbers are equal if they denote the same mathematical value. <p> @@ -2045,8 +2047,8 @@ The operator <code>~=</code> is exactly the negation of equality (<code>==</code <p> The order operators work as follows. If both arguments are numbers, -then they are compared following -the usual rule for binary operations. +then they are compared according to their mathematical values +(regardless of their subtypes). Otherwise, if both arguments are strings, then their values are compared according to the current locale. Otherwise, Lua tries to call the "lt" or the "le" @@ -2055,6 +2057,12 @@ A comparison <code>a > b</code> is translated to <code>b < a</code> and <code>a >= b</code> is translated to <code>b <= a</code>. +<p> +Following the IEEE 754 standard, +NaN is considered neither smaller than, +nor equal to, nor greater than any value (including itself). + + @@ -2636,29 +2644,22 @@ works only with <em>valid indices</em> or <em>acceptable indices</em>. <p> A <em>valid index</em> is an index that refers to a -real position within the stack, that is, -its position lies between 1 and the stack top -(<code>1 ≤ abs(index) ≤ top</code>). - -Usually, functions that can modify the value at an index -require valid indices. - - -<p> -Unless otherwise noted, -any function that accepts valid indices also accepts <em>pseudo-indices</em>, -which represent some Lua values that are accessible to C code -but which are not in the stack. -Pseudo-indices are used to access the registry +position that stores a modifiable Lua value. +It comprises stack indices between 1 and the stack top +(<code>1 ≤ abs(index) ≤ top</code>) + +plus <em>pseudo-indices</em>, +which represent some positions that are accessible to C code +but that are not in the stack. +Pseudo-indices are used to access the registry (see <a href="#4.5">§4.5</a>) and the upvalues of a C function (see <a href="#4.4">§4.4</a>). <p> -Functions that do not need a specific stack position, -but only a value in the stack (e.g., query functions), +Functions that do not need a specific mutable position, +but only a value (e.g., query functions), can be called with acceptable indices. An <em>acceptable index</em> can be any valid index, -including the pseudo-indices, but it also can be any positive index after the stack top within the space allocated for the stack, that is, indices up to the stack size. @@ -2701,7 +2702,7 @@ Whenever a C function is called, its upvalues are located at specific pseudo-indices. These pseudo-indices are produced by the macro <a href="#lua_upvalueindex"><code>lua_upvalueindex</code></a>. -The first value associated with a function is at position +The first upvalue associated with a function is at index <code>lua_upvalueindex(1)</code>, and so on. Any access to <code>lua_upvalueindex(<em>n</em>)</code>, where <em>n</em> is greater than the number of upvalues of the @@ -2719,8 +2720,7 @@ Lua provides a <em>registry</em>, a predefined table that can be used by any C code to store whatever Lua values it needs to store. The registry table is always located at pseudo-index -<a name="pdf-LUA_REGISTRYINDEX"><code>LUA_REGISTRYINDEX</code></a>, -which is a valid index. +<a name="pdf-LUA_REGISTRYINDEX"><code>LUA_REGISTRYINDEX</code></a>. Any C library can store data into this table, but it must take care to choose keys that are different from those used @@ -2981,7 +2981,8 @@ tells whether the function may raise errors: <pre>int lua_absindex (lua_State *L, int idx);</pre> <p> -Converts the acceptable index <code>idx</code> into an absolute index +Converts the acceptable index <code>idx</code> +into an equivalent absolute index (that is, one that does not depend on the stack top). @@ -3224,7 +3225,7 @@ many results. <p> As an example, the following function receives a variable number -of numerical arguments and returns their average and their sum: +of numeric arguments and returns their average and their sum: <pre> static int foo (lua_State *L) { @@ -3383,8 +3384,9 @@ to write them. <p> If <code>strip</code> is true, -the binary representation is created without debug information -about the function. +the binary representation may not include all debug information +about the function, +to save space. <p> @@ -3661,7 +3663,7 @@ By default this type is <code>long long</code>, (usually a 64-bit two-complement integer), but that can be changed to <code>long</code> or <code>int</code> (usually a 32-bit two-complement integer). -(See <code>LUA_INT</code> in <code>luaconf.h</code>.) +(See <code>LUA_INT_TYPE</code> in <code>luaconf.h</code>.) <p> @@ -3850,7 +3852,7 @@ and 0 otherwise. <p> The type for continuation-function contexts. -It must be a numerical type. +It must be a numeric type. This type is defined as <code>intptr_t</code> when <code>intptr_t</code> is available, so that it can store pointers too. @@ -4068,7 +4070,7 @@ the table during its traversal. <hr><h3><a name="lua_Number"><code>lua_Number</code></a></h3> -<pre>typedef double lua_Number;</pre> +<pre>typedef ... lua_Number;</pre> <p> The type of floats in Lua. @@ -4076,8 +4078,8 @@ The type of floats in Lua. <p> By default this type is double, -but that can be changed to a single float. -(See <code>LUA_REAL</code> in <code>luaconf.h</code>.) +but that can be changed to a single float or a long double. +(See <code>LUA_FLOAT_TYPE</code> in <code>luaconf.h</code>.) @@ -4133,7 +4135,7 @@ then the error message returned on the stack is exactly the original error message. Otherwise, <code>msgh</code> is the stack index of a <em>message handler</em>. -(In the current implementation, this index cannot be a pseudo-index.) +(This index cannot be a pseudo-index.) In case of runtime errors, this function will be called with the error message and its return value will be the message @@ -4267,20 +4269,11 @@ when called, invokes the corresponding C function. <p> -Any function to be registered in Lua must +Any function to be callable by Lua must follow the correct protocol to receive its parameters and return its results (see <a href="#lua_CFunction"><code>lua_CFunction</code></a>). -<p> -<code>lua_pushcfunction</code> is defined as a macro: - -<pre> - #define lua_pushcfunction(L,f) lua_pushcclosure(L,f,0) -</pre><p> -Note that <code>f</code> is used twice. - - @@ -4309,7 +4302,7 @@ The conversion specifiers can only be '<code>%%</code>' (inserts the character '<code>%</code>'), '<code>%s</code>' (inserts a zero-terminated string, with no size restrictions), '<code>%f</code>' (inserts a <a href="#lua_Number"><code>lua_Number</code></a>), -'<code>%L</code>' (inserts a <a href="#lua_Integer"><code>lua_Integer</code></a>), +'<code>%I</code>' (inserts a <a href="#lua_Integer"><code>lua_Integer</code></a>), '<code>%p</code>' (inserts a pointer as a hexadecimal numeral), '<code>%d</code>' (inserts an <code>int</code>), '<code>%c</code>' (inserts an <code>int</code> as a one-byte character), and @@ -4369,9 +4362,8 @@ light userdata with the same C address. <pre>const char *lua_pushliteral (lua_State *L, const char *s);</pre> <p> -This macro is equivalent to <a href="#lua_pushlstring"><code>lua_pushlstring</code></a>, -but can be used only when <code>s</code> is a literal string. -It automatically provides the string length. +This macro is equivalent to <a href="#lua_pushstring"><code>lua_pushstring</code></a>, +but should be used only when <code>s</code> is a literal string. @@ -4598,9 +4590,9 @@ that is, it does not invoke metamethods. <pre>void lua_rawsetp (lua_State *L, int index, const void *p);</pre> <p> -Does the equivalent of <code>t[k] = v</code>, +Does the equivalent of <code>t[p] = v</code>, where <code>t</code> is the table at the given index, -<code>k</code> is the pointer <code>p</code> represented as a light userdata, +<code>p</code> is encoded as a light userdata, and <code>v</code> is the value at the top of the stack. @@ -4672,7 +4664,7 @@ because a pseudo-index is not an actual stack position. <p> Moves the top element into the given valid index without shifting any element -(therefore replacing the value at the given index), +(therefore replacing the value at that given index), and then pops the top element. @@ -4684,7 +4676,7 @@ and then pops the top element. <pre>int lua_resume (lua_State *L, lua_State *from, int nargs);</pre> <p> -Starts and resumes a coroutine in a given thread. +Starts and resumes a coroutine in the given thread <code>L</code>. <p> @@ -4731,12 +4723,16 @@ this parameter can be <code>NULL</code>. <pre>void lua_rotate (lua_State *L, int idx, int n);</pre> <p> -Rotates the stack elements from <code>idx</code> to the top <code>n</code> positions -in the direction of the top, for a positive <code>n</code>, +Rotates the stack elements between the valid index <code>idx</code> +and the top of the stack. +The elements are rotated <code>n</code> positions in the direction of the top, +for a positive <code>n</code>, or <code>-n</code> positions in the direction of the bottom, for a negative <code>n</code>. The absolute value of <code>n</code> must not be greater than the size of the slice being rotated. +This function cannot be called with a pseudo-index, +because a pseudo-index is not an actual stack position. @@ -5072,7 +5068,7 @@ There is no way to convert the pointer back to its original value. <p> -Typically this function is used only for debug information. +Typically this function is used only for hashing and debug information. @@ -5127,7 +5123,7 @@ Returns the type of the value in the given valid index, or <code>LUA_TNONE</code> for a non-valid (but acceptable) index. The types returned by <a href="#lua_type"><code>lua_type</code></a> are coded by the following constants defined in <code>lua.h</code>: -<a name="pdf-LUA_TNIL"><code>LUA_TNIL</code></a>, +<a name="pdf-LUA_TNIL"><code>LUA_TNIL</code></a> (0), <a name="pdf-LUA_TNUMBER"><code>LUA_TNUMBER</code></a>, <a name="pdf-LUA_TBOOLEAN"><code>LUA_TBOOLEAN</code></a>, <a name="pdf-LUA_TSTRING"><code>LUA_TSTRING</code></a>, @@ -5618,24 +5614,26 @@ it returns 0. <pre>const char *lua_getupvalue (lua_State *L, int funcindex, int n);</pre> <p> -Gets information about a closure's upvalue. -(For Lua functions, -upvalues are the external local variables that the function uses, -and that are consequently included in its closure.) -<a href="#lua_getupvalue"><code>lua_getupvalue</code></a> gets the index <code>n</code> of an upvalue, -pushes the upvalue's value onto the stack, +Gets information about the <code>n</code>-th upvalue +of the closure at index <code>funcindex</code>. +It pushes the upvalue's value onto the stack and returns its name. -<code>funcindex</code> points to the closure in the stack. -(Upvalues have no particular order, -as they are active through the whole function. -So, they are numbered in an arbitrary order.) +Returns <code>NULL</code> (and pushes nothing) +when the index <code>n</code> is greater than the number of upvalues. <p> -Returns <code>NULL</code> (and pushes nothing) -when the index is greater than the number of upvalues. For C functions, this function uses the empty string <code>""</code> as a name for all upvalues. +(For Lua functions, +upvalues are the external local variables that the function uses, +and that are consequently included in its closure.) + + +<p> +Upvalues have no particular order, +as they are active through the whole function. +They are numbered in an arbitrary order. @@ -5680,10 +5678,10 @@ that is, they cannot call <a href="#lua_yieldk"><code>lua_yieldk</code></a>, <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. +Only count and line events can yield; +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 +(that is, with no values). @@ -5748,9 +5746,7 @@ A hook is disabled by setting <code>mask</code> to zero. <p> Sets the value of a local variable of a given activation record. -Parameters <code>ar</code> and <code>n</code> are as in <a href="#lua_getlocal"><code>lua_getlocal</code></a> -(see <a href="#lua_getlocal"><code>lua_getlocal</code></a>). -<a href="#lua_setlocal"><code>lua_setlocal</code></a> assigns the value at the top of the stack +It assigns the value at the top of the stack to the variable and returns its name. It also pops the value from the stack. @@ -5761,6 +5757,10 @@ when the index is greater than the number of active local variables. +<p> +Parameters <code>ar</code> and <code>n</code> are as in function <a href="#lua_getlocal"><code>lua_getlocal</code></a>. + + @@ -5773,13 +5773,15 @@ Sets the value of a closure's upvalue. It assigns the value at the top of the stack to the upvalue and returns its name. It also pops the value from the stack. -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>). <p> Returns <code>NULL</code> (and pops nothing) -when the index is greater than the number of upvalues. +when the index <code>n</code> is greater than the number of upvalues. + + +<p> +Parameters <code>funcindex</code> and <code>n</code> are as in function <a href="#lua_getupvalue"><code>lua_getupvalue</code></a>. @@ -5792,9 +5794,6 @@ when the index is greater than the number of upvalues. <p> Returns a unique identifier for the upvalue numbered <code>n</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). <p> @@ -5805,6 +5804,11 @@ Lua closures that share an upvalue will return identical ids for those upvalue indices. +<p> +Parameters <code>funcindex</code> and <code>n</code> are as in function <a href="#lua_getupvalue"><code>lua_getupvalue</code></a>, +but <code>n</code> cannot be greater than the number of upvalues. + + @@ -6367,9 +6371,9 @@ pushes nothing and returns <code>LUA_TNIL</code>. <p> Pushes onto the stack the metatable associated with name <code>tname</code> -in the registry (see <a href="#luaL_newmetatable"><code>luaL_newmetatable</code></a>). -If there is no metatable associated with <code>tname</code>, -returns false and pushes <b>nil</b>. +in the registry (see <a href="#luaL_newmetatable"><code>luaL_newmetatable</code></a>) +(<b>nil</b> if there is no metatable associated with that name). +Returns the type of the pushed value. @@ -7333,7 +7337,7 @@ you can use <code>next(t)</code> to check whether a table is empty. <p> The order in which the indices are enumerated is not specified, <em>even for numeric indices</em>. -(To traverse a table in numeric order, +(To traverse a table in numerical order, use a numerical <b>for</b>.) @@ -7522,8 +7526,6 @@ the function returns <b>nil</b>. <hr><h3><a name="pdf-tostring"><code>tostring (v)</code></a></h3> Receives a value of any type and converts it to a string in a human-readable format. -Floats always produce strings with some -floating-point indication (either a decimal dot or an exponent). (For complete control of how numbers are converted, use <a href="#pdf-string.format"><code>string.format</code></a>.) @@ -7579,8 +7581,8 @@ except that it sets a new message handler <code>msgh</code>. <h2>6.2 – <a name="6.2">Coroutine Manipulation</a></h2> <p> -The operations related to coroutines comprise a sub-library of -the basic library and come inside the table <a name="pdf-coroutine"><code>coroutine</code></a>. +This library comprises the operations to manipulate coroutines, +which come inside the table <a name="pdf-coroutine"><code>coroutine</code></a>. See <a href="#2.6">§2.6</a> for a general description of coroutines. @@ -7590,7 +7592,7 @@ See <a href="#2.6">§2.6</a> for a general description of coroutines. <p> Creates a new coroutine, with body <code>f</code>. -<code>f</code> must be a Lua function. +<code>f</code> must be a function. Returns this new coroutine, an object with type <code>"thread"</code>. @@ -7674,7 +7676,7 @@ or if it has stopped with an error. <p> Creates a new coroutine, with body <code>f</code>. -<code>f</code> must be a Lua function. +<code>f</code> must be a function. Returns a function that resumes the coroutine each time it is called. Any arguments passed to the function behave as the extra arguments to <code>resume</code>. @@ -8073,7 +8075,7 @@ The string library assumes one-byte character encodings. <p> <hr><h3><a name="pdf-string.byte"><code>string.byte (s [, i [, j]])</code></a></h3> -Returns the internal numerical codes of the characters <code>s[i]</code>, +Returns the internal numeric codes of the characters <code>s[i]</code>, <code>s[i+1]</code>, ..., <code>s[j]</code>. The default value for <code>i</code> is 1; the default value for <code>j</code> is <code>i</code>. @@ -8082,7 +8084,7 @@ following the same rules of function <a href="#pdf-string.sub"><code>string.sub< <p> -Numerical codes are not necessarily portable across platforms. +Numeric codes are not necessarily portable across platforms. @@ -8091,12 +8093,12 @@ Numerical codes are not necessarily portable across platforms. <hr><h3><a name="pdf-string.char"><code>string.char (···)</code></a></h3> Receives zero or more integers. Returns a string with length equal to the number of arguments, -in which each character has the internal numerical code equal +in which each character has the internal numeric code equal to its corresponding argument. <p> -Numerical codes are not necessarily portable across platforms. +Numeric codes are not necessarily portable across platforms. @@ -8112,9 +8114,9 @@ of the given function, so that a later <a href="#pdf-load"><code>load</code></a> on this string returns a copy of the function (but with new upvalues). If <code>strip</code> is a true value, -the binary representation is created without debug information -about the function -(local variable names, lines, etc.). +the binary representation may not include all debug information +about the function, +to save space. <p> @@ -8138,7 +8140,7 @@ Looks for the first match of If it finds a match, then <code>find</code> returns the indices of <code>s</code> where this occurrence starts and ends; otherwise, it returns <b>nil</b>. -A third, optional numerical argument <code>init</code> specifies +A third, optional numeric argument <code>init</code> specifies where to start the search; its default value is 1 and can be negative. A value of <b>true</b> as a fourth, optional argument <code>plain</code> @@ -8186,18 +8188,23 @@ may produce the string: <p> Options -<code>A</code> and <code>a</code> (when available), -<code>E</code>, <code>e</code>, <code>f</code>, +<code>A</code>, <code>a</code>, <code>E</code>, <code>e</code>, <code>f</code>, <code>G</code>, and <code>g</code> all expect a number as argument. Options <code>c</code>, <code>d</code>, <code>i</code>, <code>o</code>, <code>u</code>, <code>X</code>, and <code>x</code> expect an integer. -Option <code>q</code> expects a string; -option <code>s</code> expects a string without embedded zeros. -If the argument to option <code>s</code> is not a string, +Option <code>q</code> expects a string. +Option <code>s</code> expects a string without embedded zeros; +if its argument is not a string, it is converted to one following the same rules of <a href="#pdf-tostring"><code>tostring</code></a>. +<p> +When Lua is compiled with a non-C99 compiler, +options <code>A</code> and <code>a</code> (hexadecimal floats) +do not support any modifier (flags, width, length). + + <p> @@ -8344,7 +8351,7 @@ the captures from the pattern; otherwise it returns <b>nil</b>. If <code>pattern</code> specifies no captures, then the whole match is returned. -A third, optional numerical argument <code>init</code> specifies +A third, optional numeric argument <code>init</code> specifies where to start the search; its default value is 1 and can be negative. @@ -8499,7 +8506,7 @@ represents the character <em>x</em> itself. represents the character <em>x</em>. This is the standard way to escape the magic characters. Any non-alphanumeric character -(including all punctuations, even the non-magical) +(including all punctuation characters, even the non-magical) can be preceded by a '<code>%</code>' when used to represent itself in a pattern. </li> @@ -8904,7 +8911,7 @@ multiple assignment: <code>a2[t],··· = a1[f],···,a1[e]</code>. The default for <code>a2</code> is <code>a1</code>. The destination range can overlap with the source range. -Index <code>f</code> must be positive. +The number of elements to be moved must fit in a Lua integer. @@ -9120,7 +9127,7 @@ that rounds the quotient towards zero. (integer/float) <p> The float value <code>HUGE_VAL</code>, -a value larger than any other numerical value. +a value larger than any other numeric value. @@ -9602,16 +9609,12 @@ reads a numeral and returns it as a float or an integer, following the lexical conventions of Lua. (The numeral may have leading spaces and a sign.) This format always reads the longest input sequence that -is a valid prefix for a number; -if that prefix does not form a valid number +is a valid prefix for a numeral; +if that prefix does not form a valid numeral (e.g., an empty string, "<code>0x</code>", or "<code>3.4e-</code>"), it is discarded and the function returns <b>nil</b>. </li> -<li><b>"<code>i</code>": </b> -reads an integral number and returns it as an integer. -</li> - <li><b>"<code>a</code>": </b> reads the whole file, starting at the current position. On end of file, it returns the empty string. @@ -9946,17 +9949,26 @@ because of its reliance on C function <code>setlocale</code>. <p> Returns the current time when called without arguments, -or a time representing the date and time specified by the given table. +or a time representing the local date and time specified by the given table. This table must have fields <code>year</code>, <code>month</code>, and <code>day</code>, and may have fields <code>hour</code> (default is 12), <code>min</code> (default is 0), <code>sec</code> (default is 0), and <code>isdst</code> (default is <b>nil</b>). +Other fields are ignored. For a description of these fields, see the <a href="#pdf-os.date"><code>os.date</code></a> function. <p> +The values in these fields do not need to be inside their valid ranges. +For instance, if <code>sec</code> is -10, +it means -10 seconds from the time specified by the other fields; +if <code>hour</code> is 1000, +it means +1000 hours from the time specified by the other fields. + + +<p> The returned value is a number, whose meaning depends on your system. In POSIX, Windows, and some other systems, this number counts the number @@ -10093,7 +10105,7 @@ valid lines. <p> For instance, the expression <code>debug.getinfo(1,"n").name</code> returns -a table with a name for the current function, +a name for the current function, if a reasonable name can be found, and the expression <code>debug.getinfo(print)</code> returns a table with all available information @@ -10599,7 +10611,8 @@ The <code>bit32</code> library has been deprecated. It is easy to require a compatible external library or, better yet, to replace its functions with appropriate bitwise operations. (Keep in mind that <code>bit32</code> operates on 32-bit integers, -while the bitwise operators in standard Lua operate on 64-bit integers.) +while the bitwise operators in Lua 5.3 operate on Lua integers, +which by default have 64 bits.) </li> <li> @@ -10614,7 +10627,7 @@ its <code>__ipairs</code> metamethod has been deprecated. <li> Option names in <a href="#pdf-io.read"><code>io.read</code></a> do not have a starting '<code>*</code>' anymore. -For compatibility, Lua will continue to ignore this character. +For compatibility, Lua will continue to accept (and ignore) this character. </li> <li> @@ -10641,6 +10654,12 @@ if it cannot find an open function according to the new style. but it did not document the change.) </li> +<li> +The call <code>collectgarbage("count")</code> now returns only one result. +(You can compute that second result from the fractional part +of the first result.) +</li> + </ul> @@ -10776,13 +10795,12 @@ and LiteralString, see <a href="#3.1">§3.1</a>.) -<HR> -<SMALL CLASS="footer"> +<P CLASS="footer"> Last update: -Tue Jan 6 10:10:50 BRST 2015 -</SMALL> +Wed Jun 10 18:31:15 BRT 2015 +</P> <!-- -Last change: revised for Lua 5.3.0 (final) +Last change: revised for Lua 5.3.1 --> </body></html> diff --git a/doc/readme.html b/doc/readme.html index 0165755..152246f 100644 --- a/doc/readme.html +++ b/doc/readme.html @@ -7,9 +7,9 @@ <STYLE TYPE="text/css"> blockquote, .display { border: solid #a0a0a0 2px ; + border-radius: 8px ; padding: 1em ; margin: 0px ; - border-radius: 8px ; } .display { @@ -28,13 +28,12 @@ tt, kbd, code { <BODY> -<HR> <H1> -<A HREF="http://www.lua.org/"><IMG SRC="logo.gif" ALT="Lua" BORDER=0></A> -Welcome to Lua 5.3.0 +<A HREF="http://www.lua.org/"><IMG SRC="logo.gif" ALT="Lua"></A> +Welcome to Lua 5.3 </H1> -<P> +<DIV CLASS="menubar"> <A HREF="#about">about</A> · <A HREF="#install">installation</A> @@ -44,9 +43,9 @@ Welcome to Lua 5.3.0 <A HREF="#license">license</A> · <A HREF="contents.html">reference manual</A> +</DIV> <H2><A NAME="about">About Lua</A></H2> - <P> Lua is a powerful, fast, lightweight, embeddable scripting language developed by a @@ -76,7 +75,6 @@ which may differ slightly from the distributed in this package. <H2><A NAME="install">Installing Lua</A></H2> - <P> Lua is distributed in <A HREF="http://www.lua.org/ftp/">source</A> @@ -102,7 +100,6 @@ Try also a multi-platform distribution of Lua that includes batteries. <H3>Building Lua</H3> - <P> In most Unix-like platforms, simply do "<KBD>make</KBD>" with a suitable target. Here are the details. @@ -110,7 +107,7 @@ Here are the details. <OL> <LI> Open a terminal window and move to -the top-level directory, which is named <TT>lua-5.3.0</TT>. +the top-level directory, which is named <TT>lua-5.3.x</TT>. The <TT>Makefile</TT> there controls both the build process and the installation process. <P> <LI> @@ -140,7 +137,8 @@ and liblua.a (the library). </OL> <P> If you're running Linux and get compilation errors, -make sure you have installed the <TT>readline</TT> development package. +make sure you have installed the <TT>readline</TT> development package +(which is probably named <TT>libreadline-dev</TT> or <TT>readline-devel</TT>). If you get link errors after that, then try "<KBD>make linux MYLIBS=-ltermcap</KBD>". @@ -174,7 +172,7 @@ then try "<KBD>make linux MYLIBS=-ltermcap</KBD>". <DT> include: <DD> - lauxlib.h lua.h lua.hpp luaconf.h lualib.h + lua.h luaconf.h lualib.h lauxlib.h lua.hpp <DT> lib: <DD> @@ -215,7 +213,6 @@ then try "<KBD>make linux MYLIBS=-ltermcap</KBD>". Further customization is available to experts by editing the Lua sources. <H3><A NAME="other">Building Lua on other systems</A></H3> - <P> If you're not using the usual Unix tools, then the instructions for building Lua depend on the compiler you use. You'll need to create @@ -258,7 +255,6 @@ compiler: some features before building Lua. <H2><A NAME="changes">Changes since Lua 5.2</A></H2> - <P> Here are the main changes introduced in Lua 5.3. The @@ -315,11 +311,10 @@ Here are the other changes introduced in Lua 5.3: </UL> <H2><A NAME="license">License</A></H2> +<P> <A HREF="http://www.opensource.org/docs/definition.php"> -<IMG SRC="osi-certified-72x60.png" ALIGN="right" BORDER="0" ALT="[osi certified]" STYLE="padding-left: 30px ;"> +<IMG SRC="osi-certified-72x60.png" ALIGN="right" ALT="[osi certified]" STYLE="padding-left: 30px ;"> </A> - -<P> Lua is free software distributed under the terms of the <A HREF="http://www.opensource.org/licenses/mit-license.html">MIT license</A> reproduced below; @@ -358,13 +353,12 @@ THE SOFTWARE. </BLOCKQUOTE> <P> -<HR> -<SMALL CLASS="footer"> +<P CLASS="footer"> Last update: -Fri Dec 12 09:58:42 BRST 2014 -</SMALL> +Mon Jun 1 21:48:24 BRT 2015 +</P> <!-- -Last change: updated for Lua 5.3.0 (final) +Last change: revised for Lua 5.3.1 --> </BODY> diff --git a/src/Makefile b/src/Makefile index 2e7a412..d71c75c 100644 --- a/src/Makefile +++ b/src/Makefile @@ -130,68 +130,68 @@ solaris: # DO NOT DELETE lapi.o: lapi.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \ - lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lstring.h \ - ltable.h lundump.h lvm.h + lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lstring.h \ + ltable.h lundump.h lvm.h lauxlib.o: lauxlib.c lprefix.h lua.h luaconf.h lauxlib.h lbaselib.o: lbaselib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h lbitlib.o: lbitlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h lcode.o: lcode.c lprefix.h lua.h luaconf.h lcode.h llex.h lobject.h \ - llimits.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h \ - ldo.h lgc.h lstring.h ltable.h lvm.h + llimits.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h \ + ldo.h lgc.h lstring.h ltable.h lvm.h lcorolib.o: lcorolib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h lctype.o: lctype.c lprefix.h lctype.h lua.h luaconf.h llimits.h ldblib.o: ldblib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h ldebug.o: ldebug.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \ - lobject.h ltm.h lzio.h lmem.h lcode.h llex.h lopcodes.h lparser.h \ - ldebug.h ldo.h lfunc.h lstring.h lgc.h ltable.h lvm.h + lobject.h ltm.h lzio.h lmem.h lcode.h llex.h lopcodes.h lparser.h \ + ldebug.h ldo.h lfunc.h lstring.h lgc.h ltable.h lvm.h ldo.o: ldo.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \ - lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lopcodes.h \ - lparser.h lstring.h ltable.h lundump.h lvm.h + lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lopcodes.h \ + lparser.h lstring.h ltable.h lundump.h lvm.h ldump.o: ldump.c lprefix.h lua.h luaconf.h lobject.h llimits.h lstate.h \ - ltm.h lzio.h lmem.h lundump.h + ltm.h lzio.h lmem.h lundump.h lfunc.o: lfunc.c lprefix.h lua.h luaconf.h lfunc.h lobject.h llimits.h \ - lgc.h lstate.h ltm.h lzio.h lmem.h + lgc.h lstate.h ltm.h lzio.h lmem.h lgc.o: lgc.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \ - llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h + llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h linit.o: linit.c lprefix.h lua.h luaconf.h lualib.h lauxlib.h liolib.o: liolib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h -llex.o: llex.c lprefix.h lua.h luaconf.h lctype.h llimits.h ldo.h \ - lobject.h lstate.h ltm.h lzio.h lmem.h lgc.h llex.h lparser.h lstring.h \ - ltable.h +llex.o: llex.c lprefix.h lua.h luaconf.h lctype.h llimits.h ldebug.h \ + lstate.h lobject.h ltm.h lzio.h lmem.h ldo.h lgc.h llex.h lparser.h \ + lstring.h ltable.h lmathlib.o: lmathlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h lmem.o: lmem.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \ - llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h + llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h loadlib.o: loadlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h lobject.o: lobject.c lprefix.h lua.h luaconf.h lctype.h llimits.h \ - ldebug.h lstate.h lobject.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h \ - lvm.h + ldebug.h lstate.h lobject.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h \ + lvm.h lopcodes.o: lopcodes.c lprefix.h lopcodes.h llimits.h lua.h luaconf.h loslib.o: loslib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h lparser.o: lparser.c lprefix.h lua.h luaconf.h lcode.h llex.h lobject.h \ - llimits.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h \ - ldo.h lfunc.h lstring.h lgc.h ltable.h + llimits.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h \ + ldo.h lfunc.h lstring.h lgc.h ltable.h lstate.o: lstate.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \ - lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h llex.h \ - lstring.h ltable.h + lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h llex.h \ + lstring.h ltable.h lstring.o: lstring.c lprefix.h lua.h luaconf.h ldebug.h lstate.h \ - lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h + lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h lstrlib.o: lstrlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h ltable.o: ltable.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \ - llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h lstring.h ltable.h lvm.h + llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h lstring.h ltable.h lvm.h ltablib.o: ltablib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h ltm.o: ltm.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \ - llimits.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h ltable.h lvm.h + llimits.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h ltable.h lvm.h lua.o: lua.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h luac.o: luac.c lprefix.h lua.h luaconf.h lauxlib.h lobject.h llimits.h \ - lstate.h ltm.h lzio.h lmem.h lundump.h ldebug.h lopcodes.h + lstate.h ltm.h lzio.h lmem.h lundump.h ldebug.h lopcodes.h lundump.o: lundump.c lprefix.h lua.h luaconf.h ldebug.h lstate.h \ - lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.h \ - lundump.h + lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.h \ + lundump.h lutf8lib.o: lutf8lib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h lvm.o: lvm.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \ - llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lstring.h \ - ltable.h lvm.h + llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lstring.h \ + ltable.h lvm.h lzio.o: lzio.c lprefix.h lua.h luaconf.h llimits.h lmem.h lstate.h \ - lobject.h ltm.h lzio.h + lobject.h ltm.h lzio.h # (end of Makefile) @@ -1,5 +1,5 @@ /* -** $Id: lapi.c,v 2.244 2014/12/26 14:43:45 roberto Exp $ +** $Id: lapi.c,v 2.249 2015/04/06 12:23:48 roberto Exp $ ** Lua API ** See Copyright Notice in lua.h */ @@ -51,29 +51,29 @@ const char lua_ident[] = /* test for valid but not pseudo index */ #define isstackindex(i, o) (isvalid(o) && !ispseudo(i)) -#define api_checkvalidindex(o) api_check(isvalid(o), "invalid index") +#define api_checkvalidindex(l,o) api_check(l, isvalid(o), "invalid index") -#define api_checkstackindex(i, o) \ - api_check(isstackindex(i, o), "index not in the stack") +#define api_checkstackindex(l, i, o) \ + api_check(l, isstackindex(i, o), "index not in the stack") static TValue *index2addr (lua_State *L, int idx) { CallInfo *ci = L->ci; if (idx > 0) { TValue *o = ci->func + idx; - api_check(idx <= ci->top - (ci->func + 1), "unacceptable index"); + api_check(L, idx <= ci->top - (ci->func + 1), "unacceptable index"); if (o >= L->top) return NONVALIDVALUE; else return o; } else if (!ispseudo(idx)) { /* negative index */ - api_check(idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index"); + api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index"); return L->top + idx; } else if (idx == LUA_REGISTRYINDEX) return &G(L)->l_registry; else { /* upvalues */ idx = LUA_REGISTRYINDEX - idx; - api_check(idx <= MAXUPVAL + 1, "upvalue index too large"); + api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large"); if (ttislcf(ci->func)) /* light C function? */ return NONVALIDVALUE; /* it has no upvalues */ else { @@ -98,7 +98,7 @@ LUA_API int lua_checkstack (lua_State *L, int n) { int res; CallInfo *ci = L->ci; lua_lock(L); - api_check(n >= 0, "negative 'n'"); + api_check(L, n >= 0, "negative 'n'"); if (L->stack_last - L->top > n) /* stack large enough? */ res = 1; /* yes; check is OK */ else { /* no; need to grow stack */ @@ -120,11 +120,12 @@ LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { if (from == to) return; lua_lock(to); api_checknelems(from, n); - api_check(G(from) == G(to), "moving among independent states"); - api_check(to->ci->top - to->top >= n, "not enough elements to move"); + api_check(from, G(from) == G(to), "moving among independent states"); + api_check(from, to->ci->top - to->top >= n, "not enough elements to move"); from->top -= n; for (i = 0; i < n; i++) { - setobj2s(to, to->top++, from->top + i); + setobj2s(to, to->top, from->top + i); + api_incr_top(to); } lua_unlock(to); } @@ -159,7 +160,7 @@ LUA_API const lua_Number *lua_version (lua_State *L) { LUA_API int lua_absindex (lua_State *L, int idx) { return (idx > 0 || ispseudo(idx)) ? idx - : cast_int(L->top - L->ci->func + idx); + : cast_int(L->top - L->ci->func) + idx; } @@ -172,13 +173,13 @@ LUA_API void lua_settop (lua_State *L, int idx) { StkId func = L->ci->func; lua_lock(L); if (idx >= 0) { - api_check(idx <= L->stack_last - (func + 1), "new top too large"); + api_check(L, idx <= L->stack_last - (func + 1), "new top too large"); while (L->top < (func + 1) + idx) setnilvalue(L->top++); L->top = (func + 1) + idx; } else { - api_check(-(idx+1) <= (L->top - (func + 1)), "invalid new top"); + api_check(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top"); L->top += idx+1; /* 'subtract' index (index is negative) */ } lua_unlock(L); @@ -208,8 +209,8 @@ LUA_API void lua_rotate (lua_State *L, int idx, int n) { lua_lock(L); t = L->top - 1; /* end of stack segment being rotated */ p = index2addr(L, idx); /* start of segment */ - api_checkstackindex(idx, p); - api_check((n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'"); + api_checkstackindex(L, idx, p); + api_check(L, (n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'"); m = (n >= 0 ? t - n : p - n - 1); /* end of prefix */ reverse(L, p, m); /* reverse the prefix with length 'n' */ reverse(L, m + 1, t); /* reverse the suffix */ @@ -223,7 +224,7 @@ LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) { lua_lock(L); fr = index2addr(L, fromidx); to = index2addr(L, toidx); - api_checkvalidindex(to); + api_checkvalidindex(L, to); setobj(L, to, fr); if (isupvalue(toidx)) /* function upvalue? */ luaC_barrier(L, clCvalue(L->ci->func), fr); @@ -255,7 +256,7 @@ LUA_API int lua_type (lua_State *L, int idx) { LUA_API const char *lua_typename (lua_State *L, int t) { UNUSED(L); - api_check(LUA_TNONE <= t && t < LUA_NUMTAGS, "invalid tag"); + api_check(L, LUA_TNONE <= t && t < LUA_NUMTAGS, "invalid tag"); return ttypename(t); } @@ -305,7 +306,7 @@ LUA_API void lua_arith (lua_State *L, int op) { else { /* for unary operations, add fake 2nd operand */ api_checknelems(L, 1); setobjs2s(L, L->top, L->top - 1); - L->top++; + api_incr_top(L); } /* first operand at top - 2, second at top - 1; result go to top - 2 */ luaO_arith(L, op, L->top - 2, L->top - 1, L->top - 2); @@ -325,7 +326,7 @@ LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) { case LUA_OPEQ: i = luaV_equalobj(L, o1, o2); break; case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break; case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break; - default: api_check(0, "invalid option"); + default: api_check(L, 0, "invalid option"); } } lua_unlock(L); @@ -382,15 +383,17 @@ LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { luaO_tostring(L, o); lua_unlock(L); } - if (len != NULL) *len = tsvalue(o)->len; + if (len != NULL) + *len = vslen(o); return svalue(o); } LUA_API size_t lua_rawlen (lua_State *L, int idx) { StkId o = index2addr(L, idx); - switch (ttnov(o)) { - case LUA_TSTRING: return tsvalue(o)->len; + switch (ttype(o)) { + case LUA_TSHRSTR: return tsvalue(o)->shrlen; + case LUA_TLNGSTR: return tsvalue(o)->u.lnglen; case LUA_TUSERDATA: return uvalue(o)->len; case LUA_TTABLE: return luaH_getn(hvalue(o)); default: return 0; @@ -431,9 +434,8 @@ LUA_API const void *lua_topointer (lua_State *L, int idx) { case LUA_TCCL: return clCvalue(o); case LUA_TLCF: return cast(void *, cast(size_t, fvalue(o))); case LUA_TTHREAD: return thvalue(o); - case LUA_TUSERDATA: - case LUA_TLIGHTUSERDATA: - return lua_touserdata(L, idx); + case LUA_TUSERDATA: return getudatamem(uvalue(o)); + case LUA_TLIGHTUSERDATA: return pvalue(o); default: return NULL; } } @@ -482,20 +484,19 @@ LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) { LUA_API const char *lua_pushstring (lua_State *L, const char *s) { - if (s == NULL) { - lua_pushnil(L); - return NULL; - } + lua_lock(L); + if (s == NULL) + setnilvalue(L->top); else { TString *ts; - lua_lock(L); luaC_checkGC(L); ts = luaS_new(L, s); setsvalue2s(L, L->top, ts); - api_incr_top(L); - lua_unlock(L); - return getstr(ts); + s = getstr(ts); /* internal copy's address */ } + api_incr_top(L); + lua_unlock(L); + return s; } @@ -531,7 +532,7 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { else { CClosure *cl; api_checknelems(L, n); - api_check(n <= MAXUPVAL, "upvalue index too large"); + api_check(L, n <= MAXUPVAL, "upvalue index too large"); luaC_checkGC(L); cl = luaF_newCclosure(L, n); cl->f = fn; @@ -583,7 +584,8 @@ LUA_API int lua_getglobal (lua_State *L, const char *name) { const TValue *gt; /* global table */ lua_lock(L); gt = luaH_getint(reg, LUA_RIDX_GLOBALS); - setsvalue2s(L, L->top++, luaS_new(L, name)); + setsvalue2s(L, L->top, luaS_new(L, name)); + api_incr_top(L); luaV_gettable(L, gt, L->top - 1, L->top - 1); lua_unlock(L); return ttnov(L->top - 1); @@ -628,7 +630,7 @@ LUA_API int lua_rawget (lua_State *L, int idx) { StkId t; lua_lock(L); t = index2addr(L, idx); - api_check(ttistable(t), "table expected"); + api_check(L, ttistable(t), "table expected"); setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1)); lua_unlock(L); return ttnov(L->top - 1); @@ -639,7 +641,7 @@ LUA_API int lua_rawgeti (lua_State *L, int idx, lua_Integer n) { StkId t; lua_lock(L); t = index2addr(L, idx); - api_check(ttistable(t), "table expected"); + api_check(L, ttistable(t), "table expected"); setobj2s(L, L->top, luaH_getint(hvalue(t), n)); api_incr_top(L); lua_unlock(L); @@ -652,7 +654,7 @@ LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) { TValue k; lua_lock(L); t = index2addr(L, idx); - api_check(ttistable(t), "table expected"); + api_check(L, ttistable(t), "table expected"); setpvalue(&k, cast(void *, p)); setobj2s(L, L->top, luaH_get(hvalue(t), &k)); api_incr_top(L); @@ -705,7 +707,7 @@ LUA_API int lua_getuservalue (lua_State *L, int idx) { StkId o; lua_lock(L); o = index2addr(L, idx); - api_check(ttisfulluserdata(o), "full userdata expected"); + api_check(L, ttisfulluserdata(o), "full userdata expected"); getuservalue(L, uvalue(o), L->top); api_incr_top(L); lua_unlock(L); @@ -724,7 +726,8 @@ LUA_API void lua_setglobal (lua_State *L, const char *name) { lua_lock(L); api_checknelems(L, 1); gt = luaH_getint(reg, LUA_RIDX_GLOBALS); - setsvalue2s(L, L->top++, luaS_new(L, name)); + setsvalue2s(L, L->top, luaS_new(L, name)); + api_incr_top(L); luaV_settable(L, gt, L->top - 1, L->top - 2); L->top -= 2; /* pop value and key */ lua_unlock(L); @@ -747,7 +750,8 @@ LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { lua_lock(L); api_checknelems(L, 1); t = index2addr(L, idx); - setsvalue2s(L, L->top++, luaS_new(L, k)); + setsvalue2s(L, L->top, luaS_new(L, k)); + api_incr_top(L); luaV_settable(L, t, L->top - 1, L->top - 2); L->top -= 2; /* pop value and key */ lua_unlock(L); @@ -759,7 +763,8 @@ LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) { lua_lock(L); api_checknelems(L, 1); t = index2addr(L, idx); - setivalue(L->top++, n); + setivalue(L->top, n); + api_incr_top(L); luaV_settable(L, t, L->top - 1, L->top - 2); L->top -= 2; /* pop value and key */ lua_unlock(L); @@ -772,7 +777,7 @@ LUA_API void lua_rawset (lua_State *L, int idx) { lua_lock(L); api_checknelems(L, 2); o = index2addr(L, idx); - api_check(ttistable(o), "table expected"); + api_check(L, ttistable(o), "table expected"); t = hvalue(o); setobj2t(L, luaH_set(L, t, L->top-2), L->top-1); invalidateTMcache(t); @@ -788,7 +793,7 @@ LUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) { lua_lock(L); api_checknelems(L, 1); o = index2addr(L, idx); - api_check(ttistable(o), "table expected"); + api_check(L, ttistable(o), "table expected"); t = hvalue(o); luaH_setint(L, t, n, L->top - 1); luaC_barrierback(L, t, L->top-1); @@ -804,7 +809,7 @@ LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) { lua_lock(L); api_checknelems(L, 1); o = index2addr(L, idx); - api_check(ttistable(o), "table expected"); + api_check(L, ttistable(o), "table expected"); t = hvalue(o); setpvalue(&k, cast(void *, p)); setobj2t(L, luaH_set(L, t, &k), L->top - 1); @@ -823,7 +828,7 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) { if (ttisnil(L->top - 1)) mt = NULL; else { - api_check(ttistable(L->top - 1), "table expected"); + api_check(L, ttistable(L->top - 1), "table expected"); mt = hvalue(L->top - 1); } switch (ttnov(obj)) { @@ -859,7 +864,7 @@ LUA_API void lua_setuservalue (lua_State *L, int idx) { lua_lock(L); api_checknelems(L, 1); o = index2addr(L, idx); - api_check(ttisfulluserdata(o), "full userdata expected"); + api_check(L, ttisfulluserdata(o), "full userdata expected"); setuservalue(L, uvalue(o), L->top - 1); luaC_barrier(L, gcvalue(o), L->top - 1); L->top--; @@ -873,7 +878,7 @@ LUA_API void lua_setuservalue (lua_State *L, int idx) { #define checkresults(L,na,nr) \ - api_check((nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \ + api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \ "results from function overflow current stack size") @@ -881,10 +886,10 @@ LUA_API void lua_callk (lua_State *L, int nargs, int nresults, lua_KContext ctx, lua_KFunction k) { StkId func; lua_lock(L); - api_check(k == NULL || !isLua(L->ci), + api_check(L, k == NULL || !isLua(L->ci), "cannot use continuations inside hooks"); api_checknelems(L, nargs+1); - api_check(L->status == LUA_OK, "cannot do calls on non-normal thread"); + api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); checkresults(L, nargs, nresults); func = L->top - (nargs+1); if (k != NULL && L->nny == 0) { /* need to prepare continuation? */ @@ -922,16 +927,16 @@ LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc, int status; ptrdiff_t func; lua_lock(L); - api_check(k == NULL || !isLua(L->ci), + api_check(L, k == NULL || !isLua(L->ci), "cannot use continuations inside hooks"); api_checknelems(L, nargs+1); - api_check(L->status == LUA_OK, "cannot do calls on non-normal thread"); + api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); checkresults(L, nargs, nresults); if (errfunc == 0) func = 0; else { StkId o = index2addr(L, errfunc); - api_checkstackindex(errfunc, o); + api_checkstackindex(L, errfunc, o); func = savestack(L, o); } c.func = L->top - (nargs+1); /* function to be called */ @@ -1096,7 +1101,7 @@ LUA_API int lua_next (lua_State *L, int idx) { int more; lua_lock(L); t = index2addr(L, idx); - api_check(ttistable(t), "table expected"); + api_check(L, ttistable(t), "table expected"); more = luaH_next(L, hvalue(t), L->top - 1); if (more) { api_incr_top(L); @@ -1228,9 +1233,9 @@ LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) { LClosure *f; StkId fi = index2addr(L, fidx); - api_check(ttisLclosure(fi), "Lua function expected"); + api_check(L, ttisLclosure(fi), "Lua function expected"); f = clLvalue(fi); - api_check((1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index"); + api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index"); if (pf) *pf = f; return &f->upvals[n - 1]; /* get its upvalue pointer */ } @@ -1244,11 +1249,11 @@ LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) { } case LUA_TCCL: { /* C closure */ CClosure *f = clCvalue(fi); - api_check(1 <= n && n <= f->nupvalues, "invalid upvalue index"); + api_check(L, 1 <= n && n <= f->nupvalues, "invalid upvalue index"); return &f->upvalue[n - 1]; } default: { - api_check(0, "closure expected"); + api_check(L, 0, "closure expected"); return NULL; } } @@ -1,5 +1,5 @@ /* -** $Id: lapi.h,v 2.8 2014/07/15 21:26:50 roberto Exp $ +** $Id: lapi.h,v 2.9 2015/03/06 19:49:50 roberto Exp $ ** Auxiliary functions from Lua API ** See Copyright Notice in lua.h */ @@ -11,13 +11,13 @@ #include "llimits.h" #include "lstate.h" -#define api_incr_top(L) {L->top++; api_check(L->top <= L->ci->top, \ +#define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top, \ "stack overflow");} #define adjustresults(L,nres) \ { if ((nres) == LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; } -#define api_checknelems(L,n) api_check((n) < (L->top - L->ci->func), \ +#define api_checknelems(L,n) api_check(L, (n) < (L->top - L->ci->func), \ "not enough elements in the stack") diff --git a/src/lauxlib.c b/src/lauxlib.c index 1c41d6a..b8bace7 100644 --- a/src/lauxlib.c +++ b/src/lauxlib.c @@ -1,5 +1,5 @@ /* -** $Id: lauxlib.c,v 1.279 2014/12/14 18:32:26 roberto Exp $ +** $Id: lauxlib.c,v 1.280 2015/02/03 17:38:24 roberto Exp $ ** Auxiliary functions for building Lua libraries ** See Copyright Notice in lua.h */ @@ -286,7 +286,7 @@ LUALIB_API int luaL_execresult (lua_State *L, int stat) { */ LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { - if (luaL_getmetatable(L, tname)) /* name already in use? */ + if (luaL_getmetatable(L, tname) != LUA_TNIL) /* name already in use? */ return 0; /* leave previous value on top, but return 0 */ lua_pop(L, 1); lua_newtable(L); /* create metatable */ diff --git a/src/lbaselib.c b/src/lbaselib.c index a240395..9a15124 100644 --- a/src/lbaselib.c +++ b/src/lbaselib.c @@ -1,5 +1,5 @@ /* -** $Id: lbaselib.c,v 1.309 2014/12/10 12:26:42 roberto Exp $ +** $Id: lbaselib.c,v 1.310 2015/03/28 19:14:47 roberto Exp $ ** Basic library ** See Copyright Notice in lua.h */ @@ -55,7 +55,7 @@ static const char *b_str2int (const char *s, int base, lua_Integer *pn) { return NULL; do { int digit = (isdigit((unsigned char)*s)) ? *s - '0' - : toupper((unsigned char)*s) - 'A' + 10; + : (toupper((unsigned char)*s) - 'A') + 10; if (digit >= base) return NULL; /* invalid numeral */ n = n * base + digit; s++; diff --git a/src/lcode.c b/src/lcode.c index 5e34624..d6f0fcd 100644 --- a/src/lcode.c +++ b/src/lcode.c @@ -1,5 +1,5 @@ /* -** $Id: lcode.c,v 2.99 2014/12/29 16:49:25 roberto Exp $ +** $Id: lcode.c,v 2.101 2015/04/29 18:24:11 roberto Exp $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -29,8 +29,8 @@ #include "lvm.h" -/* Maximum number of registers in a Lua function */ -#define MAXREGS 250 +/* Maximum number of registers in a Lua function (must fit in 8 bits) */ +#define MAXREGS 255 #define hasjumps(e) ((e)->t != (e)->f) @@ -279,7 +279,8 @@ void luaK_checkstack (FuncState *fs, int n) { int newstack = fs->freereg + n; if (newstack > fs->f->maxstacksize) { if (newstack >= MAXREGS) - luaX_syntaxerror(fs->ls, "function or expression too complex"); + luaX_syntaxerror(fs->ls, + "function or expression needs too many registers"); fs->f->maxstacksize = cast_byte(newstack); } } @@ -573,8 +574,8 @@ int luaK_exp2RK (FuncState *fs, expdesc *e) { case VKFLT: { e->u.info = luaK_numberK(fs, e->u.nval); e->k = VK; - /* go through */ } + /* FALLTHROUGH */ case VK: { vk: if (e->u.info <= MAXINDEXRK) /* constant fits in 'argC'? */ @@ -793,7 +794,7 @@ static int constfolding (FuncState *fs, int op, expdesc *e1, expdesc *e2) { static void codeexpval (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2, int line) { lua_assert(op >= OP_ADD); - if (op <= OP_BNOT && constfolding(fs, op - OP_ADD + LUA_OPADD, e1, e2)) + if (op <= OP_BNOT && constfolding(fs, (op - OP_ADD) + LUA_OPADD, e1, e2)) return; /* result has been folded */ else { int o1, o2; @@ -920,11 +921,11 @@ void luaK_posfix (FuncState *fs, BinOpr op, break; } case OPR_EQ: case OPR_LT: case OPR_LE: { - codecomp(fs, cast(OpCode, op - OPR_EQ + OP_EQ), 1, e1, e2); + codecomp(fs, cast(OpCode, (op - OPR_EQ) + OP_EQ), 1, e1, e2); break; } case OPR_NE: case OPR_GT: case OPR_GE: { - codecomp(fs, cast(OpCode, op - OPR_NE + OP_EQ), 0, e1, e2); + codecomp(fs, cast(OpCode, (op - OPR_NE) + OP_EQ), 0, e1, e2); break; } default: lua_assert(0); diff --git a/src/ldblib.c b/src/ldblib.c index 24a11b5..9151458 100644 --- a/src/ldblib.c +++ b/src/ldblib.c @@ -1,5 +1,5 @@ /* -** $Id: ldblib.c,v 1.148 2015/01/02 12:52:22 roberto Exp $ +** $Id: ldblib.c,v 1.149 2015/02/19 17:06:21 roberto Exp $ ** Interface from Lua to its debug API ** See Copyright Notice in lua.h */ @@ -27,6 +27,17 @@ static const int HOOKKEY = 0; +/* +** If L1 != L, L1 can be in any state, and therefore there is no +** garanties about its stack space; any push in L1 must be +** checked. +*/ +static void checkstack (lua_State *L, lua_State *L1, int n) { + if (L != L1 && !lua_checkstack(L1, n)) + luaL_error(L, "stack overflow"); +} + + static int db_getregistry (lua_State *L) { lua_pushvalue(L, LUA_REGISTRYINDEX); return 1; @@ -127,12 +138,16 @@ static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) { /* ** Calls 'lua_getinfo' and collects all results in a new table. +** L1 needs stack space for an optional input (function) plus +** two optional outputs (function and line table) from function +** 'lua_getinfo'. */ static int db_getinfo (lua_State *L) { lua_Debug ar; int arg; lua_State *L1 = getthread(L, &arg); const char *options = luaL_optstring(L, arg+2, "flnStu"); + checkstack(L, L1, 3); if (lua_isfunction(L, arg + 1)) { /* info about a function? */ options = lua_pushfstring(L, ">%s", options); /* add '>' to 'options' */ lua_pushvalue(L, arg + 1); /* move function to 'L1' stack */ @@ -190,6 +205,7 @@ static int db_getlocal (lua_State *L) { int level = (int)luaL_checkinteger(L, arg + 1); if (!lua_getstack(L1, level, &ar)) /* out of range? */ return luaL_argerror(L, arg+1, "level out of range"); + checkstack(L, L1, 1); name = lua_getlocal(L1, &ar, nvar); if (name) { lua_xmove(L1, L, 1); /* move local value */ @@ -216,6 +232,7 @@ static int db_setlocal (lua_State *L) { return luaL_argerror(L, arg+1, "level out of range"); luaL_checkany(L, arg+3); lua_settop(L, arg+3); + checkstack(L, L1, 1); lua_xmove(L, L1, 1); name = lua_setlocal(L1, &ar, nvar); if (name == NULL) @@ -350,6 +367,7 @@ static int db_sethook (lua_State *L) { lua_pushvalue(L, -1); lua_setmetatable(L, -2); /* setmetatable(hooktable) = hooktable */ } + checkstack(L, L1, 1); lua_pushthread(L1); lua_xmove(L1, L, 1); /* key (thread) */ lua_pushvalue(L, arg + 1); /* value (hook function) */ lua_rawset(L, -3); /* hooktable[L1] = new Lua hook */ @@ -370,6 +388,7 @@ static int db_gethook (lua_State *L) { lua_pushliteral(L, "external hook"); else { /* hook table must exist */ lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY); + checkstack(L, L1, 1); lua_pushthread(L1); lua_xmove(L1, L, 1); lua_rawget(L, -2); /* 1st result = hooktable[L1] */ lua_remove(L, -2); /* remove hook table */ diff --git a/src/ldebug.c b/src/ldebug.c index 6986bf0..f76582c 100644 --- a/src/ldebug.c +++ b/src/ldebug.c @@ -1,5 +1,5 @@ /* -** $Id: ldebug.c,v 2.110 2015/01/02 12:52:22 roberto Exp $ +** $Id: ldebug.c,v 2.115 2015/05/22 17:45:56 roberto Exp $ ** Debug Interface ** See Copyright Notice in lua.h */ @@ -34,6 +34,10 @@ #define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_TCCL) +/* Active Lua function (given call info) */ +#define ci_func(ci) (clLvalue((ci)->func)) + + static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name); @@ -49,6 +53,22 @@ static int currentline (CallInfo *ci) { /* +** If function yielded, its 'func' can be in the 'extra' field. The +** next function restores 'func' to its correct value for debugging +** purposes. (It exchanges 'func' and 'extra'; so, when called again, +** after debugging, it also "re-restores" ** 'func' to its altered value. +*/ +static void swapextra (lua_State *L) { + if (L->status == LUA_YIELD) { + CallInfo *ci = L->ci; /* get function that yielded */ + StkId temp = ci->func; /* exchange its 'func' and 'extra' values */ + ci->func = restorestack(L, ci->extra); + ci->extra = savestack(L, temp); + } +} + + +/* ** this function can be called asynchronous (e.g. during a signal) */ LUA_API void lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { @@ -106,7 +126,7 @@ static const char *upvalname (Proto *p, int uv) { static const char *findvararg (CallInfo *ci, int n, StkId *pos) { int nparams = clLvalue(ci->func)->p->numparams; - if (n >= ci->u.l.base - ci->func - nparams) + if (n >= cast_int(ci->u.l.base - ci->func) - nparams) return NULL; /* no such vararg */ else { *pos = ci->func + nparams + n; @@ -144,6 +164,7 @@ static const char *findlocal (lua_State *L, CallInfo *ci, int n, LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { const char *name; lua_lock(L); + swapextra(L); if (ar == NULL) { /* information about non-active function? */ if (!isLfunction(L->top - 1)) /* not a Lua function? */ name = NULL; @@ -151,26 +172,30 @@ LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { name = luaF_getlocalname(clLvalue(L->top - 1)->p, n, 0); } else { /* active function; get information through 'ar' */ - StkId pos = 0; /* to avoid warnings */ + StkId pos = NULL; /* to avoid warnings */ name = findlocal(L, ar->i_ci, n, &pos); if (name) { setobj2s(L, L->top, pos); api_incr_top(L); } } + swapextra(L); lua_unlock(L); return name; } LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { - StkId pos = 0; /* to avoid warnings */ - const char *name = findlocal(L, ar->i_ci, n, &pos); + StkId pos = NULL; /* to avoid warnings */ + const char *name; lua_lock(L); + swapextra(L); + name = findlocal(L, ar->i_ci, n, &pos); if (name) { setobjs2s(L, pos, L->top - 1); L->top--; /* pop value */ } + swapextra(L); lua_unlock(L); return name; } @@ -270,10 +295,11 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { CallInfo *ci; StkId func; lua_lock(L); + swapextra(L); if (*what == '>') { ci = NULL; func = L->top - 1; - api_check(ttisfunction(func), "function expected"); + api_check(L, ttisfunction(func), "function expected"); what++; /* skip the '>' */ L->top--; /* pop function */ } @@ -288,6 +314,7 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { setobjs2s(L, L->top, func); api_incr_top(L); } + swapextra(L); /* correct before option 'L', which can raise a mem. error */ if (strchr(what, 'L')) collectvalidlines(L, cl); lua_unlock(L); @@ -572,19 +599,16 @@ l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { } -static void addinfo (lua_State *L, const char *msg) { - CallInfo *ci = L->ci; - if (isLua(ci)) { /* is Lua code? */ - char buff[LUA_IDSIZE]; /* add file:line information */ - int line = currentline(ci); - TString *src = ci_func(ci)->p->source; - if (src) - luaO_chunkid(buff, getstr(src), LUA_IDSIZE); - else { /* no source available; use "?" instead */ - buff[0] = '?'; buff[1] = '\0'; - } - luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); +/* add src:line information to 'msg' */ +const char *luaG_addinfo (lua_State *L, const char *msg, TString *src, + int line) { + char buff[LUA_IDSIZE]; + if (src) + luaO_chunkid(buff, getstr(src), LUA_IDSIZE); + else { /* no source available; use "?" instead */ + buff[0] = '?'; buff[1] = '\0'; } + return luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); } @@ -601,10 +625,14 @@ l_noret luaG_errormsg (lua_State *L) { l_noret luaG_runerror (lua_State *L, const char *fmt, ...) { + CallInfo *ci = L->ci; + const char *msg; va_list argp; va_start(argp, fmt); - addinfo(L, luaO_pushvfstring(L, fmt, argp)); + msg = luaO_pushvfstring(L, fmt, argp); /* format message */ va_end(argp); + if (isLua(ci)) /* if Lua function, add source:line information */ + luaG_addinfo(L, msg, ci_func(ci)->p->source, currentline(ci)); luaG_errormsg(L); } diff --git a/src/ldebug.h b/src/ldebug.h index 0d8966c..0e31546 100644 --- a/src/ldebug.h +++ b/src/ldebug.h @@ -1,5 +1,5 @@ /* -** $Id: ldebug.h,v 2.12 2014/11/10 14:46:05 roberto Exp $ +** $Id: ldebug.h,v 2.14 2015/05/22 17:45:56 roberto Exp $ ** Auxiliary functions from Debug Interface module ** See Copyright Notice in lua.h */ @@ -17,9 +17,6 @@ #define resethookcount(L) (L->hookcount = L->basehookcount) -/* Active Lua function (given call info) */ -#define ci_func(ci) (clLvalue((ci)->func)) - LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *opname); @@ -33,6 +30,8 @@ LUAI_FUNC l_noret luaG_tointerror (lua_State *L, const TValue *p1, LUAI_FUNC l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2); LUAI_FUNC l_noret luaG_runerror (lua_State *L, const char *fmt, ...); +LUAI_FUNC const char *luaG_addinfo (lua_State *L, const char *msg, + TString *src, int line); LUAI_FUNC l_noret luaG_errormsg (lua_State *L); LUAI_FUNC void luaG_traceexec (lua_State *L); @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 2.135 2014/11/11 17:13:39 roberto Exp $ +** $Id: ldo.c,v 2.138 2015/05/22 17:48:19 roberto Exp $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -323,6 +323,7 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { case LUA_TCCL: { /* C closure */ f = clCvalue(func)->f; Cfunc: + luaC_checkGC(L); /* stack grow uses memory */ luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ ci = next_ci(L); /* now 'enter' new function */ ci->nresults = nresults; @@ -330,20 +331,20 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { ci->top = L->top + LUA_MINSTACK; lua_assert(ci->top <= L->stack_last); ci->callstatus = 0; - luaC_checkGC(L); /* stack grow uses memory */ if (L->hookmask & LUA_MASKCALL) luaD_hook(L, LUA_HOOKCALL, -1); lua_unlock(L); n = (*f)(L); /* do the actual call */ lua_lock(L); api_checknelems(L, n); - luaD_poscall(L, L->top - n); + luaD_poscall(L, L->top - n, n); return 1; } case LUA_TLCL: { /* Lua function: prepare its call */ StkId base; Proto *p = clLvalue(func)->p; n = cast_int(L->top - func) - 1; /* number of real arguments */ + luaC_checkGC(L); /* stack grow uses memory */ luaD_checkstack(L, p->maxstacksize); for (; n < p->numparams; n++) setnilvalue(L->top++); /* complete missing arguments */ @@ -364,7 +365,6 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { ci->u.l.savedpc = p->code; /* starting point */ ci->callstatus = CIST_LUA; L->top = ci->top; - luaC_checkGC(L); /* stack grow uses memory */ if (L->hookmask & LUA_MASKCALL) callhook(L, ci); return 0; @@ -379,7 +379,7 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { } -int luaD_poscall (lua_State *L, StkId firstResult) { +int luaD_poscall (lua_State *L, StkId firstResult, int nres) { StkId res; int wanted, i; CallInfo *ci = L->ci; @@ -393,9 +393,9 @@ int luaD_poscall (lua_State *L, StkId firstResult) { } res = ci->func; /* res == final position of 1st result */ wanted = ci->nresults; - L->ci = ci = ci->previous; /* back to caller */ + L->ci = ci->previous; /* back to caller */ /* move results to correct place */ - for (i = wanted; i != 0 && firstResult < L->top; i--) + for (i = wanted; i != 0 && nres-- > 0; i--) setobjs2s(L, res++, firstResult++); while (i-- > 0) setnilvalue(res++); @@ -449,7 +449,7 @@ static void finishCcall (lua_State *L, int status) { lua_lock(L); api_checknelems(L, n); /* finish 'luaD_precall' */ - luaD_poscall(L, L->top - n); + luaD_poscall(L, L->top - n, n); } @@ -533,7 +533,8 @@ static l_noret resume_error (lua_State *L, const char *msg, StkId firstArg) { */ static void resume (lua_State *L, void *ud) { int nCcalls = L->nCcalls; - StkId firstArg = cast(StkId, ud); + int n = *(cast(int*, ud)); /* number of arguments */ + StkId firstArg = L->top - n; /* first argument */ CallInfo *ci = L->ci; if (nCcalls >= LUAI_MAXCCALLS) resume_error(L, "C stack overflow", firstArg); @@ -553,14 +554,13 @@ static void resume (lua_State *L, void *ud) { luaV_execute(L); /* just continue running Lua code */ else { /* 'common' yield */ if (ci->u.c.k != NULL) { /* does it have a continuation function? */ - int n; lua_unlock(L); n = (*ci->u.c.k)(L, LUA_YIELD, ci->u.c.ctx); /* call continuation */ lua_lock(L); api_checknelems(L, n); firstArg = L->top - n; /* yield results come from continuation */ } - luaD_poscall(L, firstArg); /* finish 'luaD_precall' */ + luaD_poscall(L, firstArg, n); /* finish 'luaD_precall' */ } unroll(L, NULL); /* run continuation */ } @@ -576,7 +576,7 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) { L->nCcalls = (from) ? from->nCcalls + 1 : 1; L->nny = 0; /* allow yields */ api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); - status = luaD_rawrunprotected(L, resume, L->top - nargs); + status = luaD_rawrunprotected(L, resume, &nargs); if (status == -1) /* error calling 'lua_resume'? */ status = LUA_ERRRUN; else { /* continue running after recoverable errors */ @@ -619,7 +619,7 @@ LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, L->status = LUA_YIELD; ci->extra = savestack(L, ci->func); /* save current 'func' */ if (isLua(ci)) { /* inside a hook? */ - api_check(k == NULL, "hooks cannot continue after yielding"); + api_check(L, k == NULL, "hooks cannot continue after yielding"); } else { if ((ci->u.c.k = k) != NULL) /* is there a continuation? */ @@ -1,5 +1,5 @@ /* -** $Id: ldo.h,v 2.21 2014/10/25 11:50:46 roberto Exp $ +** $Id: ldo.h,v 2.22 2015/05/22 17:48:19 roberto Exp $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -34,7 +34,7 @@ LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults, int allowyield); LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, ptrdiff_t oldtop, ptrdiff_t ef); -LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult); +LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult, int nres); LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize); LUAI_FUNC void luaD_growstack (lua_State *L, int n); LUAI_FUNC void luaD_shrinkstack (lua_State *L); diff --git a/src/ldump.c b/src/ldump.c index b6c7114..4c04812 100644 --- a/src/ldump.c +++ b/src/ldump.c @@ -1,5 +1,5 @@ /* -** $Id: ldump.c,v 2.34 2014/11/02 19:19:04 roberto Exp $ +** $Id: ldump.c,v 2.36 2015/03/30 15:43:51 roberto Exp $ ** save precompiled Lua chunks ** See Copyright Notice in lua.h */ @@ -74,14 +74,15 @@ static void DumpString (const TString *s, DumpState *D) { if (s == NULL) DumpByte(0, D); else { - size_t size = s->len + 1; /* include trailing '\0' */ + size_t size = tsslen(s) + 1; /* include trailing '\0' */ + const char *str = getstr(s); if (size < 0xFF) DumpByte(cast_int(size), D); else { DumpByte(0xFF, D); DumpVar(size, D); } - DumpVector(getstr(s), size - 1, D); /* no need to save '\0' */ + DumpVector(str, size - 1, D); /* no need to save '\0' */ } } diff --git a/src/lfunc.h b/src/lfunc.h index 256d3cf..2eeb0d5 100644 --- a/src/lfunc.h +++ b/src/lfunc.h @@ -1,5 +1,5 @@ /* -** $Id: lfunc.h,v 2.14 2014/06/19 18:27:20 roberto Exp $ +** $Id: lfunc.h,v 2.15 2015/01/13 15:49:11 roberto Exp $ ** Auxiliary functions to manipulate prototypes and closures ** See Copyright Notice in lua.h */ @@ -23,6 +23,13 @@ /* +** maximum number of upvalues in a closure (both C and Lua). (Value +** must fit in a VM register.) +*/ +#define MAXUPVAL 255 + + +/* ** Upvalues for Lua closures */ struct UpVal { @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 2.201 2014/12/20 13:58:15 roberto Exp $ +** $Id: lgc.c,v 2.205 2015/03/25 13:42:19 roberto Exp $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -83,8 +83,13 @@ #define markvalue(g,o) { checkconsistency(o); \ if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); } -#define markobject(g,t) \ - { if ((t) && iswhite(t)) reallymarkobject(g, obj2gco(t)); } +#define markobject(g,t) { if (iswhite(t)) reallymarkobject(g, obj2gco(t)); } + +/* +** mark an object that can be NULL (either because it is really optional, +** or it was stripped as debug info, or inside an uncompleted structure) +*/ +#define markobjectN(g,t) { if (t) markobject(g,t); } static void reallymarkobject (global_State *g, GCObject *o); @@ -226,15 +231,19 @@ static void reallymarkobject (global_State *g, GCObject *o) { reentry: white2gray(o); switch (o->tt) { - case LUA_TSHRSTR: + case LUA_TSHRSTR: { + gray2black(o); + g->GCmemtrav += sizelstring(gco2ts(o)->shrlen); + break; + } case LUA_TLNGSTR: { gray2black(o); - g->GCmemtrav += sizestring(gco2ts(o)); + g->GCmemtrav += sizelstring(gco2ts(o)->u.lnglen); break; } case LUA_TUSERDATA: { TValue uvalue; - markobject(g, gco2u(o)->metatable); /* mark its metatable */ + markobjectN(g, gco2u(o)->metatable); /* mark its metatable */ gray2black(o); g->GCmemtrav += sizeudata(gco2u(o)); getuservalue(g->mainthread, gco2u(o), &uvalue); @@ -275,7 +284,7 @@ static void reallymarkobject (global_State *g, GCObject *o) { static void markmt (global_State *g) { int i; for (i=0; i < LUA_NUMTAGS; i++) - markobject(g, g->mt[i]); + markobjectN(g, g->mt[i]); } @@ -437,7 +446,7 @@ static void traversestrongtable (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); + markobjectN(g, h->metatable); if (mode && ttisstring(mode) && /* is there a weak mode? */ ((weakkey = strchr(svalue(mode), 'k')), (weakvalue = strchr(svalue(mode), 'v')), @@ -457,19 +466,24 @@ static lu_mem traversetable (global_State *g, Table *h) { } +/* +** Traverse a prototype. (While a prototype is being build, its +** arrays can be larger than needed; the extra slots are filled with +** NULL, so the use of 'markobjectN') +*/ static int traverseproto (global_State *g, Proto *f) { int i; if (f->cache && iswhite(f->cache)) f->cache = NULL; /* allow cache to be collected */ - markobject(g, f->source); + markobjectN(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 */ - markobject(g, f->upvalues[i].name); + markobjectN(g, f->upvalues[i].name); for (i = 0; i < f->sizep; i++) /* mark nested protos */ - markobject(g, f->p[i]); + markobjectN(g, f->p[i]); for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */ - markobject(g, f->locvars[i].varname); + markobjectN(g, f->locvars[i].varname); return sizeof(Proto) + sizeof(Instruction) * f->sizecode + sizeof(Proto *) * f->sizep + sizeof(TValue) * f->sizek + @@ -494,7 +508,7 @@ static lu_mem traverseCclosure (global_State *g, CClosure *cl) { */ static lu_mem traverseLclosure (global_State *g, LClosure *cl) { int i; - markobject(g, cl->p); /* mark its prototype */ + markobjectN(g, cl->p); /* mark its prototype */ for (i = 0; i < cl->nupvalues; i++) { /* mark its upvalues */ UpVal *uv = cl->upvals[i]; if (uv != NULL) { @@ -689,9 +703,10 @@ static void freeobj (lua_State *L, GCObject *o) { case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break; case LUA_TSHRSTR: luaS_remove(L, gco2ts(o)); /* remove it from hash table */ - /* go through */ + luaM_freemem(L, o, sizelstring(gco2ts(o)->shrlen)); + break; case LUA_TLNGSTR: { - luaM_freemem(L, o, sizestring(gco2ts(o))); + luaM_freemem(L, o, sizelstring(gco2ts(o)->u.lnglen)); break; } default: lua_assert(0); @@ -1002,6 +1017,7 @@ static l_mem atomic (lua_State *L) { /* clear values from resurrected weak tables */ clearvalues(g, g->weak, origweak); clearvalues(g, g->allweak, origall); + luaS_clearcache(g); g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ work += g->GCmemtrav; /* complete counting */ return work; /* estimate of memory marked by 'atomic' */ diff --git a/src/liolib.c b/src/liolib.c index 4dea396..193cac6 100644 --- a/src/liolib.c +++ b/src/liolib.c @@ -1,5 +1,5 @@ /* -** $Id: liolib.c,v 2.142 2015/01/02 12:50:28 roberto Exp $ +** $Id: liolib.c,v 2.144 2015/04/03 18:41:57 roberto Exp $ ** Standard I/O (and system) library ** See Copyright Notice in lua.h */ @@ -410,12 +410,6 @@ static int readdigits (RN *rn, int hex) { } -/* access to locale "radix character" (decimal point) */ -#if !defined(l_getlocaledecpoint) -#define l_getlocaledecpoint() (localeconv()->decimal_point[0]) -#endif - - /* ** Read a number: first reads a valid prefix of a numeral into a buffer. ** Then it calls 'lua_stringtonumber' to check whether the format is @@ -425,9 +419,10 @@ static int read_number (lua_State *L, FILE *f) { RN rn; int count = 0; int hex = 0; - char decp[2] = "."; + char decp[2]; rn.f = f; rn.n = 0; - decp[0] = l_getlocaledecpoint(); /* get decimal point from locale */ + decp[0] = lua_getlocaledecpoint(); /* get decimal point from locale */ + decp[1] = '\0'; l_lockfile(rn.f); do { rn.c = l_getc(rn.f); } while (isspace(rn.c)); /* skip spaces */ test2(&rn, "-+"); /* optional signal */ @@ -457,7 +452,7 @@ static int read_number (lua_State *L, FILE *f) { static int test_eof (lua_State *L, FILE *f) { int c = getc(f); ungetc(c, f); /* no-op when c == EOF */ - lua_pushlstring(L, NULL, 0); + lua_pushliteral(L, ""); return (c != EOF); } @@ -1,5 +1,5 @@ /* -** $Id: llex.c,v 2.89 2014/11/14 16:06:09 roberto Exp $ +** $Id: llex.c,v 2.93 2015/05/22 17:45:56 roberto Exp $ ** Lexical Analyzer ** See Copyright Notice in lua.h */ @@ -16,6 +16,7 @@ #include "lua.h" #include "lctype.h" +#include "ldebug.h" #include "ldo.h" #include "lgc.h" #include "llex.h" @@ -68,7 +69,7 @@ static void save (LexState *ls, int c) { void luaX_init (lua_State *L) { int i; - TString *e = luaS_new(L, LUA_ENV); /* create env name */ + TString *e = luaS_newliteral(L, LUA_ENV); /* create env name */ luaC_fix(L, obj2gco(e)); /* never collect this name */ for (i=0; i<NUM_RESERVED; i++) { TString *ts = luaS_new(L, luaX_tokens[i]); @@ -106,9 +107,7 @@ static const char *txtToken (LexState *ls, int token) { static l_noret lexerror (LexState *ls, const char *msg, int token) { - char buff[LUA_IDSIZE]; - luaO_chunkid(buff, getstr(ls->source), LUA_IDSIZE); - msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg); + msg = luaG_addinfo(ls->L, msg, ls->source, ls->linenumber); if (token) luaO_pushfstring(ls->L, "%s near %s", msg, txtToken(ls, token)); luaD_throw(ls->L, LUA_ERRSYNTAX); @@ -172,7 +171,7 @@ void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source, ls->linenumber = 1; ls->lastline = 1; ls->source = source; - ls->envn = luaS_new(L, LUA_ENV); /* get env name */ + ls->envn = luaS_newliteral(L, LUA_ENV); /* get env name */ luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ } @@ -221,11 +220,6 @@ static void buffreplace (LexState *ls, char from, char to) { } -#if !defined(l_getlocaledecpoint) -#define l_getlocaledecpoint() (localeconv()->decimal_point[0]) -#endif - - #define buff2num(b,o) (luaO_str2num(luaZ_buffer(b), o) != 0) /* @@ -234,7 +228,7 @@ static void buffreplace (LexState *ls, char from, char to) { */ static void trydecpoint (LexState *ls, TValue *o) { char old = ls->decpoint; - ls->decpoint = l_getlocaledecpoint(); + ls->decpoint = lua_getlocaledecpoint(); buffreplace(ls, old, ls->decpoint); /* try new decimal separator */ if (!buff2num(ls->buff, o)) { /* format error with correct decimal point: no more options */ @@ -283,8 +277,9 @@ static int read_numeral (LexState *ls, SemInfo *seminfo) { /* -** skip a sequence '[=*[' or ']=*]' and return its number of '='s or -** -1 if sequence is malformed +** skip a sequence '[=*[' or ']=*]'; if sequence is wellformed, return +** its number of '='s; otherwise, return a negative number (-1 iff there +** are no '='s after initial bracket) */ static int skip_sep (LexState *ls) { int count = 0; @@ -501,8 +496,9 @@ static int llex (LexState *ls, SemInfo *seminfo) { read_long_string(ls, seminfo, sep); return TK_STRING; } - else if (sep == -1) return '['; - else lexerror(ls, "invalid long string delimiter", TK_STRING); + else if (sep != -1) /* '[=...' missing second bracket */ + lexerror(ls, "invalid long string delimiter", TK_STRING); + return '['; } case '=': { next(ls); diff --git a/src/llimits.h b/src/llimits.h index 8f71a6f..277c724 100644 --- a/src/llimits.h +++ b/src/llimits.h @@ -1,5 +1,5 @@ /* -** $Id: llimits.h,v 1.125 2014/12/19 13:30:23 roberto Exp $ +** $Id: llimits.h,v 1.135 2015/06/09 14:21:00 roberto Exp $ ** Limits, basic types, and some other 'installation-dependent' definitions ** See Copyright Notice in lua.h */ @@ -52,11 +52,11 @@ typedef unsigned char lu_byte; /* -** conversion of pointer to integer: +** conversion of pointer to unsigned integer: ** this is for hashing only; there is no problem if the integer ** cannot hold the whole pointer value */ -#define point2int(p) ((unsigned int)((size_t)(p) & UINT_MAX)) +#define point2uint(p) ((unsigned int)((size_t)(p) & UINT_MAX)) @@ -88,22 +88,20 @@ typedef LUAI_UACINT l_uacInt; /* ** assertion for checking API calls */ -#if defined(LUA_USE_APICHECK) -#include <assert.h> -#define luai_apicheck(e) assert(e) -#else -#define luai_apicheck(e) lua_assert(e) +#if !defined(luai_apicheck) +#define luai_apicheck(l,e) lua_assert(e) #endif - -#define api_check(e,msg) luai_apicheck((e) && msg) +#define api_check(l,e,msg) luai_apicheck(l,(e) && msg) +/* macro to avoid warnings about unused variables */ #if !defined(UNUSED) -#define UNUSED(x) ((void)(x)) /* to avoid warnings */ +#define UNUSED(x) ((void)(x)) #endif +/* type casts (a macro highlights casts in the code) */ #define cast(t, exp) ((t)(exp)) #define cast_void(i) cast(void, (i)) @@ -149,11 +147,6 @@ typedef LUAI_UACINT l_uacInt; #define LUAI_MAXCCALLS 200 #endif -/* -** maximum number of upvalues in a closure (both C and Lua). (Value -** must fit in an unsigned char.) -*/ -#define MAXUPVAL UCHAR_MAX /* @@ -168,10 +161,33 @@ typedef unsigned long Instruction; +/* +** Maximum length for short strings, that is, strings that are +** internalized. (Cannot be smaller than reserved words or tags for +** metamethods, as these strings must be internalized; +** #("function") = 8, #("__newindex") = 10.) +*/ +#if !defined(LUAI_MAXSHORTLEN) +#define LUAI_MAXSHORTLEN 40 +#endif + -/* minimum size for the string table (must be power of 2) */ +/* +** Initial size for the string table (must be power of 2). +** The Lua core alone registers ~50 strings (reserved words + +** metaevent keys + a few others). Libraries would typically add +** a few dozens more. +*/ #if !defined(MINSTRTABSIZE) -#define MINSTRTABSIZE 64 /* minimum size for "predefined" strings */ +#define MINSTRTABSIZE 128 +#endif + + +/* +** Size of cache for strings in the API (better be a prime) +*/ +#if !defined(STRCACHE_SIZE) +#define STRCACHE_SIZE 127 #endif @@ -181,11 +197,19 @@ typedef unsigned long Instruction; #endif +/* +** macros that are executed whenether program enters the Lua core +** ('lua_lock') and leaves the core ('lua_unlock') +*/ #if !defined(lua_lock) #define lua_lock(L) ((void) 0) #define lua_unlock(L) ((void) 0) #endif +/* +** macro executed during Lua functions at points where the +** function can yield. +*/ #if !defined(luai_threadyield) #define luai_threadyield(L) {lua_unlock(L); lua_lock(L);} #endif @@ -223,6 +247,53 @@ typedef unsigned long Instruction; /* +** The luai_num* macros define the primitive operations over numbers. +*/ + +/* floor division (defined as 'floor(a/b)') */ +#if !defined(luai_numidiv) +#define luai_numidiv(L,a,b) ((void)L, l_floor(luai_numdiv(L,a,b))) +#endif + +/* float division */ +#if !defined(luai_numdiv) +#define luai_numdiv(L,a,b) ((a)/(b)) +#endif + +/* +** modulo: defined as 'a - floor(a/b)*b'; this definition gives NaN when +** 'b' is huge, but the result should be 'a'. 'fmod' gives the result of +** 'a - trunc(a/b)*b', and therefore must be corrected when 'trunc(a/b) +** ~= floor(a/b)'. That happens when the division has a non-integer +** negative result, which is equivalent to the test below. +*/ +#if !defined(luai_nummod) +#define luai_nummod(L,a,b,m) \ + { (m) = l_mathop(fmod)(a,b); if ((m)*(b) < 0) (m) += (b); } +#endif + +/* exponentiation */ +#if !defined(luai_numpow) +#define luai_numpow(L,a,b) ((void)L, l_mathop(pow)(a,b)) +#endif + +/* the others are quite standard operations */ +#if !defined(luai_numadd) +#define luai_numadd(L,a,b) ((a)+(b)) +#define luai_numsub(L,a,b) ((a)-(b)) +#define luai_nummul(L,a,b) ((a)*(b)) +#define luai_numunm(L,a) (-(a)) +#define luai_numeq(a,b) ((a)==(b)) +#define luai_numlt(a,b) ((a)<(b)) +#define luai_numle(a,b) ((a)<=(b)) +#define luai_numisnan(a) (!luai_numeq((a), (a))) +#endif + + + + + +/* ** macro to control inclusion of some hard tests on stack reallocation */ #if !defined(HARDSTACKTESTS) diff --git a/src/lmathlib.c b/src/lmathlib.c index 002c508..4f2ec60 100644 --- a/src/lmathlib.c +++ b/src/lmathlib.c @@ -1,5 +1,5 @@ /* -** $Id: lmathlib.c,v 1.114 2014/12/27 20:32:26 roberto Exp $ +** $Id: lmathlib.c,v 1.115 2015/03/12 14:04:04 roberto Exp $ ** Standard mathematical library ** See Copyright Notice in lua.h */ @@ -183,6 +183,9 @@ static int math_log (lua_State *L) { res = l_mathop(log)(x); else { lua_Number base = luaL_checknumber(L, 2); +#if !defined(LUA_USE_C89) + if (base == 2.0) res = l_mathop(log2)(x); else +#endif if (base == 10.0) res = l_mathop(log10)(x); else res = l_mathop(log)(x)/l_mathop(log)(base); } @@ -1,5 +1,5 @@ /* -** $Id: lmem.c,v 1.89 2014/11/02 19:33:33 roberto Exp $ +** $Id: lmem.c,v 1.91 2015/03/06 19:45:54 roberto Exp $ ** Interface to Memory Manager ** See Copyright Notice in lua.h */ @@ -85,10 +85,11 @@ void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { #endif newblock = (*g->frealloc)(g->ud, block, osize, nsize); if (newblock == NULL && nsize > 0) { - api_check( nsize > realosize, - "realloc cannot fail when shrinking a block"); - luaC_fullgc(L, 1); /* try to free some memory... */ - newblock = (*g->frealloc)(g->ud, block, osize, nsize); /* try again */ + lua_assert(nsize > realosize); /* cannot fail when shrinking a block */ + if (g->version) { /* is state fully built? */ + luaC_fullgc(L, 1); /* try to free some memory... */ + newblock = (*g->frealloc)(g->ud, block, osize, nsize); /* try again */ + } if (newblock == NULL) luaD_throw(L, LUA_ERRMEM); } diff --git a/src/loadlib.c b/src/loadlib.c index 7f8d990..bbf8f67 100644 --- a/src/loadlib.c +++ b/src/loadlib.c @@ -1,5 +1,5 @@ /* -** $Id: loadlib.c,v 1.124 2015/01/05 13:51:39 roberto Exp $ +** $Id: loadlib.c,v 1.126 2015/02/16 13:14:33 roberto Exp $ ** Dynamic library loader for Lua ** See Copyright Notice in lua.h ** @@ -14,6 +14,7 @@ #include "lprefix.h" +#include <stdio.h> #include <stdlib.h> #include <string.h> @@ -136,8 +137,8 @@ static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym); #include <dlfcn.h> /* -** Macro to covert pointer to void* to pointer to function. This cast -** is undefined according to ISO C, but POSIX assumes that it must work. +** Macro to convert pointer-to-void* to pointer-to-function. This cast +** is undefined according to ISO C, but POSIX assumes that it works. ** (The '__extension__' in gnu compilers is only to avoid warnings.) */ #if defined(__GNUC__) diff --git a/src/lobject.c b/src/lobject.c index 6a24aff..6c53b98 100644 --- a/src/lobject.c +++ b/src/lobject.c @@ -1,5 +1,5 @@ /* -** $Id: lobject.c,v 2.101 2014/12/26 14:43:45 roberto Exp $ +** $Id: lobject.c,v 2.104 2015/04/11 18:30:08 roberto Exp $ ** Some generic functions over Lua objects ** See Copyright Notice in lua.h */ @@ -10,6 +10,8 @@ #include "lprefix.h" +#include <locale.h> +#include <math.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> @@ -39,8 +41,12 @@ LUAI_DDEF const TValue luaO_nilobject_ = {NILCONSTANT}; int luaO_int2fb (unsigned int x) { int e = 0; /* exponent */ if (x < 8) return x; - while (x >= 0x10) { - x = (x+1) >> 1; + while (x >= (8 << 4)) { /* coarse steps */ + x = (x + 0xf) >> 4; /* x = ceil(x / 16) */ + e += 4; + } + while (x >= (8 << 1)) { /* fine steps */ + x = (x + 1) >> 1; /* x = ceil(x / 2) */ e++; } return ((e+1) << 3) | (cast_int(x) - 8); @@ -55,8 +61,11 @@ int luaO_fb2int (int x) { } +/* +** Computes ceil(log2(x)) +*/ int luaO_ceillog2 (unsigned int x) { - static const lu_byte log_2[256] = { + static const lu_byte log_2[256] = { /* log_2[i] = ceil(log2(i - 1)) */ 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, @@ -149,13 +158,13 @@ void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2, } /* could not perform raw operation; try metamethod */ lua_assert(L != NULL); /* should not fail when folding (compile time) */ - luaT_trybinTM(L, p1, p2, res, cast(TMS, op - LUA_OPADD + TM_ADD)); + luaT_trybinTM(L, p1, p2, res, cast(TMS, (op - LUA_OPADD) + TM_ADD)); } int luaO_hexavalue (int c) { if (lisdigit(c)) return c - '0'; - else return ltolower(c) - 'a' + 10; + else return (ltolower(c) - 'a') + 10; } @@ -172,9 +181,8 @@ static int isneg (const char **s) { ** Lua's implementation for 'lua_strx2number' ** =================================================================== */ -#if !defined(lua_strx2number) -#include <math.h> +#if !defined(lua_strx2number) /* maximum number of significant digits to read (to avoid overflows even with single floats) */ @@ -185,21 +193,22 @@ static int isneg (const char **s) { ** C99 specification for 'strtod' */ static lua_Number lua_strx2number (const char *s, char **endptr) { + int dot = lua_getlocaledecpoint(); lua_Number r = 0.0; /* result (accumulator) */ int sigdig = 0; /* number of significant digits */ int nosigdig = 0; /* number of non-significant digits */ int e = 0; /* exponent correction */ int neg; /* 1 if number is negative */ - int dot = 0; /* true after seen a dot */ + int hasdot = 0; /* true after seen a dot */ *endptr = cast(char *, s); /* nothing is valid yet */ while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ neg = isneg(&s); /* check signal */ if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */ return 0.0; /* invalid format (no '0x') */ for (s += 2; ; s++) { /* skip '0x' and read numeral */ - if (*s == '.') { - if (dot) break; /* second dot? stop loop */ - else dot = 1; + if (*s == dot) { + if (hasdot) break; /* second dot? stop loop */ + else hasdot = 1; } else if (lisxdigit(cast_uchar(*s))) { if (sigdig == 0 && *s == '0') /* non-significant digit (zero)? */ @@ -207,7 +216,7 @@ static lua_Number lua_strx2number (const char *s, char **endptr) { else if (++sigdig <= MAXSIGDIG) /* can read it without overflow? */ r = (r * cast_num(16.0)) + luaO_hexavalue(*s); else e++; /* too many digits; ignore, but still count for exponent */ - if (dot) e--; /* decimal digit? correct exponent */ + if (hasdot) e--; /* decimal digit? correct exponent */ } else break; /* neither a dot nor a digit */ } @@ -244,7 +253,7 @@ static const char *l_str2d (const char *s, lua_Number *result) { *result = lua_strx2number(s, &endptr); else *result = lua_str2number(s, &endptr); - if (endptr == s) return 0; /* nothing recognized */ + if (endptr == s) return NULL; /* nothing recognized */ while (lisspace(cast_uchar(*endptr))) endptr++; return (*endptr == '\0' ? endptr : NULL); /* OK if no trailing characters */ } @@ -290,7 +299,7 @@ size_t luaO_str2num (const char *s, TValue *o) { } else return 0; /* conversion failed */ - return (e - s + 1); /* success; return string size */ + return (e - s) + 1; /* success; return string size */ } @@ -329,7 +338,7 @@ void luaO_tostring (lua_State *L, StkId obj) { len = lua_number2str(buff, fltvalue(obj)); #if !defined(LUA_COMPAT_FLOATSTRING) if (buff[strspn(buff, "-0123456789")] == '\0') { /* looks like an int? */ - buff[len++] = '.'; + buff[len++] = lua_getlocaledecpoint(); buff[len++] = '0'; /* adds '.0' to result */ } #endif diff --git a/src/lobject.h b/src/lobject.h index d7d0ebf..9230b7a 100644 --- a/src/lobject.h +++ b/src/lobject.h @@ -1,5 +1,5 @@ /* -** $Id: lobject.h,v 2.106 2015/01/05 13:52:37 roberto Exp $ +** $Id: lobject.h,v 2.111 2015/06/09 14:21:42 roberto Exp $ ** Type definitions for Lua objects ** See Copyright Notice in lua.h */ @@ -35,8 +35,6 @@ ** bit 6: whether value is collectable */ -#define VARBITS (3 << 4) - /* ** LUA_TFUNCTION variants: @@ -190,9 +188,15 @@ typedef struct lua_TValue TValue; #define setfltvalue(obj,x) \ { TValue *io=(obj); val_(io).n=(x); settt_(io, LUA_TNUMFLT); } +#define chgfltvalue(obj,x) \ + { TValue *io=(obj); lua_assert(ttisfloat(io)); val_(io).n=(x); } + #define setivalue(obj,x) \ { TValue *io=(obj); val_(io).i=(x); settt_(io, LUA_TNUMINT); } +#define chgivalue(obj,x) \ + { TValue *io=(obj); lua_assert(ttisinteger(io)); val_(io).i=(x); } + #define setnilvalue(obj) settt_(obj, LUA_TNIL) #define setfvalue(obj,x) \ @@ -303,9 +307,12 @@ typedef TValue *StkId; /* index to stack elements */ typedef struct TString { CommonHeader; lu_byte extra; /* reserved words for short strings; "has hash" for longs */ + lu_byte shrlen; /* length for short strings */ unsigned int hash; - size_t len; /* number of characters in string */ - struct TString *hnext; /* linked list for hash table */ + union { + size_t lnglen; /* length for long strings */ + struct TString *hnext; /* linked list for hash table */ + } u; } TString; @@ -329,6 +336,12 @@ typedef union UTString { /* get the actual string (array of bytes) from a Lua value */ #define svalue(o) getstr(tsvalue(o)) +/* get string length from 'TString *s' */ +#define tsslen(s) ((s)->tt == LUA_TSHRSTR ? (s)->shrlen : (s)->u.lnglen) + +/* get string length from 'TValue *o' */ +#define vslen(o) tsslen(tsvalue(o)) + /* ** Header for userdata; memory area follows the end of this structure @@ -361,13 +374,13 @@ typedef union UUdata { #define setuservalue(L,u,o) \ { const TValue *io=(o); Udata *iu = (u); \ - iu->user_ = io->value_; iu->ttuv_ = io->tt_; \ + iu->user_ = io->value_; iu->ttuv_ = rttype(io); \ checkliveness(G(L),io); } #define getuservalue(L,u,o) \ { TValue *io=(o); const Udata *iu = (u); \ - io->value_ = iu->user_; io->tt_ = iu->ttuv_; \ + io->value_ = iu->user_; settt_(io, iu->ttuv_); \ checkliveness(G(L),io); } @@ -376,7 +389,7 @@ typedef union UUdata { */ typedef struct Upvaldesc { TString *name; /* upvalue name (for debug information) */ - lu_byte instack; /* whether it is in stack */ + lu_byte instack; /* whether it is in stack (register) */ lu_byte idx; /* index of upvalue (in stack or in outer function's list) */ } Upvaldesc; @@ -399,7 +412,7 @@ typedef struct Proto { CommonHeader; lu_byte numparams; /* number of fixed parameters */ lu_byte is_vararg; - lu_byte maxstacksize; /* maximum stack used by this function */ + lu_byte maxstacksize; /* number of registers needed by this function */ int sizeupvalues; /* size of 'upvalues' */ int sizek; /* size of 'k' */ int sizecode; @@ -409,12 +422,12 @@ typedef struct Proto { int linedefined; int lastlinedefined; TValue *k; /* constants used by the function */ - Instruction *code; + Instruction *code; /* opcodes */ struct Proto **p; /* functions defined inside the function */ int *lineinfo; /* map from opcodes to source lines (debug information) */ LocVar *locvars; /* information about local variables (debug information) */ Upvaldesc *upvalues; /* upvalue information */ - struct LClosure *cache; /* last created closure with this prototype */ + struct LClosure *cache; /* last-created closure with this prototype */ TString *source; /* used for debug information */ GCObject *gclist; } Proto; diff --git a/src/loslib.c b/src/loslib.c index 20359b2..cb8a3c3 100644 --- a/src/loslib.c +++ b/src/loslib.c @@ -1,5 +1,5 @@ /* -** $Id: loslib.c,v 1.54 2014/12/26 14:46:07 roberto Exp $ +** $Id: loslib.c,v 1.57 2015/04/10 17:41:04 roberto Exp $ ** Standard Operating System library ** See Copyright Notice in lua.h */ @@ -22,10 +22,12 @@ #include "lualib.h" -#if !defined(LUA_STRFTIMEOPTIONS) /* { */ /* +** {================================================================== ** list of valid conversion specifiers for the 'strftime' function +** =================================================================== */ +#if !defined(LUA_STRFTIMEOPTIONS) /* { */ #if defined(LUA_USE_C89) #define LUA_STRFTIMEOPTIONS { "aAbBcdHIjmMpSUwWxXyYz%", "" } @@ -37,8 +39,14 @@ #endif #endif /* } */ +/* }================================================================== */ +/* +** {================================================================== +** Configuration for time-related stuff +** =================================================================== +*/ #if !defined(l_time_t) /* { */ /* @@ -51,12 +59,38 @@ #endif /* } */ +#if !defined(l_gmtime) /* { */ +/* +** By default, Lua uses gmtime/localtime, except when POSIX is available, +** where it uses gmtime_r/localtime_r +*/ + +#if defined(LUA_USE_POSIX) /* { */ + +#define l_gmtime(t,r) gmtime_r(t,r) +#define l_localtime(t,r) localtime_r(t,r) + +#else /* }{ */ + +/* ISO C definitions */ +#define l_gmtime(t,r) ((void)(r)->tm_sec, gmtime(t)) +#define l_localtime(t,r) ((void)(r)->tm_sec, localtime(t)) + +#endif /* } */ + +#endif /* } */ + +/* }================================================================== */ + -#if !defined(lua_tmpnam) /* { */ /* -** By default, Lua uses tmpnam except when POSIX is available, where it -** uses mkstemp. +** {================================================================== +** Configuration for 'tmpnam': +** By default, Lua uses tmpnam except when POSIX is available, where +** it uses mkstemp. +** =================================================================== */ +#if !defined(lua_tmpnam) /* { */ #if defined(LUA_USE_POSIX) /* { */ @@ -83,31 +117,10 @@ #endif /* } */ #endif /* } */ +/* }================================================================== */ -#if !defined(l_gmtime) /* { */ -/* -** By default, Lua uses gmtime/localtime, except when POSIX is available, -** where it uses gmtime_r/localtime_r -*/ - -#if defined(LUA_USE_POSIX) /* { */ - -#define l_gmtime(t,r) gmtime_r(t,r) -#define l_localtime(t,r) localtime_r(t,r) - -#else /* }{ */ - -/* ISO C definitions */ -#define l_gmtime(t,r) ((void)(r)->tm_sec, gmtime(t)) -#define l_localtime(t,r) ((void)(r)->tm_sec, localtime(t)) - -#endif /* } */ - -#endif /* } */ - - static int os_execute (lua_State *L) { const char *cmd = luaL_optstring(L, 1, NULL); @@ -287,7 +300,7 @@ static int os_time (lua_State *L) { t = mktime(&ts); } if (t != (time_t)(l_timet)t) - luaL_error(L, "time result cannot be represented in this Lua instalation"); + luaL_error(L, "time result cannot be represented in this Lua installation"); else if (t == (time_t)(-1)) lua_pushnil(L); else @@ -297,8 +310,9 @@ static int os_time (lua_State *L) { static int os_difftime (lua_State *L) { - double res = difftime((l_checktime(L, 1)), (l_checktime(L, 2))); - lua_pushnumber(L, (lua_Number)res); + time_t t1 = l_checktime(L, 1); + time_t t2 = l_checktime(L, 2); + lua_pushnumber(L, (lua_Number)difftime(t1, t2)); return 1; } diff --git a/src/lstate.c b/src/lstate.c index ff6b02d..12e51d2 100644 --- a/src/lstate.c +++ b/src/lstate.c @@ -1,5 +1,5 @@ /* -** $Id: lstate.c,v 2.127 2014/11/02 19:33:33 roberto Exp $ +** $Id: lstate.c,v 2.128 2015/03/04 13:31:21 roberto Exp $ ** Global State ** See Copyright Notice in lua.h */ @@ -37,9 +37,6 @@ #endif -#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. @@ -200,12 +197,9 @@ static void f_luaopen (lua_State *L, void *ud) { UNUSED(ud); stack_init(L, L); /* init stack */ init_registry(L, g); - luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ + luaS_init(L); luaT_init(L); luaX_init(L); - /* pre-create memory-error message */ - g->memerrmsg = luaS_newliteral(L, MEMERRMSG); - luaC_fix(L, obj2gco(g->memerrmsg)); /* it should never be collected */ g->gcrunning = 1; /* allow gc */ g->version = lua_version(NULL); luai_userstateopen(L); diff --git a/src/lstate.h b/src/lstate.h index 81e12c4..eefc217 100644 --- a/src/lstate.h +++ b/src/lstate.h @@ -1,5 +1,5 @@ /* -** $Id: lstate.h,v 2.119 2014/10/30 18:53:28 roberto Exp $ +** $Id: lstate.h,v 2.122 2015/06/01 16:34:37 roberto Exp $ ** Global State ** See Copyright Notice in lua.h */ @@ -94,6 +94,7 @@ typedef struct CallInfo { #define CIST_YPCALL (1<<4) /* call is a yieldable protected call */ #define CIST_TAIL (1<<5) /* call was tail called */ #define CIST_HOOKYIELD (1<<6) /* last hook called yielded */ +#define CIST_LEQ (1<<7) /* using __lt for __le */ #define isLua(ci) ((ci)->callstatus & CIST_LUA) @@ -140,6 +141,7 @@ typedef struct global_State { TString *memerrmsg; /* memory-error message */ TString *tmname[TM_N]; /* array with tag-method names */ struct Table *mt[LUA_NUMTAGS]; /* metatables for basic types */ + TString *strcache[STRCACHE_SIZE][1]; /* cache for strings in API */ } global_State; diff --git a/src/lstring.c b/src/lstring.c index 2947113..5e0e3c4 100644 --- a/src/lstring.c +++ b/src/lstring.c @@ -1,5 +1,5 @@ /* -** $Id: lstring.c,v 2.45 2014/11/02 19:19:04 roberto Exp $ +** $Id: lstring.c,v 2.49 2015/06/01 16:34:37 roberto Exp $ ** String table (keeps all strings handled by Lua) ** See Copyright Notice in lua.h */ @@ -22,6 +22,8 @@ #include "lstring.h" +#define MEMERRMSG "not enough memory" + /* ** Lua will use at most ~(2^LUAI_HASHLIMIT) bytes from a string to @@ -36,10 +38,10 @@ ** equality for long strings */ int luaS_eqlngstr (TString *a, TString *b) { - size_t len = a->len; + size_t len = a->u.lnglen; lua_assert(a->tt == LUA_TLNGSTR && b->tt == LUA_TLNGSTR); return (a == b) || /* same instance or... */ - ((len == b->len) && /* equal length and ... */ + ((len == b->u.lnglen) && /* equal length and ... */ (memcmp(getstr(a), getstr(b), len) == 0)); /* equal contents */ } @@ -69,9 +71,9 @@ void luaS_resize (lua_State *L, int newsize) { TString *p = tb->hash[i]; tb->hash[i] = NULL; while (p) { /* for each node in the list */ - TString *hnext = p->hnext; /* save next */ + TString *hnext = p->u.hnext; /* save next */ unsigned int h = lmod(p->hash, newsize); /* new position */ - p->hnext = tb->hash[h]; /* chain it */ + p->u.hnext = tb->hash[h]; /* chain it */ tb->hash[h] = p; p = hnext; } @@ -85,6 +87,34 @@ void luaS_resize (lua_State *L, int newsize) { } +/* +** Clear API string cache. (Entries cannot be empty, so fill them with +** a non-collectable string.) +*/ +void luaS_clearcache (global_State *g) { + int i; + for (i = 0; i < STRCACHE_SIZE; i++) { + if (iswhite(g->strcache[i][0])) /* will entry be collected? */ + g->strcache[i][0] = g->memerrmsg; /* replace it with something fixed */ + } +} + + +/* +** Initialize the string table and the string cache +*/ +void luaS_init (lua_State *L) { + global_State *g = G(L); + int i; + luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ + /* pre-create memory-error message */ + g->memerrmsg = luaS_newliteral(L, MEMERRMSG); + luaC_fix(L, obj2gco(g->memerrmsg)); /* it should never be collected */ + for (i = 0; i < STRCACHE_SIZE; i++) /* fill cache with valid strings */ + g->strcache[i][0] = g->memerrmsg; +} + + /* ** creates a new string object @@ -97,7 +127,6 @@ static TString *createstrobj (lua_State *L, const char *str, size_t l, totalsize = sizelstring(l); o = luaC_newobj(L, tag, totalsize); ts = gco2ts(o); - ts->len = l; ts->hash = h; ts->extra = 0; memcpy(getaddrstr(ts), str, l * sizeof(char)); @@ -110,8 +139,8 @@ void luaS_remove (lua_State *L, TString *ts) { stringtable *tb = &G(L)->strt; TString **p = &tb->hash[lmod(ts->hash, tb->size)]; while (*p != ts) /* find previous element */ - p = &(*p)->hnext; - *p = (*p)->hnext; /* remove element from its list */ + p = &(*p)->u.hnext; + *p = (*p)->u.hnext; /* remove element from its list */ tb->nuse--; } @@ -124,8 +153,8 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) { global_State *g = G(L); unsigned int h = luaS_hash(str, l, g->seed); TString **list = &g->strt.hash[lmod(h, g->strt.size)]; - for (ts = *list; ts != NULL; ts = ts->hnext) { - if (l == ts->len && + for (ts = *list; ts != NULL; ts = ts->u.hnext) { + if (l == ts->shrlen && (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) { /* found! */ if (isdead(g, ts)) /* dead (but not collected yet)? */ @@ -138,7 +167,8 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) { list = &g->strt.hash[lmod(h, g->strt.size)]; /* recompute with new size */ } ts = createstrobj(L, str, l, LUA_TSHRSTR, h); - ts->hnext = *list; + ts->shrlen = cast_byte(l); + ts->u.hnext = *list; *list = ts; g->strt.nuse++; return ts; @@ -152,18 +182,32 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { if (l <= LUAI_MAXSHORTLEN) /* short string? */ return internshrstr(L, str, l); else { + TString *ts; if (l + 1 > (MAX_SIZE - sizeof(TString))/sizeof(char)) luaM_toobig(L); - return createstrobj(L, str, l, LUA_TLNGSTR, G(L)->seed); + ts = createstrobj(L, str, l, LUA_TLNGSTR, G(L)->seed); + ts->u.lnglen = l; + return ts; } } /* -** new zero-terminated string +** Create or reuse a zero-terminated string, first checking in the +** cache (using the string address as a key). The cache can contain +** only zero-terminated strings, so it is safe to use 'strcmp' to +** check hits. */ TString *luaS_new (lua_State *L, const char *str) { - return luaS_newlstr(L, str, strlen(str)); + unsigned int i = point2uint(str) % STRCACHE_SIZE; /* hash */ + TString **p = G(L)->strcache[i]; + if (strcmp(str, getstr(p[0])) == 0) /* hit? */ + return p[0]; /* that it is */ + else { /* normal route */ + TString *s = luaS_newlstr(L, str, strlen(str)); + p[0] = s; + return s; + } } diff --git a/src/lstring.h b/src/lstring.h index d3f04ca..e746f5f 100644 --- a/src/lstring.h +++ b/src/lstring.h @@ -1,5 +1,5 @@ /* -** $Id: lstring.h,v 1.56 2014/07/18 14:46:47 roberto Exp $ +** $Id: lstring.h,v 1.59 2015/03/25 13:42:19 roberto Exp $ ** String table (keep all strings handled by Lua) ** See Copyright Notice in lua.h */ @@ -13,7 +13,6 @@ #define sizelstring(l) (sizeof(union UTString) + ((l) + 1) * sizeof(char)) -#define sizestring(s) sizelstring((s)->len) #define sizeludata(l) (sizeof(union UUdata) + (l)) #define sizeudata(u) sizeludata((u)->len) @@ -37,6 +36,8 @@ 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 void luaS_resize (lua_State *L, int newsize); +LUAI_FUNC void luaS_clearcache (global_State *g); +LUAI_FUNC void luaS_init (lua_State *L); LUAI_FUNC void luaS_remove (lua_State *L, TString *ts); LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s); 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 a650b76..19c350d 100644 --- a/src/lstrlib.c +++ b/src/lstrlib.c @@ -1,5 +1,5 @@ /* -** $Id: lstrlib.c,v 1.221 2014/12/11 14:03:07 roberto Exp $ +** $Id: lstrlib.c,v 1.229 2015/05/20 17:39:23 roberto Exp $ ** Standard library for string operations and pattern-matching ** See Copyright Notice in lua.h */ @@ -11,6 +11,7 @@ #include <ctype.h> +#include <float.h> #include <limits.h> #include <stddef.h> #include <stdio.h> @@ -70,7 +71,7 @@ static int str_sub (lua_State *L) { if (start < 1) start = 1; if (end > (lua_Integer)l) end = l; if (start <= end) - lua_pushlstring(L, s + start - 1, (size_t)(end - start + 1)); + lua_pushlstring(L, s + start - 1, (size_t)(end - start) + 1); else lua_pushliteral(L, ""); return 1; } @@ -149,9 +150,9 @@ static int str_byte (lua_State *L) { if (posi < 1) posi = 1; if (pose > (lua_Integer)l) pose = l; if (posi > pose) return 0; /* empty interval; return no values */ - n = (int)(pose - posi + 1); - if (posi + n <= pose) /* arithmetic overflow? */ + if (pose - posi >= INT_MAX) /* arithmetic overflow? */ return luaL_error(L, "string slice too long"); + n = (int)(pose - posi) + 1; luaL_checkstack(L, n, "string slice too long"); for (i=0; i<n; i++) lua_pushinteger(L, uchar(s[posi+i-1])); @@ -499,7 +500,7 @@ static const char *match (MatchState *ms, const char *s, const char *p) { } case '+': /* 1 or more repetitions */ s++; /* 1 match already done */ - /* go through */ + /* FALLTHROUGH */ case '*': /* 0 or more repetitions */ s = max_expand(ms, s, p, ep); break; @@ -554,7 +555,7 @@ static void push_onecapture (MatchState *ms, int i, const char *s, ptrdiff_t l = ms->capture[i].len; if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture"); if (l == CAP_POSITION) - lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1); + lua_pushinteger(ms->L, (ms->capture[i].init - ms->src_init) + 1); else lua_pushlstring(ms->L, ms->capture[i].init, l); } @@ -598,8 +599,8 @@ static int str_find_aux (lua_State *L, int find) { /* do a plain search */ const char *s2 = lmemfind(s + init - 1, ls - (size_t)init + 1, p, lp); if (s2) { - lua_pushinteger(L, s2 - s + 1); - lua_pushinteger(L, s2 - s + lp); + lua_pushinteger(L, (s2 - s) + 1); + lua_pushinteger(L, (s2 - s) + lp); return 2; } } @@ -621,7 +622,7 @@ static int str_find_aux (lua_State *L, int find) { lua_assert(ms.matchdepth == MAXCCALLS); if ((res=match(&ms, s1, p)) != NULL) { if (find) { - lua_pushinteger(L, s1 - s + 1); /* start */ + lua_pushinteger(L, (s1 - s) + 1); /* start */ lua_pushinteger(L, res - s); /* end */ return push_captures(&ms, NULL, 0) + 2; } @@ -797,17 +798,100 @@ static int str_gsub (lua_State *L) { ** ======================================================= */ -/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ -#define MAX_ITEM 512 +#if !defined(lua_number2strx) /* { */ + +/* +** Hexadecimal floating-point formatter +*/ + +#include <locale.h> +#include <math.h> + +#define SIZELENMOD (sizeof(LUA_NUMBER_FRMLEN)/sizeof(char)) + + +/* +** Number of bits that goes into the first digit. It can be any value +** between 1 and 4; the following definition tries to align the number +** to nibble boundaries by making what is left after that first digit a +** multiple of 4. +*/ +#define L_NBFD ((l_mathlim(MANT_DIG) - 1)%4 + 1) + + +/* +** Add integer part of 'x' to buffer and return new 'x' +*/ +static lua_Number adddigit (char *buff, int n, lua_Number x) { + lua_Number dd = l_mathop(floor)(x); /* get integer part from 'x' */ + int d = (int)dd; + buff[n] = (d < 10 ? d + '0' : d - 10 + 'a'); /* add to buffer */ + return x - dd; /* return what is left */ +} + + +static int num2straux (char *buff, lua_Number x) { + if (x != x || x == HUGE_VAL || x == -HUGE_VAL) /* inf or NaN? */ + return sprintf(buff, LUA_NUMBER_FMT, x); /* equal to '%g' */ + else if (x == 0) { /* can be -0... */ + sprintf(buff, LUA_NUMBER_FMT, x); + strcat(buff, "x0p+0"); /* reuses '0/-0' from 'sprintf'... */ + return strlen(buff); + } + else { + int e; + lua_Number m = l_mathop(frexp)(x, &e); /* 'x' fraction and exponent */ + int n = 0; /* character count */ + if (m < 0) { /* is number negative? */ + buff[n++] = '-'; /* add signal */ + m = -m; /* make it positive */ + } + buff[n++] = '0'; buff[n++] = 'x'; /* add "0x" */ + m = adddigit(buff, n++, m * (1 << L_NBFD)); /* add first digit */ + e -= L_NBFD; /* this digit goes before the radix point */ + if (m > 0) { /* more digits? */ + buff[n++] = lua_getlocaledecpoint(); /* add radix point */ + do { /* add as many digits as needed */ + m = adddigit(buff, n++, m * 16); + } while (m > 0); + } + n += sprintf(buff + n, "p%+d", e); /* add exponent */ + return n; + } +} + + +static int lua_number2strx (lua_State *L, char *buff, const char *fmt, + lua_Number x) { + int n = num2straux(buff, x); + if (fmt[SIZELENMOD] == 'A') { + int i; + for (i = 0; i < n; i++) + buff[i] = toupper(uchar(buff[i])); + } + else if (fmt[SIZELENMOD] != 'a') + luaL_error(L, "modifiers for format '%%a'/'%%A' not implemented"); + return n; +} + +#endif /* } */ + + +/* +** Maximum size of each formatted item. This maximum size is produced +** by format('%.99f', minfloat), and is equal to 99 + 2 ('-' and '.') + +** number of decimal digits to represent minfloat. +*/ +#define MAX_ITEM (120 + l_mathlim(MAX_10_EXP)) + /* valid flags in a format specification */ #define FLAGS "-+ #0" /* ** maximum size of each format specification (such as "%-099.99d") -** (+2 for length modifiers; +10 accounts for %99.99x plus margin of error) */ -#define MAX_FORMAT (sizeof(FLAGS) + 2 + 10) +#define MAX_FORMAT 32 static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { @@ -849,8 +933,8 @@ static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { if (isdigit(uchar(*p))) luaL_error(L, "invalid format (width or precision too long)"); *(form++) = '%'; - memcpy(form, strfrmt, (p - strfrmt + 1) * sizeof(char)); - form += p - strfrmt + 1; + memcpy(form, strfrmt, ((p - strfrmt) + 1) * sizeof(char)); + form += (p - strfrmt) + 1; *form = '\0'; return p; } @@ -901,9 +985,10 @@ static int str_format (lua_State *L) { nb = sprintf(buff, form, n); break; } -#if defined(LUA_USE_AFORMAT) case 'a': case 'A': -#endif + addlenmod(form, LUA_NUMBER_FRMLEN); + nb = lua_number2strx(L, buff, form, luaL_checknumber(L, arg)); + break; case 'e': case 'E': case 'f': case 'g': case 'G': { addlenmod(form, LUA_NUMBER_FRMLEN); @@ -921,13 +1006,12 @@ static int str_format (lua_State *L) { /* no precision and string is too long to be formatted; keep original string */ luaL_addvalue(&b); - break; } else { nb = sprintf(buff, form, s); lua_pop(L, 1); /* remove result from 'luaL_tolstring' */ - break; } + break; } default: { /* also treat cases 'pnLlh' */ return luaL_error(L, "invalid option '%%%c' to 'format'", @@ -1249,7 +1333,7 @@ static int str_pack (lua_State *L) { totalsize += len + 1; break; } - case Kpadding: luaL_addchar(&b, LUA_PACKPADBYTE); /* go through */ + case Kpadding: luaL_addchar(&b, LUA_PACKPADBYTE); /* FALLTHROUGH */ case Kpaddalign: case Knop: arg--; /* undo increment */ break; diff --git a/src/ltable.c b/src/ltable.c index 38be005..04f2a34 100644 --- a/src/ltable.c +++ b/src/ltable.c @@ -1,5 +1,5 @@ /* -** $Id: ltable.c,v 2.100 2015/01/05 13:52:37 roberto Exp $ +** $Id: ltable.c,v 2.111 2015/06/09 14:21:13 roberto Exp $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ @@ -14,8 +14,8 @@ ** Implementation of tables (aka arrays, objects, or hash tables). ** Tables keep its elements in two parts: an array part and a hash part. ** Non-negative integer keys are all candidates to be kept in the array -** part. The actual size of the array is the largest 'n' such that at -** least half the slots between 0 and n are in use. +** part. The actual size of the array is the largest 'n' such that +** more than half the slots between 1 and n are in use. ** Hash uses a mix of chained scatter table with Brent's variation. ** A main invariant of these tables is that, if an element is not ** in its main position (i.e. the 'original' position that its hash gives @@ -23,9 +23,7 @@ ** Hence even when the load factor reaches 100%, performance remains good. */ -#include <float.h> #include <math.h> -#include <string.h> #include <limits.h> #include "lua.h" @@ -71,7 +69,7 @@ #define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1)))) -#define hashpointer(t,p) hashmod(t, point2int(p)) +#define hashpointer(t,p) hashmod(t, point2uint(p)) #define dummynode (&dummynode_) @@ -85,31 +83,33 @@ static const Node dummynode_ = { /* -** Checks whether a float has a value representable as a lua_Integer -** (and does the conversion if so) +** Hash for floating-point numbers. +** The main computation should be just +** n = frepx(n, &i); return (n * INT_MAX) + i +** but there are some numerical subtleties. +** In a two-complement representation, INT_MAX does not has an exact +** representation as a float, but INT_MIN does; because the absolute +** value of 'frexp' is smaller than 1 (unless 'n' is inf/NaN), the +** absolute value of the product 'frexp * -INT_MIN' is smaller or equal +** to INT_MAX. Next, the use of 'unsigned int' avoids overflows when +** adding 'i'; the use of '~u' (instead of '-u') avoids problems with +** INT_MIN. */ -static int numisinteger (lua_Number x, lua_Integer *p) { - if ((x) == l_floor(x)) /* integral value? */ - return lua_numbertointeger(x, p); /* try as an integer */ - else return 0; -} - - -/* -** hash for floating-point numbers -*/ -static Node *hashfloat (const Table *t, lua_Number n) { +#if !defined(l_hashfloat) +static int l_hashfloat (lua_Number n) { int i; - n = l_mathop(frexp)(n, &i) * cast_num(INT_MAX - DBL_MAX_EXP); - i += cast_int(n); - if (i < 0) { - if (cast(unsigned int, i) == 0u - i) /* use unsigned to avoid overflows */ - i = 0; /* handle INT_MIN */ - i = -i; /* must be a positive value */ + lua_Integer ni; + n = l_mathop(frexp)(n, &i) * -cast_num(INT_MIN); + if (!lua_numbertointeger(n, &ni)) { /* is 'n' inf/-inf/NaN? */ + lua_assert(luai_numisnan(n) || l_mathop(fabs)(n) == HUGE_VAL); + return 0; + } + else { /* normal case */ + unsigned int u = cast(unsigned int, i) + cast(unsigned int, ni); + return cast_int(u <= cast(unsigned int, INT_MAX) ? u : ~u); } - return hashmod(t, i); } - +#endif /* @@ -121,13 +121,13 @@ static Node *mainposition (const Table *t, const TValue *key) { case LUA_TNUMINT: return hashint(t, ivalue(key)); case LUA_TNUMFLT: - return hashfloat(t, fltvalue(key)); + return hashmod(t, l_hashfloat(fltvalue(key))); case LUA_TSHRSTR: return hashstr(t, tsvalue(key)); case LUA_TLNGSTR: { TString *s = tsvalue(key); if (s->extra == 0) { /* no hash? */ - s->hash = luaS_hash(getstr(s), s->len, s->hash); + s->hash = luaS_hash(getstr(s), s->u.lnglen, s->hash); s->extra = 1; /* now it has its hash */ } return hashstr(t, tsvalue(key)); @@ -219,28 +219,29 @@ int luaH_next (lua_State *L, Table *t, StkId key) { /* ** Compute the optimal size for the array part of table 't'. 'nums' is a ** "count array" where 'nums[i]' is the number of integers in the table -** between 2^(i - 1) + 1 and 2^i. Put in '*narray' the optimal size, and -** return the number of elements that will go to that part. +** between 2^(i - 1) + 1 and 2^i. 'pna' enters with the total number of +** integer keys in the table and leaves with the number of keys that +** will go to the array part; return the optimal size. */ -static unsigned int computesizes (unsigned int nums[], unsigned int *narray) { +static unsigned int computesizes (unsigned int nums[], unsigned int *pna) { int i; - unsigned int twotoi; /* 2^i */ + unsigned int twotoi; /* 2^i (candidate for optimal size) */ unsigned int a = 0; /* number of elements smaller than 2^i */ unsigned int na = 0; /* number of elements to go to array part */ - unsigned int n = 0; /* optimal size for array part */ - for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) { + unsigned int optimal = 0; /* optimal size for array part */ + /* loop while keys can fill more than half of total size */ + for (i = 0, twotoi = 1; *pna > twotoi / 2; i++, twotoi *= 2) { if (nums[i] > 0) { a += nums[i]; if (a > twotoi/2) { /* more than half elements present? */ - n = twotoi; /* optimal size (till now) */ - na = a; /* all elements up to 'n' will go to array part */ + optimal = twotoi; /* optimal size (till now) */ + na = a; /* all elements up to 'optimal' will go to array part */ } } - if (a == *narray) break; /* all elements already counted */ } - *narray = n; - lua_assert(*narray/2 <= na && na <= *narray); - return na; + lua_assert((optimal == 0 || optimal / 2 < na) && na <= optimal); + *pna = na; + return optimal; } @@ -255,6 +256,11 @@ static int countint (const TValue *key, unsigned int *nums) { } +/* +** Count keys in array part of table 't': Fill 'nums[i]' with +** number of keys that will go into corresponding slice and return +** total number of non-nil keys. +*/ static unsigned int numusearray (const Table *t, unsigned int *nums) { int lg; unsigned int ttlg; /* 2^lg */ @@ -281,8 +287,7 @@ static unsigned int numusearray (const Table *t, unsigned int *nums) { } -static int numusehash (const Table *t, unsigned int *nums, - unsigned int *pnasize) { +static int numusehash (const Table *t, unsigned int *nums, unsigned int *pna) { int totaluse = 0; /* total number of elements */ int ause = 0; /* elements added to 'nums' (can go to array part) */ int i = sizenode(t); @@ -293,7 +298,7 @@ static int numusehash (const Table *t, unsigned int *nums, totaluse++; } } - *pnasize += ause; + *pna += ause; return totaluse; } @@ -363,7 +368,7 @@ void luaH_resize (lua_State *L, Table *t, unsigned int nasize, } } if (!isdummy(nold)) - luaM_freearray(L, nold, cast(size_t, twoto(oldhsize))); /* free old array */ + luaM_freearray(L, nold, cast(size_t, twoto(oldhsize))); /* free old hash */ } @@ -376,21 +381,22 @@ void luaH_resizearray (lua_State *L, Table *t, unsigned int nasize) { ** nums[i] = number of keys 'k' where 2^(i - 1) < k <= 2^i */ static void rehash (lua_State *L, Table *t, const TValue *ek) { - unsigned int nasize, na; + unsigned int asize; /* optimal size for array part */ + unsigned int na; /* number of keys in the array part */ unsigned int nums[MAXABITS + 1]; int i; int totaluse; for (i = 0; i <= MAXABITS; i++) nums[i] = 0; /* reset counts */ - nasize = numusearray(t, nums); /* count keys in array part */ - totaluse = nasize; /* all those keys are integer keys */ - totaluse += numusehash(t, nums, &nasize); /* count keys in hash part */ + na = numusearray(t, nums); /* count keys in array part */ + totaluse = na; /* all those keys are integer keys */ + totaluse += numusehash(t, nums, &na); /* count keys in hash part */ /* count extra key */ - nasize += countint(ek, nums); + na += countint(ek, nums); totaluse++; /* compute new size for array part */ - na = computesizes(nums, &nasize); + asize = computesizes(nums, &na); /* resize the table to new computed sizes */ - luaH_resize(L, t, nasize, totaluse - na); + luaH_resize(L, t, asize, totaluse - na); } @@ -443,14 +449,13 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { TValue aux; if (ttisnil(key)) luaG_runerror(L, "table index is nil"); else if (ttisfloat(key)) { - lua_Number n = fltvalue(key); lua_Integer k; - if (luai_numisnan(n)) - luaG_runerror(L, "table index is NaN"); - if (numisinteger(n, &k)) { /* index is int? */ + if (luaV_tointeger(key, &k, 0)) { /* index is int? */ setivalue(&aux, k); key = &aux; /* insert it as an integer */ } + else if (luai_numisnan(fltvalue(key))) + luaG_runerror(L, "table index is NaN"); } mp = mainposition(t, key); if (!ttisnil(gval(mp)) || isdummy(mp)) { /* main position is taken? */ @@ -544,10 +549,10 @@ const TValue *luaH_get (Table *t, const TValue *key) { case LUA_TNIL: return luaO_nilobject; case LUA_TNUMFLT: { lua_Integer k; - if (numisinteger(fltvalue(key), &k)) /* index is int? */ + if (luaV_tointeger(key, &k, 0)) /* index is int? */ return luaH_getint(t, k); /* use specialized version */ - /* else go through */ - } + /* else... */ + } /* FALLTHROUGH */ default: { Node *n = mainposition(t, key); for (;;) { /* check whether 'key' is somewhere in the chain */ diff --git a/src/ltablib.c b/src/ltablib.c index 8f78afb..a05c885 100644 --- a/src/ltablib.c +++ b/src/ltablib.c @@ -1,5 +1,5 @@ /* -** $Id: ltablib.c,v 1.79 2014/11/02 19:19:04 roberto Exp $ +** $Id: ltablib.c,v 1.80 2015/01/13 16:27:29 roberto Exp $ ** Library for Table Manipulation ** See Copyright Notice in lua.h */ @@ -124,8 +124,6 @@ static int tmove (lua_State *L) { lua_Integer e = luaL_checkinteger(L, 3); lua_Integer t = luaL_checkinteger(L, 4); int tt = !lua_isnoneornil(L, 5) ? 5 : 1; /* destination table */ - /* the following restriction avoids several problems with overflows */ - luaL_argcheck(L, f > 0, 2, "initial position must be positive"); if (e >= f) { /* otherwise, nothing to move */ lua_Integer n, i; ta.geti = (luaL_getmetafield(L, 1, "__index") == LUA_TNIL) @@ -134,7 +132,11 @@ static int tmove (lua_State *L) { ta.seti = (luaL_getmetafield(L, tt, "__newindex") == LUA_TNIL) ? (luaL_checktype(L, tt, LUA_TTABLE), lua_rawseti) : lua_seti; + luaL_argcheck(L, f > 0 || e < LUA_MAXINTEGER + f, 3, + "too many elements to move"); n = e - f + 1; /* number of elements to move */ + luaL_argcheck(L, t <= LUA_MAXINTEGER - n + 1, 4, + "destination wrap around"); if (t > f) { for (i = n - 1; i >= 0; i--) { (*ta.geti)(L, 1, f + i); @@ -1,5 +1,5 @@ /* -** $Id: ltm.c,v 2.33 2014/11/21 12:15:57 roberto Exp $ +** $Id: ltm.c,v 2.34 2015/03/30 15:42:27 roberto Exp $ ** Tag methods ** See Copyright Notice in lua.h */ @@ -117,6 +117,7 @@ void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, switch (event) { case TM_CONCAT: luaG_concaterror(L, p1, p2); + /* call never returns, but to avoid warnings: *//* FALLTHROUGH */ case TM_BAND: case TM_BOR: case TM_BXOR: case TM_SHL: case TM_SHR: case TM_BNOT: { lua_Number dummy; @@ -124,8 +125,8 @@ void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, luaG_tointerror(L, p1, p2); else luaG_opinterror(L, p1, p2, "perform bitwise operation on"); - /* else go through */ } + /* calls never return, but to avoid warnings: *//* FALLTHROUGH */ default: luaG_opinterror(L, p1, p2, "perform arithmetic on"); } @@ -1,5 +1,5 @@ /* -** $Id: lua.c,v 1.222 2014/11/11 19:41:27 roberto Exp $ +** $Id: lua.c,v 1.225 2015/03/30 15:42:59 roberto Exp $ ** Lua stand-alone interpreter ** See Copyright Notice in lua.h */ @@ -80,9 +80,7 @@ #include <readline/readline.h> #include <readline/history.h> #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_saveline(L,line) ((void)L, add_history(line)) #define lua_freeline(L,b) ((void)L, free(b)) #else /* }{ */ @@ -90,7 +88,7 @@ #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_saveline(L,line) { (void)L; (void)line; } #define lua_freeline(L,b) { (void)L; (void)b; } #endif /* } */ @@ -315,11 +313,11 @@ static int pushline (lua_State *L, int firstline) { lua_pop(L, 1); /* remove prompt */ l = strlen(b); if (l > 0 && b[l-1] == '\n') /* line ends with newline? */ - b[l-1] = '\0'; /* remove it */ + b[--l] = '\0'; /* remove it */ if (firstline && b[0] == '=') /* for compatibility with 5.2, ... */ lua_pushfstring(L, "return %s", b + 1); /* change '=' to 'return' */ else - lua_pushstring(L, b); + lua_pushlstring(L, b, l); lua_freeline(L, b); return 1; } @@ -336,8 +334,12 @@ static int addreturn (lua_State *L) { lua_pushvalue(L, -2); /* duplicate line */ lua_concat(L, 2); /* new line is "return ..." */ line = lua_tolstring(L, -1, &len); - if ((status = luaL_loadbuffer(L, line, len, "=stdin")) == LUA_OK) + if ((status = luaL_loadbuffer(L, line, len, "=stdin")) == LUA_OK) { lua_remove(L, -3); /* remove original line */ + line += sizeof("return")/sizeof(char); /* remove 'return' for history */ + if (line[0] != '\0') /* non empty? */ + lua_saveline(L, line); /* keep history */ + } else lua_pop(L, 2); /* remove result from 'luaL_loadbuffer' and new line */ return status; @@ -352,8 +354,10 @@ static int multiline (lua_State *L) { size_t len; const char *line = lua_tolstring(L, 1, &len); /* get what it has */ int status = luaL_loadbuffer(L, line, len, "=stdin"); /* try it */ - if (!incomplete(L, status) || !pushline(L, 0)) + if (!incomplete(L, status) || !pushline(L, 0)) { + lua_saveline(L, line); /* keep history */ return status; /* cannot or should not try to add continuation line */ + } lua_pushliteral(L, "\n"); /* add newline... */ lua_insert(L, -2); /* ...between the two lines */ lua_concat(L, 3); /* join them */ @@ -374,7 +378,6 @@ static int loadline (lua_State *L) { return -1; /* no input */ if ((status = addreturn(L)) != LUA_OK) /* 'return ...' did not work? */ status = multiline(L); /* try as command, maybe with continuation lines */ - lua_saveline(L, 1); /* keep history */ lua_remove(L, 1); /* remove line from the stack */ lua_assert(lua_gettop(L) == 1); return status; @@ -482,14 +485,14 @@ static int collectargs (char **argv, int *first) { args |= has_E; break; case 'i': - args |= has_i; /* goes through (-i implies -v) */ + args |= has_i; /* (-i implies -v) *//* FALLTHROUGH */ case 'v': if (argv[i][2] != '\0') /* extra characters after 1st? */ return has_error; /* invalid option */ args |= has_v; break; case 'e': - args |= has_e; /* go through */ + args |= has_e; /* FALLTHROUGH */ case 'l': /* both options need an argument */ if (argv[i][2] == '\0') { /* no concatenated argument? */ i++; /* try next 'argv' */ @@ -513,17 +516,16 @@ static int collectargs (char **argv, int *first) { static int runargs (lua_State *L, char **argv, int n) { int i; for (i = 1; i < n; i++) { - int status; int option = argv[i][1]; lua_assert(argv[i][0] == '-'); /* already checked */ if (option == 'e' || option == 'l') { + int status; const char *extra = argv[i] + 2; /* both options need an argument */ if (*extra == '\0') extra = argv[++i]; lua_assert(extra != NULL); - if (option == 'e') - status = dostring(L, extra, "=(command line)"); - else - status = dolibrary(L, extra); + status = (option == 'e') + ? dostring(L, extra, "=(command line)") + : dolibrary(L, extra); if (status != LUA_OK) return 0; } } @@ -1,5 +1,5 @@ /* -** $Id: lua.h,v 1.325 2014/12/26 17:24:27 roberto Exp $ +** $Id: lua.h,v 1.328 2015/06/03 13:03:38 roberto Exp $ ** Lua - A Scripting Language ** Lua.org, PUC-Rio, Brazil (http://www.lua.org) ** See Copyright Notice at the end of this file @@ -19,7 +19,7 @@ #define LUA_VERSION_MAJOR "5" #define LUA_VERSION_MINOR "3" #define LUA_VERSION_NUM 503 -#define LUA_VERSION_RELEASE "0" +#define LUA_VERSION_RELEASE "1" #define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR #define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE @@ -35,9 +35,11 @@ /* -** pseudo-indices +** Pseudo-indices +** (-LUAI_MAXSTACK is the minimum valid index; we keep some free empty +** space after that to help overflow detection) */ -#define LUA_REGISTRYINDEX LUAI_FIRSTPSEUDOIDX +#define LUA_REGISTRYINDEX (-LUAI_MAXSTACK - 1000) #define lua_upvalueindex(i) (LUA_REGISTRYINDEX - (i)) @@ -356,8 +358,7 @@ LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); #define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) #define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) -#define lua_pushliteral(L, s) \ - lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) +#define lua_pushliteral(L, s) lua_pushstring(L, "" s) #define lua_pushglobaltable(L) \ lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS) @@ -1,5 +1,5 @@ /* -** $Id: luac.c,v 1.72 2015/01/06 03:09:13 lhf Exp $ +** $Id: luac.c,v 1.75 2015/03/12 01:58:27 lhf Exp $ ** Lua compiler (saves bytecodes to files; also lists bytecodes) ** See Copyright Notice in lua.h */ @@ -206,7 +206,7 @@ int main(int argc, char* argv[]) } /* -** $Id: print.c,v 1.76 2015/01/05 16:12:50 lhf Exp $ +** $Id: luac.c,v 1.75 2015/03/12 01:58:27 lhf Exp $ ** print bytecodes ** See Copyright Notice in lua.h */ @@ -226,7 +226,7 @@ int main(int argc, char* argv[]) static void PrintString(const TString* ts) { const char* s=getstr(ts); - size_t i,n=ts->len; + size_t i,n=tsslen(ts); printf("%c",'"'); for (i=0; i<n; i++) { diff --git a/src/luaconf.h.in b/src/luaconf.h.in index e05e09c..86bad93 100644 --- a/src/luaconf.h.in +++ b/src/luaconf.h.in @@ -1,5 +1,5 @@ /* -** $Id: luaconf.h,v 1.238 2014/12/29 13:27:55 roberto Exp $ +** $Id: luaconf.h,v 1.251 2015/05/20 17:39:23 roberto Exp $ ** Configuration file for Lua ** See Copyright Notice in lua.h */ @@ -78,10 +78,8 @@ /* -@@ LUA_INT_INT / LUA_INT_LONG / LUA_INT_LONGLONG defines the type for -** Lua integers. -@@ LUA_REAL_FLOAT / LUA_REAL_DOUBLE / LUA_REAL_LONGDOUBLE defines -** the type for Lua floats. +@@ LUA_INT_TYPE defines the type for Lua integers. +@@ LUA_FLOAT_TYPE defines the type for Lua floats. ** Lua should work fine with any mix of these options (if supported ** by your C compiler). The usual configurations are 64-bit integers ** and 'double' (the default), 32-bit integers and 'float' (for @@ -89,31 +87,46 @@ ** compliant with C99, which may not have support for 'long long'). */ +/* predefined options for LUA_INT_TYPE */ +#define LUA_INT_INT 1 +#define LUA_INT_LONG 2 +#define LUA_INT_LONGLONG 3 + +/* predefined options for LUA_FLOAT_TYPE */ +#define LUA_FLOAT_FLOAT 1 +#define LUA_FLOAT_DOUBLE 2 +#define LUA_FLOAT_LONGDOUBLE 3 + #if defined(LUA_32BITS) /* { */ /* ** 32-bit integers and 'float' */ #if LUAI_BITSINT >= 32 /* use 'int' if big enough */ -#define LUA_INT_INT +#define LUA_INT_TYPE LUA_INT_INT #else /* otherwise use 'long' */ -#define LUA_INT_LONG +#define LUA_INT_TYPE LUA_INT_LONG #endif -#define LUA_REAL_FLOAT +#define LUA_FLOAT_TYPE LUA_FLOAT_FLOAT #elif defined(LUA_C89_NUMBERS) /* }{ */ /* ** largest types available for C89 ('long' and 'double') */ -#define LUA_INT_LONG -#define LUA_REAL_DOUBLE +#define LUA_INT_TYPE LUA_INT_LONG +#define LUA_FLOAT_TYPE LUA_FLOAT_DOUBLE + +#endif /* } */ + -#else /* }{ */ /* ** default configuration for 64-bit Lua ('long long' and 'double') */ -#define LUA_INT_LONGLONG -#define LUA_REAL_DOUBLE +#if !defined(LUA_INT_TYPE) +#define LUA_INT_TYPE LUA_INT_LONGLONG +#endif +#if !defined(LUA_FLOAT_TYPE) +#define LUA_FLOAT_TYPE LUA_FLOAT_DOUBLE #endif /* } */ /* }================================================================== */ @@ -256,20 +269,15 @@ */ #define LUA_COMPAT_APIINTCASTS - -/* -@@ LUA_COMPAT_FLOATSTRING makes Lua format integral floats without a -@@ a float mark ('.0'). -** This macro is not on by default even in compatibility mode, -** because this is not really an incompatibility. -*/ -/* #define LUA_COMPAT_FLOATSTRING */ - #endif /* } */ #if defined(LUA_COMPAT_5_1) /* { */ +/* Incompatibilities from 5.2 -> 5.3 */ +#define LUA_COMPAT_MATHLIB +#define LUA_COMPAT_APIINTCASTS + /* @@ LUA_COMPAT_UNPACK controls the presence of global 'unpack'. ** You can replace it with 'table.unpack'. @@ -329,6 +337,15 @@ #endif /* } */ + +/* +@@ LUA_COMPAT_FLOATSTRING makes Lua format integral floats without a +@@ a float mark ('.0'). +** This macro is not on by default even in compatibility mode, +** because this is not really an incompatibility. +*/ +/* #define LUA_COMPAT_FLOATSTRING */ + /* }================================================================== */ @@ -336,30 +353,30 @@ /* ** {================================================================== ** Configuration for Numbers. -** Change these definitions if no predefined LUA_REAL_* / LUA_INT_* +** Change these definitions if no predefined LUA_FLOAT_* / LUA_INT_* ** satisfy your needs. ** =================================================================== */ /* @@ LUA_NUMBER is the floating-point type used by Lua. -** @@ LUAI_UACNUMBER is the result of an 'usual argument conversion' @@ over a floating number. -** +@@ l_mathlim(x) corrects limit name 'x' to the proper float type +** by prefixing it with one of FLT/DBL/LDBL. @@ LUA_NUMBER_FRMLEN is the length modifier for writing floats. @@ LUA_NUMBER_FMT is the format for writing floats. @@ lua_number2str converts a float to a string. -** @@ l_mathop allows the addition of an 'l' or 'f' to all math operations. -** @@ lua_str2number converts a decimal numeric string to a number. */ -#if defined(LUA_REAL_FLOAT) /* { single float */ +#if LUA_FLOAT_TYPE == LUA_FLOAT_FLOAT /* { single float */ #define LUA_NUMBER float +#define l_mathlim(n) (FLT_##n) + #define LUAI_UACNUMBER double #define LUA_NUMBER_FRMLEN "" @@ -370,10 +387,12 @@ #define lua_str2number(s,p) strtof((s), (p)) -#elif defined(LUA_REAL_LONGDOUBLE) /* }{ long double */ +#elif LUA_FLOAT_TYPE == LUA_FLOAT_LONGDOUBLE /* }{ long double */ #define LUA_NUMBER long double +#define l_mathlim(n) (LDBL_##n) + #define LUAI_UACNUMBER long double #define LUA_NUMBER_FRMLEN "L" @@ -383,10 +402,12 @@ #define lua_str2number(s,p) strtold((s), (p)) -#elif defined(LUA_REAL_DOUBLE) /* }{ double */ +#elif LUA_FLOAT_TYPE == LUA_FLOAT_DOUBLE /* }{ double */ #define LUA_NUMBER double +#define l_mathlim(n) (DBL_##n) + #define LUAI_UACNUMBER double #define LUA_NUMBER_FRMLEN "" @@ -396,9 +417,9 @@ #define lua_str2number(s,p) strtod((s), (p)) -#else /* }{ */ +#else /* }{ */ -#error "numeric real type not defined" +#error "numeric float type not defined" #endif /* } */ @@ -422,46 +443,6 @@ (*(p) = (LUA_INTEGER)(n), 1)) -/* -@@ The luai_num* macros define the primitive operations over numbers. -** They should work for any size of floating numbers. -*/ - -/* the following operations need the math library */ -#if defined(lobject_c) || defined(lvm_c) -#include <math.h> - -/* floor division (defined as 'floor(a/b)') */ -#define luai_numidiv(L,a,b) ((void)L, l_mathop(floor)(luai_numdiv(L,a,b))) - -/* -** module: defined as 'a - floor(a/b)*b'; the previous definition gives -** NaN when 'b' is huge, but the result should be 'a'. 'fmod' gives the -** result of 'a - trunc(a/b)*b', and therefore must be corrected when -** 'trunc(a/b) ~= floor(a/b)'. That happens when the division has a -** non-integer negative result, which is equivalent to the test below -*/ -#define luai_nummod(L,a,b,m) \ - { (m) = l_mathop(fmod)(a,b); if ((m)*(b) < 0) (m) += (b); } - -/* exponentiation */ -#define luai_numpow(L,a,b) ((void)L, l_mathop(pow)(a,b)) - -#endif - -/* these are quite standard operations */ -#if defined(LUA_CORE) -#define luai_numadd(L,a,b) ((a)+(b)) -#define luai_numsub(L,a,b) ((a)-(b)) -#define luai_nummul(L,a,b) ((a)*(b)) -#define luai_numdiv(L,a,b) ((a)/(b)) -#define luai_numunm(L,a) (-(a)) -#define luai_numeq(a,b) ((a)==(b)) -#define luai_numlt(a,b) ((a)<(b)) -#define luai_numle(a,b) ((a)<=(b)) -#define luai_numisnan(a) (!luai_numeq((a), (a))) -#endif - /* @@ LUA_INTEGER is the integer type used by Lua. @@ -494,7 +475,7 @@ /* now the variable definitions */ -#if defined(LUA_INT_INT) /* { int */ +#if LUA_INT_TYPE == LUA_INT_INT /* { int */ #define LUA_INTEGER int #define LUA_INTEGER_FRMLEN "" @@ -502,7 +483,7 @@ #define LUA_MAXINTEGER INT_MAX #define LUA_MININTEGER INT_MIN -#elif defined(LUA_INT_LONG) /* }{ long */ +#elif LUA_INT_TYPE == LUA_INT_LONG /* }{ long */ #define LUA_INTEGER long #define LUA_INTEGER_FRMLEN "l" @@ -510,7 +491,7 @@ #define LUA_MAXINTEGER LONG_MAX #define LUA_MININTEGER LONG_MIN -#elif defined(LUA_INT_LONGLONG) /* }{ long long */ +#elif LUA_INT_TYPE == LUA_INT_LONGLONG /* }{ long long */ #if defined(LLONG_MAX) /* { */ /* use ISO C99 stuff */ @@ -548,13 +529,13 @@ /* ** {================================================================== -** Dependencies with C99 +** Dependencies with C99 and other C details ** =================================================================== */ /* @@ lua_strx2number converts an hexadecimal numeric string to a number. -** In C99, 'strtod' does both conversions. Otherwise, you can +** In C99, 'strtod' does that conversion. Otherwise, you can ** leave 'lua_strx2number' undefined and Lua will provide its own ** implementation. */ @@ -564,11 +545,15 @@ /* -@@ LUA_USE_AFORMAT allows '%a'/'%A' specifiers in 'string.format' -** Enable it if the C function 'printf' supports these specifiers. -** (C99 demands it and Windows also supports it.) +@@ lua_number2strx converts a float to an hexadecimal numeric string. +** In C99, 'sprintf' (with format specifiers '%a'/'%A') does that. +** Otherwise, you can leave 'lua_number2strx' undefined and Lua will +** provide its own implementation. */ -#cmakedefine LUA_USE_AFORMAT +#if !defined(LUA_USE_C89) +#define lua_number2strx(L,b,f,n) sprintf(b,f,n) +#endif + /* ** 'strtof' and 'opf' variants for math functions are not valid in @@ -595,12 +580,50 @@ #if !defined(LUA_USE_C89) && defined(__STDC_VERSION__) && \ __STDC_VERSION__ >= 199901L #include <stdint.h> -#if defined (INTPTR_MAX) /* even in C99 this type is optional */ +#if defined(INTPTR_MAX) /* even in C99 this type is optional */ #undef LUA_KCONTEXT #define LUA_KCONTEXT intptr_t #endif #endif + +/* +@@ lua_getlocaledecpoint gets the locale "radix character" (decimal point). +** Change that if you do not want to use C locales. (Code using this +** macro must include header 'locale.h'.) +*/ +#if !defined(lua_getlocaledecpoint) +#define lua_getlocaledecpoint() (localeconv()->decimal_point[0]) +#endif + +/* }================================================================== */ + + +/* +** {================================================================== +** Language Variations +** ===================================================================== +*/ + +/* +@@ LUA_NOCVTN2S/LUA_NOCVTS2N control how Lua performs some +** coercions. Define LUA_NOCVTN2S to turn off automatic coercion from +** numbers to strings. Define LUA_NOCVTS2N to turn off automatic +** coercion from strings to numbers. +*/ +/* #define LUA_NOCVTN2S */ +/* #define LUA_NOCVTS2N */ + + +/* +@@ LUA_USE_APICHECK turns on several consistency checks on the C API. +** Define it as a help when debugging C code. +*/ +#if defined(LUA_USE_APICHECK) +#include <assert.h> +#define luai_apicheck(l,e) assert(e) +#endif + /* }================================================================== */ @@ -624,9 +647,6 @@ #define LUAI_MAXSTACK 15000 #endif -/* reserve some space for error handling */ -#define LUAI_FIRSTPSEUDOIDX (-LUAI_MAXSTACK - 1000) - /* @@ LUA_EXTRASPACE defines the size of a raw memory area associated with @@ -645,19 +665,17 @@ /* -@@ LUAI_MAXSHORTLEN is the maximum length for short strings, that is, -** strings that are internalized. (Cannot be smaller than reserved words -** or tags for metamethods, as these strings must be internalized; -** #("function") = 8, #("__newindex") = 10.) -*/ -#define LUAI_MAXSHORTLEN 40 - - -/* @@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. -** CHANGE it if it uses too much C-stack space. +** CHANGE it if it uses too much C-stack space. (For long double, +** 'string.format("%.99f", 1e4932)' needs ~5030 bytes, so a +** smaller buffer would force a memory allocation for each call to +** 'string.format'.) */ -#define LUAL_BUFFERSIZE ((int)(0x80 * sizeof(void*) * sizeof(lua_Integer))) +#if defined(LUA_FLOAT_LONGDOUBLE) +#define LUAL_BUFFERSIZE 8192 +#else +#define LUAL_BUFFERSIZE ((int)(0x80 * sizeof(void*) * sizeof(lua_Integer))) +#endif /* }================================================================== */ @@ -682,5 +700,7 @@ + + #endif diff --git a/src/luaconf.h.orig b/src/luaconf.h.orig index fd28d21..7cfa4fa 100644 --- a/src/luaconf.h.orig +++ b/src/luaconf.h.orig @@ -1,5 +1,5 @@ /* -** $Id: luaconf.h,v 1.238 2014/12/29 13:27:55 roberto Exp $ +** $Id: luaconf.h,v 1.251 2015/05/20 17:39:23 roberto Exp $ ** Configuration file for Lua ** See Copyright Notice in lua.h */ @@ -96,10 +96,8 @@ /* -@@ LUA_INT_INT / LUA_INT_LONG / LUA_INT_LONGLONG defines the type for -** Lua integers. -@@ LUA_REAL_FLOAT / LUA_REAL_DOUBLE / LUA_REAL_LONGDOUBLE defines -** the type for Lua floats. +@@ LUA_INT_TYPE defines the type for Lua integers. +@@ LUA_FLOAT_TYPE defines the type for Lua floats. ** Lua should work fine with any mix of these options (if supported ** by your C compiler). The usual configurations are 64-bit integers ** and 'double' (the default), 32-bit integers and 'float' (for @@ -107,31 +105,46 @@ ** compliant with C99, which may not have support for 'long long'). */ +/* predefined options for LUA_INT_TYPE */ +#define LUA_INT_INT 1 +#define LUA_INT_LONG 2 +#define LUA_INT_LONGLONG 3 + +/* predefined options for LUA_FLOAT_TYPE */ +#define LUA_FLOAT_FLOAT 1 +#define LUA_FLOAT_DOUBLE 2 +#define LUA_FLOAT_LONGDOUBLE 3 + #if defined(LUA_32BITS) /* { */ /* ** 32-bit integers and 'float' */ #if LUAI_BITSINT >= 32 /* use 'int' if big enough */ -#define LUA_INT_INT +#define LUA_INT_TYPE LUA_INT_INT #else /* otherwise use 'long' */ -#define LUA_INT_LONG +#define LUA_INT_TYPE LUA_INT_LONG #endif -#define LUA_REAL_FLOAT +#define LUA_FLOAT_TYPE LUA_FLOAT_FLOAT #elif defined(LUA_C89_NUMBERS) /* }{ */ /* ** largest types available for C89 ('long' and 'double') */ -#define LUA_INT_LONG -#define LUA_REAL_DOUBLE +#define LUA_INT_TYPE LUA_INT_LONG +#define LUA_FLOAT_TYPE LUA_FLOAT_DOUBLE + +#endif /* } */ + -#else /* }{ */ /* ** default configuration for 64-bit Lua ('long long' and 'double') */ -#define LUA_INT_LONGLONG -#define LUA_REAL_DOUBLE +#if !defined(LUA_INT_TYPE) +#define LUA_INT_TYPE LUA_INT_LONGLONG +#endif +#if !defined(LUA_FLOAT_TYPE) +#define LUA_FLOAT_TYPE LUA_FLOAT_DOUBLE #endif /* } */ /* }================================================================== */ @@ -155,7 +168,7 @@ ** non-conventional directories. */ #define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR -#if defined(_WIN32) /* { */ +#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. @@ -300,20 +313,15 @@ */ #define LUA_COMPAT_APIINTCASTS - -/* -@@ LUA_COMPAT_FLOATSTRING makes Lua format integral floats without a -@@ a float mark ('.0'). -** This macro is not on by default even in compatibility mode, -** because this is not really an incompatibility. -*/ -/* #define LUA_COMPAT_FLOATSTRING */ - #endif /* } */ #if defined(LUA_COMPAT_5_1) /* { */ +/* Incompatibilities from 5.2 -> 5.3 */ +#define LUA_COMPAT_MATHLIB +#define LUA_COMPAT_APIINTCASTS + /* @@ LUA_COMPAT_UNPACK controls the presence of global 'unpack'. ** You can replace it with 'table.unpack'. @@ -373,6 +381,15 @@ #endif /* } */ + +/* +@@ LUA_COMPAT_FLOATSTRING makes Lua format integral floats without a +@@ a float mark ('.0'). +** This macro is not on by default even in compatibility mode, +** because this is not really an incompatibility. +*/ +/* #define LUA_COMPAT_FLOATSTRING */ + /* }================================================================== */ @@ -380,30 +397,30 @@ /* ** {================================================================== ** Configuration for Numbers. -** Change these definitions if no predefined LUA_REAL_* / LUA_INT_* +** Change these definitions if no predefined LUA_FLOAT_* / LUA_INT_* ** satisfy your needs. ** =================================================================== */ /* @@ LUA_NUMBER is the floating-point type used by Lua. -** @@ LUAI_UACNUMBER is the result of an 'usual argument conversion' @@ over a floating number. -** +@@ l_mathlim(x) corrects limit name 'x' to the proper float type +** by prefixing it with one of FLT/DBL/LDBL. @@ LUA_NUMBER_FRMLEN is the length modifier for writing floats. @@ LUA_NUMBER_FMT is the format for writing floats. @@ lua_number2str converts a float to a string. -** @@ l_mathop allows the addition of an 'l' or 'f' to all math operations. -** @@ lua_str2number converts a decimal numeric string to a number. */ -#if defined(LUA_REAL_FLOAT) /* { single float */ +#if LUA_FLOAT_TYPE == LUA_FLOAT_FLOAT /* { single float */ #define LUA_NUMBER float +#define l_mathlim(n) (FLT_##n) + #define LUAI_UACNUMBER double #define LUA_NUMBER_FRMLEN "" @@ -414,10 +431,12 @@ #define lua_str2number(s,p) strtof((s), (p)) -#elif defined(LUA_REAL_LONGDOUBLE) /* }{ long double */ +#elif LUA_FLOAT_TYPE == LUA_FLOAT_LONGDOUBLE /* }{ long double */ #define LUA_NUMBER long double +#define l_mathlim(n) (LDBL_##n) + #define LUAI_UACNUMBER long double #define LUA_NUMBER_FRMLEN "L" @@ -427,10 +446,12 @@ #define lua_str2number(s,p) strtold((s), (p)) -#elif defined(LUA_REAL_DOUBLE) /* }{ double */ +#elif LUA_FLOAT_TYPE == LUA_FLOAT_DOUBLE /* }{ double */ #define LUA_NUMBER double +#define l_mathlim(n) (DBL_##n) + #define LUAI_UACNUMBER double #define LUA_NUMBER_FRMLEN "" @@ -440,9 +461,9 @@ #define lua_str2number(s,p) strtod((s), (p)) -#else /* }{ */ +#else /* }{ */ -#error "numeric real type not defined" +#error "numeric float type not defined" #endif /* } */ @@ -466,46 +487,6 @@ (*(p) = (LUA_INTEGER)(n), 1)) -/* -@@ The luai_num* macros define the primitive operations over numbers. -** They should work for any size of floating numbers. -*/ - -/* the following operations need the math library */ -#if defined(lobject_c) || defined(lvm_c) -#include <math.h> - -/* floor division (defined as 'floor(a/b)') */ -#define luai_numidiv(L,a,b) ((void)L, l_mathop(floor)(luai_numdiv(L,a,b))) - -/* -** module: defined as 'a - floor(a/b)*b'; the previous definition gives -** NaN when 'b' is huge, but the result should be 'a'. 'fmod' gives the -** result of 'a - trunc(a/b)*b', and therefore must be corrected when -** 'trunc(a/b) ~= floor(a/b)'. That happens when the division has a -** non-integer negative result, which is equivalent to the test below -*/ -#define luai_nummod(L,a,b,m) \ - { (m) = l_mathop(fmod)(a,b); if ((m)*(b) < 0) (m) += (b); } - -/* exponentiation */ -#define luai_numpow(L,a,b) ((void)L, l_mathop(pow)(a,b)) - -#endif - -/* these are quite standard operations */ -#if defined(LUA_CORE) -#define luai_numadd(L,a,b) ((a)+(b)) -#define luai_numsub(L,a,b) ((a)-(b)) -#define luai_nummul(L,a,b) ((a)*(b)) -#define luai_numdiv(L,a,b) ((a)/(b)) -#define luai_numunm(L,a) (-(a)) -#define luai_numeq(a,b) ((a)==(b)) -#define luai_numlt(a,b) ((a)<(b)) -#define luai_numle(a,b) ((a)<=(b)) -#define luai_numisnan(a) (!luai_numeq((a), (a))) -#endif - /* @@ LUA_INTEGER is the integer type used by Lua. @@ -538,7 +519,7 @@ /* now the variable definitions */ -#if defined(LUA_INT_INT) /* { int */ +#if LUA_INT_TYPE == LUA_INT_INT /* { int */ #define LUA_INTEGER int #define LUA_INTEGER_FRMLEN "" @@ -546,7 +527,7 @@ #define LUA_MAXINTEGER INT_MAX #define LUA_MININTEGER INT_MIN -#elif defined(LUA_INT_LONG) /* }{ long */ +#elif LUA_INT_TYPE == LUA_INT_LONG /* }{ long */ #define LUA_INTEGER long #define LUA_INTEGER_FRMLEN "l" @@ -554,7 +535,7 @@ #define LUA_MAXINTEGER LONG_MAX #define LUA_MININTEGER LONG_MIN -#elif defined(LUA_INT_LONGLONG) /* }{ long long */ +#elif LUA_INT_TYPE == LUA_INT_LONGLONG /* }{ long long */ #if defined(LLONG_MAX) /* { */ /* use ISO C99 stuff */ @@ -592,13 +573,13 @@ /* ** {================================================================== -** Dependencies with C99 +** Dependencies with C99 and other C details ** =================================================================== */ /* @@ lua_strx2number converts an hexadecimal numeric string to a number. -** In C99, 'strtod' does both conversions. Otherwise, you can +** In C99, 'strtod' does that conversion. Otherwise, you can ** leave 'lua_strx2number' undefined and Lua will provide its own ** implementation. */ @@ -608,12 +589,13 @@ /* -@@ LUA_USE_AFORMAT allows '%a'/'%A' specifiers in 'string.format' -** Enable it if the C function 'printf' supports these specifiers. -** (C99 demands it and Windows also supports it.) +@@ lua_number2strx converts a float to an hexadecimal numeric string. +** In C99, 'sprintf' (with format specifiers '%a'/'%A') does that. +** Otherwise, you can leave 'lua_number2strx' undefined and Lua will +** provide its own implementation. */ -#if !defined(LUA_USE_C89) || defined(LUA_USE_WINDOWS) -#define LUA_USE_AFORMAT +#if !defined(LUA_USE_C89) +#define lua_number2strx(L,b,f,n) sprintf(b,f,n) #endif @@ -642,12 +624,50 @@ #if !defined(LUA_USE_C89) && defined(__STDC_VERSION__) && \ __STDC_VERSION__ >= 199901L #include <stdint.h> -#if defined (INTPTR_MAX) /* even in C99 this type is optional */ +#if defined(INTPTR_MAX) /* even in C99 this type is optional */ #undef LUA_KCONTEXT #define LUA_KCONTEXT intptr_t #endif #endif + +/* +@@ lua_getlocaledecpoint gets the locale "radix character" (decimal point). +** Change that if you do not want to use C locales. (Code using this +** macro must include header 'locale.h'.) +*/ +#if !defined(lua_getlocaledecpoint) +#define lua_getlocaledecpoint() (localeconv()->decimal_point[0]) +#endif + +/* }================================================================== */ + + +/* +** {================================================================== +** Language Variations +** ===================================================================== +*/ + +/* +@@ LUA_NOCVTN2S/LUA_NOCVTS2N control how Lua performs some +** coercions. Define LUA_NOCVTN2S to turn off automatic coercion from +** numbers to strings. Define LUA_NOCVTS2N to turn off automatic +** coercion from strings to numbers. +*/ +/* #define LUA_NOCVTN2S */ +/* #define LUA_NOCVTS2N */ + + +/* +@@ LUA_USE_APICHECK turns on several consistency checks on the C API. +** Define it as a help when debugging C code. +*/ +#if defined(LUA_USE_APICHECK) +#include <assert.h> +#define luai_apicheck(l,e) assert(e) +#endif + /* }================================================================== */ @@ -671,9 +691,6 @@ #define LUAI_MAXSTACK 15000 #endif -/* reserve some space for error handling */ -#define LUAI_FIRSTPSEUDOIDX (-LUAI_MAXSTACK - 1000) - /* @@ LUA_EXTRASPACE defines the size of a raw memory area associated with @@ -692,19 +709,17 @@ /* -@@ LUAI_MAXSHORTLEN is the maximum length for short strings, that is, -** strings that are internalized. (Cannot be smaller than reserved words -** or tags for metamethods, as these strings must be internalized; -** #("function") = 8, #("__newindex") = 10.) -*/ -#define LUAI_MAXSHORTLEN 40 - - -/* @@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. -** CHANGE it if it uses too much C-stack space. +** CHANGE it if it uses too much C-stack space. (For long double, +** 'string.format("%.99f", 1e4932)' needs ~5030 bytes, so a +** smaller buffer would force a memory allocation for each call to +** 'string.format'.) */ -#define LUAL_BUFFERSIZE ((int)(0x80 * sizeof(void*) * sizeof(lua_Integer))) +#if defined(LUA_FLOAT_LONGDOUBLE) +#define LUAL_BUFFERSIZE 8192 +#else +#define LUAL_BUFFERSIZE ((int)(0x80 * sizeof(void*) * sizeof(lua_Integer))) +#endif /* }================================================================== */ diff --git a/src/lutf8lib.c b/src/lutf8lib.c index be4f087..9042582 100644 --- a/src/lutf8lib.c +++ b/src/lutf8lib.c @@ -1,5 +1,5 @@ /* -** $Id: lutf8lib.c,v 1.13 2014/11/02 19:19:04 roberto Exp $ +** $Id: lutf8lib.c,v 1.15 2015/03/28 19:16:55 roberto Exp $ ** Standard library for UTF-8 manipulation ** See Copyright Notice in lua.h */ @@ -11,6 +11,7 @@ #include <assert.h> +#include <limits.h> #include <stdlib.h> #include <string.h> @@ -37,7 +38,7 @@ static lua_Integer u_posrelat (lua_Integer pos, size_t len) { ** Decode one UTF-8 sequence, returning NULL if byte sequence is invalid. */ static const char *utf8_decode (const char *o, int *val) { - static unsigned int limits[] = {0xFF, 0x7F, 0x7FF, 0xFFFF}; + static const unsigned int limits[] = {0xFF, 0x7F, 0x7FF, 0xFFFF}; const unsigned char *s = (const unsigned char *)o; unsigned int c = s[0]; unsigned int res = 0; /* final result */ @@ -106,9 +107,9 @@ static int codepoint (lua_State *L) { luaL_argcheck(L, posi >= 1, 2, "out of range"); luaL_argcheck(L, pose <= (lua_Integer)len, 3, "out of range"); if (posi > pose) return 0; /* empty interval; return no values */ - n = (int)(pose - posi + 1); - if (posi + n <= pose) /* (lua_Integer -> int) overflow? */ + if (pose - posi >= INT_MAX) /* (lua_Integer -> int) overflow? */ return luaL_error(L, "string slice too long"); + n = (int)(pose - posi) + 1; luaL_checkstack(L, n, "string slice too long"); n = 0; se = s + pose; @@ -234,7 +235,7 @@ static int iter_codes (lua_State *L) { #define UTF8PATT "[\0-\x7F\xC2-\xF4][\x80-\xBF]*" -static struct luaL_Reg funcs[] = { +static const luaL_Reg funcs[] = { {"offset", byteoffset}, {"codepoint", codepoint}, {"char", utfchar}, @@ -248,7 +249,7 @@ static struct luaL_Reg funcs[] = { LUAMOD_API int luaopen_utf8 (lua_State *L) { luaL_newlib(L, funcs); - lua_pushliteral(L, UTF8PATT); + lua_pushlstring(L, UTF8PATT, sizeof(UTF8PATT)/sizeof(char) - 1); lua_setfield(L, -2, "charpattern"); return 1; } @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.232 2014/12/27 20:30:38 roberto Exp $ +** $Id: lvm.c,v 2.245 2015/06/09 15:53:35 roberto Exp $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -9,8 +9,9 @@ #include "lprefix.h" - +#include <float.h> #include <limits.h> +#include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -30,36 +31,38 @@ #include "lvm.h" -/* -** You can define LUA_FLOORN2I if you want to convert floats to integers -** by flooring them (instead of raising an error if they are not -** integral values) -*/ -#if !defined(LUA_FLOORN2I) -#define LUA_FLOORN2I 0 -#endif - - /* limit for table tag-method chains (to avoid loops) */ #define MAXTAGLOOP 2000 + /* -** Similar to 'tonumber', but does not attempt to convert strings and -** ensure correct precision (no extra bits). Used in comparisons. +** 'l_intfitsf' checks whether a given integer can be converted to a +** float without rounding. Used in comparisons. Left undefined if +** all integers fit in a float precisely. */ -static int tofloat (const TValue *obj, lua_Number *n) { - if (ttisfloat(obj)) *n = fltvalue(obj); - else if (ttisinteger(obj)) { - volatile lua_Number x = cast_num(ivalue(obj)); /* avoid extra precision */ - *n = x; - } - else { - *n = 0; /* to avoid warnings */ - return 0; - } - return 1; -} +#if !defined(l_intfitsf) + +/* number of bits in the mantissa of a float */ +#define NBM (l_mathlim(MANT_DIG)) + +/* +** Check whether some integers may not fit in a float, that is, whether +** (maxinteger >> NBM) > 0 (that implies (1 << NBM) <= maxinteger). +** (The shifts are done in parts to avoid shifting by more than the size +** of an integer. In a worst case, NBM == 113 for long double and +** sizeof(integer) == 32.) +*/ +#if ((((LUA_MAXINTEGER >> (NBM / 4)) >> (NBM / 4)) >> (NBM / 4)) \ + >> (NBM - (3 * (NBM / 4)))) > 0 + +#define l_intfitsf(i) \ + (-((lua_Integer)1 << NBM) <= (i) && (i) <= ((lua_Integer)1 << NBM)) + +#endif + +#endif + /* @@ -73,7 +76,7 @@ int luaV_tonumber_ (const TValue *obj, lua_Number *n) { return 1; } else if (cvt2num(obj) && /* string convertible to number? */ - luaO_str2num(svalue(obj), &v) == tsvalue(obj)->len + 1) { + luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) { *n = nvalue(&v); /* convert result of 'luaO_str2num' to a float */ return 1; } @@ -88,7 +91,7 @@ int luaV_tonumber_ (const TValue *obj, lua_Number *n) { ** mode == 1: takes the floor of the number ** mode == 2: takes the ceil of the number */ -static int tointeger_aux (const TValue *obj, lua_Integer *p, int mode) { +int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode) { TValue v; again: if (ttisfloat(obj)) { @@ -106,7 +109,7 @@ static int tointeger_aux (const TValue *obj, lua_Integer *p, int mode) { return 1; } else if (cvt2num(obj) && - luaO_str2num(svalue(obj), &v) == tsvalue(obj)->len + 1) { + luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) { obj = &v; goto again; /* convert result from 'luaO_str2num' to an integer */ } @@ -115,14 +118,6 @@ static int tointeger_aux (const TValue *obj, lua_Integer *p, int mode) { /* -** try to convert a value to an integer -*/ -int luaV_tointeger_ (const TValue *obj, lua_Integer *p) { - return tointeger_aux(obj, p, LUA_FLOORN2I); -} - - -/* ** Try to convert a 'for' limit to an integer, preserving the ** semantics of the loop. ** (The following explanation assumes a non-negative step; it is valid @@ -140,11 +135,11 @@ int luaV_tointeger_ (const TValue *obj, lua_Integer *p) { static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step, int *stopnow) { *stopnow = 0; /* usually, let loops run */ - if (!tointeger_aux(obj, p, (step < 0 ? 2 : 1))) { /* not fit in integer? */ + if (!luaV_tointeger(obj, p, (step < 0 ? 2 : 1))) { /* not fit in integer? */ lua_Number n; /* try to convert to float */ if (!tonumber(obj, &n)) /* cannot convert to float? */ return 0; /* not a number */ - if (n > 0) { /* if true, float is larger than max integer */ + if (luai_numlt(0, n)) { /* if true, float is larger than max integer */ *p = LUA_MAXINTEGER; if (step < 0) *stopnow = 1; } @@ -239,9 +234,9 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { */ static int l_strcmp (const TString *ls, const TString *rs) { const char *l = getstr(ls); - size_t ll = ls->len; + size_t ll = tsslen(ls); const char *r = getstr(rs); - size_t lr = rs->len; + size_t lr = tsslen(rs); for (;;) { /* for each segment */ int temp = strcoll(l, r); if (temp != 0) /* not equal? */ @@ -261,15 +256,102 @@ static int l_strcmp (const TString *ls, const TString *rs) { /* +** Check whether integer 'i' is less than float 'f'. If 'i' has an +** exact representation as a float ('l_intfitsf'), compare numbers as +** floats. Otherwise, if 'f' is outside the range for integers, result +** is trivial. Otherwise, compare them as integers. (When 'i' has no +** float representation, either 'f' is "far away" from 'i' or 'f' has +** no precision left for a fractional part; either way, how 'f' is +** truncated is irrelevant.) When 'f' is NaN, comparisons must result +** in false. +*/ +static int LTintfloat (lua_Integer i, lua_Number f) { +#if defined(l_intfitsf) + if (!l_intfitsf(i)) { + if (f >= -cast_num(LUA_MININTEGER)) /* -minint == maxint + 1 */ + return 1; /* f >= maxint + 1 > i */ + else if (f > cast_num(LUA_MININTEGER)) /* minint < f <= maxint ? */ + return (i < cast(lua_Integer, f)); /* compare them as integers */ + else /* f <= minint <= i (or 'f' is NaN) --> not(i < f) */ + return 0; + } +#endif + return luai_numlt(cast_num(i), f); /* compare them as floats */ +} + + +/* +** Check whether integer 'i' is less than or equal to float 'f'. +** See comments on previous function. +*/ +static int LEintfloat (lua_Integer i, lua_Number f) { +#if defined(l_intfitsf) + if (!l_intfitsf(i)) { + if (f >= -cast_num(LUA_MININTEGER)) /* -minint == maxint + 1 */ + return 1; /* f >= maxint + 1 > i */ + else if (f >= cast_num(LUA_MININTEGER)) /* minint <= f <= maxint ? */ + return (i <= cast(lua_Integer, f)); /* compare them as integers */ + else /* f < minint <= i (or 'f' is NaN) --> not(i <= f) */ + return 0; + } +#endif + return luai_numle(cast_num(i), f); /* compare them as floats */ +} + + +/* +** Return 'l < r', for numbers. +*/ +static int LTnum (const TValue *l, const TValue *r) { + if (ttisinteger(l)) { + lua_Integer li = ivalue(l); + if (ttisinteger(r)) + return li < ivalue(r); /* both are integers */ + else /* 'l' is int and 'r' is float */ + return LTintfloat(li, fltvalue(r)); /* l < r ? */ + } + else { + lua_Number lf = fltvalue(l); /* 'l' must be float */ + if (ttisfloat(r)) + return luai_numlt(lf, fltvalue(r)); /* both are float */ + else if (luai_numisnan(lf)) /* 'r' is int and 'l' is float */ + return 0; /* NaN < i is always false */ + else /* without NaN, (l < r) <--> not(r <= l) */ + return !LEintfloat(ivalue(r), lf); /* not (r <= l) ? */ + } +} + + +/* +** Return 'l <= r', for numbers. +*/ +static int LEnum (const TValue *l, const TValue *r) { + if (ttisinteger(l)) { + lua_Integer li = ivalue(l); + if (ttisinteger(r)) + return li <= ivalue(r); /* both are integers */ + else /* 'l' is int and 'r' is float */ + return LEintfloat(li, fltvalue(r)); /* l <= r ? */ + } + else { + lua_Number lf = fltvalue(l); /* 'l' must be float */ + if (ttisfloat(r)) + return luai_numle(lf, fltvalue(r)); /* both are float */ + else if (luai_numisnan(lf)) /* 'r' is int and 'l' is float */ + return 0; /* NaN <= i is always false */ + else /* without NaN, (l <= r) <--> not(r < l) */ + return !LTintfloat(ivalue(r), lf); /* not (r < l) ? */ + } +} + + +/* ** Main operation less than; return 'l < r'. */ int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { int res; - lua_Number nl, nr; - if (ttisinteger(l) && ttisinteger(r)) /* both operands are integers? */ - return (ivalue(l) < ivalue(r)); - else if (tofloat(l, &nl) && tofloat(r, &nr)) /* both are numbers? */ - return luai_numlt(nl, nr); + if (ttisnumber(l) && ttisnumber(r)) /* both operands are numbers? */ + return LTnum(l, r); else if (ttisstring(l) && ttisstring(r)) /* both are strings? */ return l_strcmp(tsvalue(l), tsvalue(r)) < 0; else if ((res = luaT_callorderTM(L, l, r, TM_LT)) < 0) /* no metamethod? */ @@ -279,27 +361,34 @@ int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { /* -** Main operation less than or equal to; return 'l <= r'. +** Main operation less than or equal to; return 'l <= r'. If it needs +** a metamethod and there is no '__le', try '__lt', based on +** l <= r iff !(r < l) (assuming a total order). If the metamethod +** yields during this substitution, the continuation has to know +** about it (to negate the result of r<l); bit CIST_LEQ in the call +** status keeps that information. */ int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) { int res; - lua_Number nl, nr; - if (ttisinteger(l) && ttisinteger(r)) /* both operands are integers? */ - return (ivalue(l) <= ivalue(r)); - else if (tofloat(l, &nl) && tofloat(r, &nr)) /* both are numbers? */ - return luai_numle(nl, nr); + if (ttisnumber(l) && ttisnumber(r)) /* both operands are numbers? */ + return LEnum(l, r); else if (ttisstring(l) && ttisstring(r)) /* both are strings? */ return l_strcmp(tsvalue(l), tsvalue(r)) <= 0; - else if ((res = luaT_callorderTM(L, l, r, TM_LE)) >= 0) /* first try 'le' */ + else if ((res = luaT_callorderTM(L, l, r, TM_LE)) >= 0) /* try 'le' */ return res; - else if ((res = luaT_callorderTM(L, r, l, TM_LT)) < 0) /* else try 'lt' */ - luaG_ordererror(L, l, r); - return !res; + else { /* try 'lt': */ + L->ci->callstatus |= CIST_LEQ; /* mark it is doing 'lt' for 'le' */ + res = luaT_callorderTM(L, r, l, TM_LT); + L->ci->callstatus ^= CIST_LEQ; /* clear mark */ + if (res < 0) + luaG_ordererror(L, l, r); + return !res; /* result is negated */ + } } /* -** Main operation for equality of Lua values; return 't1 == t2'. +** Main operation for equality of Lua values; return 't1 == t2'. ** L == NULL means raw equality (no metamethods) */ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) { @@ -308,10 +397,8 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) { if (ttnov(t1) != ttnov(t2) || ttnov(t1) != LUA_TNUMBER) return 0; /* only numbers can be equal with different variants */ else { /* two numbers with different variants */ - lua_Number n1, n2; /* compare them as floats */ - lua_assert(ttisnumber(t1) && ttisnumber(t2)); - cast_void(tofloat(t1, &n1)); cast_void(tofloat(t2, &n2)); - return luai_numeq(n1, n2); + lua_Integer i1, i2; /* compare them as integers */ + return (tointeger(t1, &i1) && tointeger(t2, &i2) && i1 == i2); } } /* values have same type and same variant */ @@ -354,6 +441,8 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) { #define tostring(L,o) \ (ttisstring(o) || (cvt2str(o) && (luaO_tostring(L, o), 1))) +#define isemptystr(o) (ttisshrstring(o) && tsvalue(o)->shrlen == 0) + /* ** Main operation for concatenation: concat 'total' values in the stack, ** from 'L->top - total' up to 'L->top - 1'. @@ -365,19 +454,19 @@ void luaV_concat (lua_State *L, int total) { int n = 2; /* number of elements handled in this pass (at least 2) */ if (!(ttisstring(top-2) || cvt2str(top-2)) || !tostring(L, top-1)) luaT_trybinTM(L, top-2, top-1, top-2, TM_CONCAT); - else if (tsvalue(top-1)->len == 0) /* second operand is empty? */ + else if (isemptystr(top - 1)) /* second operand is empty? */ cast_void(tostring(L, top - 2)); /* result is first operand */ - else if (ttisstring(top-2) && tsvalue(top-2)->len == 0) { + else if (isemptystr(top - 2)) { /* first operand is an empty string? */ setobjs2s(L, top - 2, top - 1); /* result is second op. */ } else { /* at least two non-empty string values; get as many as possible */ - size_t tl = tsvalue(top-1)->len; + size_t tl = vslen(top - 1); char *buffer; int i; /* collect total length */ for (i = 1; i < total && tostring(L, top-i-1); i++) { - size_t l = tsvalue(top-i-1)->len; + size_t l = vslen(top - i - 1); if (l >= (MAX_SIZE/sizeof(char)) - tl) luaG_runerror(L, "string length overflow"); tl += l; @@ -386,7 +475,7 @@ void luaV_concat (lua_State *L, int total) { tl = 0; n = i; do { /* copy all strings to buffer */ - size_t l = tsvalue(top-i)->len; + size_t l = vslen(top - i); memcpy(buffer+tl, svalue(top-i), l * sizeof(char)); tl += l; } while (--i > 0); @@ -403,7 +492,7 @@ void luaV_concat (lua_State *L, int total) { */ void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) { const TValue *tm; - switch (ttnov(rb)) { + switch (ttype(rb)) { case LUA_TTABLE: { Table *h = hvalue(rb); tm = fasttm(L, h->metatable, TM_LEN); @@ -411,8 +500,12 @@ void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) { setivalue(ra, luaH_getn(h)); /* else primitive len */ return; } - case LUA_TSTRING: { - setivalue(ra, tsvalue(rb)->len); + case LUA_TSHRSTR: { + setivalue(ra, tsvalue(rb)->shrlen); + return; + } + case LUA_TLNGSTR: { + setivalue(ra, tsvalue(rb)->u.lnglen); return; } default: { /* try metamethod */ @@ -448,7 +541,7 @@ lua_Integer luaV_div (lua_State *L, lua_Integer m, lua_Integer n) { /* -** Integer modulus; return 'm % n'. (Assume that C '%' with +** Integer modulus; return 'm % n'. (Assume that C '%' with ** negative operands follows C99 behavior. See previous comment ** about luaV_div.) */ @@ -553,11 +646,11 @@ void luaV_finishOp (lua_State *L) { case OP_LE: case OP_LT: case OP_EQ: { int res = !l_isfalse(L->top - 1); L->top--; - /* metamethod should not be called when operand is K */ - lua_assert(!ISK(GETARG_B(inst))); - if (op == OP_LE && /* "<=" using "<" instead? */ - ttisnil(luaT_gettmbyobj(L, base + GETARG_B(inst), TM_LE))) - res = !res; /* invert result */ + if (ci->callstatus & CIST_LEQ) { /* "<=" using "<" instead? */ + lua_assert(op == OP_LE); + ci->callstatus ^= CIST_LEQ; /* clear mark */ + res = !res; /* negate result */ + } lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP); if (res != GETARG_A(inst)) /* condition failed? */ ci->u.l.savedpc++; /* skip jump instruction */ @@ -607,7 +700,7 @@ void luaV_finishOp (lua_State *L) { ** some macros for common tasks in 'luaV_execute' */ -#if !defined luai_runtimecheck +#if !defined(luai_runtimecheck) #define luai_runtimecheck(L, c) /* void */ #endif @@ -743,7 +836,7 @@ void luaV_execute (lua_State *L) { Protect(luaV_gettable(L, rb, RKC(i), ra)); vmbreak; } - vmcase(OP_ADD) { + vmcase(OP_ADD) { TValue *rb = RKB(i); TValue *rc = RKC(i); lua_Number nb; lua_Number nc; @@ -928,7 +1021,7 @@ void luaV_execute (lua_State *L) { L->top = base + c + 1; /* mark the end of concat operands */ Protect(luaV_concat(L, c - b + 1)); ra = RA(i); /* 'luav_concat' may invoke TMs and move the stack */ - rb = b + base; + rb = base + b; setobjs2s(L, ra, rb); checkGC(L, (ra >= rb ? ra + 1 : rb)); L->top = ci->top; /* restore top */ @@ -1031,9 +1124,8 @@ void luaV_execute (lua_State *L) { } vmcase(OP_RETURN) { int b = GETARG_B(i); - if (b != 0) L->top = ra+b-1; if (cl->p->sizep > 0) luaF_close(L, base); - b = luaD_poscall(L, ra); + b = luaD_poscall(L, ra, (b != 0 ? b - 1 : L->top - ra)); if (!(ci->callstatus & CIST_REENTRY)) /* 'ci' still the called one */ return; /* external invocation: return */ else { /* invocation via reentry: continue execution */ @@ -1051,7 +1143,7 @@ void luaV_execute (lua_State *L) { lua_Integer limit = ivalue(ra + 1); if ((0 < step) ? (idx <= limit) : (limit <= idx)) { ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ - setivalue(ra, idx); /* update internal index... */ + chgivalue(ra, idx); /* update internal index... */ setivalue(ra + 3, idx); /* ...and external index */ } } @@ -1062,7 +1154,7 @@ void luaV_execute (lua_State *L) { if (luai_numlt(0, step) ? luai_numle(idx, limit) : luai_numle(limit, idx)) { ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ - setfltvalue(ra, idx); /* update internal index... */ + chgfltvalue(ra, idx); /* update internal index... */ setfltvalue(ra + 3, idx); /* ...and external index */ } } @@ -1,5 +1,5 @@ /* -** $Id: lvm.h,v 2.34 2014/08/01 17:24:02 roberto Exp $ +** $Id: lvm.h,v 2.35 2015/02/20 14:27:53 roberto Exp $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -27,11 +27,21 @@ #endif +/* +** You can define LUA_FLOORN2I if you want to convert floats to integers +** by flooring them (instead of raising an error if they are not +** integral values) +*/ +#if !defined(LUA_FLOORN2I) +#define LUA_FLOORN2I 0 +#endif + + #define tonumber(o,n) \ (ttisfloat(o) ? (*(n) = fltvalue(o), 1) : luaV_tonumber_(o,n)) #define tointeger(o,i) \ - (ttisinteger(o) ? (*(i) = ivalue(o), 1) : luaV_tointeger_(o,i)) + (ttisinteger(o) ? (*(i) = ivalue(o), 1) : luaV_tointeger(o,i,LUA_FLOORN2I)) #define intop(op,v1,v2) l_castU2S(l_castS2U(v1) op l_castS2U(v2)) @@ -42,7 +52,7 @@ LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2); LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r); LUAI_FUNC int luaV_tonumber_ (const TValue *obj, lua_Number *n); -LUAI_FUNC int luaV_tointeger_ (const TValue *obj, lua_Integer *p); +LUAI_FUNC int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode); LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val); LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, |